+ * @version $Revision: 3328 $
+ * $Id: Sys.java 3328 2010-04-15 18:03:54Z matzon $
+ */
+public final class Sys {
+ /** The native library name */
+ private static final String JNI_LIBRARY_NAME = "lwjgl";
+
+ /** Current version of library */
+ private static final String VERSION = "2.4.2";
+
+ /** The implementation instance to delegate platform specific behavior to */
+ private final static SysImplementation implementation;
+
+ private final static String POSTFIX64BIT = "64";
+
+ private static void doLoadLibrary(final String lib_name) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ String library_path = System.getProperty("org.lwjgl.librarypath");
+ if (library_path != null) {
+ System.load(library_path + File.separator +
+ System.mapLibraryName(lib_name));
+ } else {
+ System.loadLibrary(lib_name);
+ }
+ return null;
+ }
+ });
+ }
+
+ private static void loadLibrary(final String lib_name) {
+ try {
+ doLoadLibrary(lib_name);
+ } catch (UnsatisfiedLinkError e) {
+ if (implementation.has64Bit()) {
+ try {
+ doLoadLibrary(lib_name + POSTFIX64BIT);
+ return;
+ } catch (UnsatisfiedLinkError e2) {
+ LWJGLUtil.log("Failed to load 64 bit library: " + e2.getMessage());
+ }
+ }
+ // Throw original error
+ throw e;
+ }
+ }
+
+ static {
+ implementation = createImplementation();
+ loadLibrary(JNI_LIBRARY_NAME);
+
+ int native_jni_version = implementation.getJNIVersion();
+ int required_version = implementation.getRequiredJNIVersion();
+ if (native_jni_version != required_version)
+ throw new LinkageError("Version mismatch: jar version is '" + required_version +
+ "', native libary version is '" + native_jni_version + "'");
+ implementation.setDebug(LWJGLUtil.DEBUG);
+ }
+
+ private static SysImplementation createImplementation() {
+ switch (LWJGLUtil.getPlatform()) {
+ case LWJGLUtil.PLATFORM_LINUX:
+ return new LinuxSysImplementation();
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ return new WindowsSysImplementation();
+ case LWJGLUtil.PLATFORM_MACOSX:
+ return new MacOSXSysImplementation();
+ default:
+ throw new IllegalStateException("Unsupported platform");
+ }
+ }
+
+ /**
+ * No constructor for Sys.
+ */
+ private Sys() {
+ }
+
+ /**
+ * Return the version of the core LWJGL libraries as a String.
+ */
+ public static String getVersion() {
+ return VERSION;
+ }
+
+ /**
+ * Initialization. This is just a dummy method to trigger the static constructor.
+ */
+ public static void initialize() {
+ }
+
+ /**
+ * Obtains the number of ticks that the hires timer does in a second. This method is fast;
+ * it should be called as frequently as possible, as it recalibrates the timer.
+ *
+ * @return timer resolution in ticks per second or 0 if no timer is present.
+ */
+ public static long getTimerResolution() {
+ return implementation.getTimerResolution();
+ }
+
+ /**
+ * Gets the current value of the hires timer, in ticks. When the Sys class is first loaded
+ * the hires timer is reset to 0. If no hires timer is present then this method will always
+ * return 0.NOTEZ BIEN that the hires timer WILL wrap around.
+ *
+ * @return the current hires time, in ticks (always >= 0)
+ */
+ public static long getTime() {
+ return implementation.getTime() & 0x7FFFFFFFFFFFFFFFL;
+ }
+
+ /**
+ * Attempt to display a modal alert to the user. This method should be used
+ * when a game fails to initialize properly or crashes out losing its display
+ * in the process. It is provided because AWT may not be available on the target
+ * platform, although on Mac and Linux and other platforms supporting AWT we
+ * delegate the task to AWT instead of doing it ourselves.
+ *
+ * The alert should display the title and the message and then the current
+ * thread should block until the user dismisses the alert - typically with an
+ * OK button click.
+ *
+ * It may be that the user's system has no windowing system installed for some
+ * reason, in which case this method may do nothing at all, or attempt to provide
+ * some console output.
+ *
+ * @param title The title of the alert. We suggest using the title of your game.
+ * @param message The message text for the alert.
+ */
+ public static void alert(String title, String message) {
+ boolean grabbed = Mouse.isGrabbed();
+ if (grabbed) {
+ Mouse.setGrabbed(false);
+ }
+ if (title == null)
+ title = "";
+ if (message == null)
+ message = "";
+ implementation.alert(title, message);
+ if (grabbed) {
+ Mouse.setGrabbed(true);
+ }
+ }
+
+ /**
+ * Open the system web browser and point it at the specified URL. It is recommended
+ * that this not be called whilst your game is running, but on application exit in
+ * a shutdown hook, as the screen resolution will not be reset when the browser is
+ * brought into view.
+ *
+ * There is no guarantee that this will work, nor that we can detect if it has
+ * failed - hence we don't return success code or throw an Exception. This is just a
+ * best attempt at opening the URL given - don't rely on it to work!
+ *
+ * @param url The URL. Ensure that the URL is properly encoded.
+ * @return false if we are CERTAIN the call has failed
+ */
+ public static boolean openURL(String url) {
+ // Attempt to use Webstart if we have it available
+ try {
+ // Lookup the javax.jnlp.BasicService object
+ final Class serviceManagerClass = Class.forName("javax.jnlp.ServiceManager");
+ Method lookupMethod = (Method)AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return serviceManagerClass.getMethod("lookup", new Class[] {String.class});
+ }
+ });
+ Object basicService = lookupMethod.invoke(serviceManagerClass, new Object[] {"javax.jnlp.BasicService"});
+ final Class basicServiceClass = Class.forName("javax.jnlp.BasicService");
+ Method showDocumentMethod = (Method)AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return basicServiceClass.getMethod("showDocument", new Class[] {URL.class});
+ }
+ });
+ try {
+ Boolean ret = (Boolean) showDocumentMethod.invoke(basicService, new Object[] {new URL(url)});
+ return ret.booleanValue();
+ } catch (MalformedURLException e) {
+ e.printStackTrace(System.err);
+ return false;
+ }
+ } catch (Exception ue) {
+ return implementation.openURL(url);
+ }
+ }
+
+ /**
+ * Get the contents of the system clipboard. The system might not have a
+ * clipboard (particularly if it doesn't even have a keyboard) in which case
+ * we return null. Otherwise we return a String, which may be the empty
+ * string "".
+ *
+ * @return a String, or null if there is no system clipboard.
+ */
+ public static String getClipboard() {
+ return implementation.getClipboard();
+ }
+}
diff --git a/src/java/org/lwjgl/SysImplementation.java b/src/java/org/lwjgl/SysImplementation.java
new file mode 100644
index 0000000..10a1c7b
--- /dev/null
+++ b/src/java/org/lwjgl/SysImplementation.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ *
+ * System class platform specific method interface
+ *
+ * @author cix_foo
+ * @author elias_naur
+ * @version $Revision: 3054 $
+ * $Id: SysImplementation.java 3054 2008-04-30 14:34:54Z elias_naur $
+ */
+interface SysImplementation {
+ /**
+ * Return the required version of the native library
+ */
+ int getRequiredJNIVersion();
+
+ /**
+ * Return the version of the native library
+ */
+ int getJNIVersion();
+
+ void setDebug(boolean debug);
+
+ /**
+ * Obtains the number of ticks that the hires timer does in a second.
+ *
+ * @return timer resolution in ticks per second or 0 if no timer is present.
+ */
+ long getTimerResolution();
+
+ long getTime();
+
+ void alert(String title, String message);
+
+ boolean openURL(String url);
+
+ String getClipboard();
+
+ /**
+ * Returns true there exists a separate 64 bit library
+ * on the platform
+ */
+ boolean has64Bit();
+}
diff --git a/src/java/org/lwjgl/WindowsSysImplementation.java b/src/java/org/lwjgl/WindowsSysImplementation.java
new file mode 100644
index 0000000..0c9cac9
--- /dev/null
+++ b/src/java/org/lwjgl/WindowsSysImplementation.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.security.AccessController;
+import java.lang.reflect.Method;
+
+import org.lwjgl.opengl.Display;
+
+/**
+ *
+ * @author $Author: spasi $
+ * @version $Revision: 3300 $
+ * $Id: WindowsSysImplementation.java 3300 2010-03-31 20:56:07Z spasi $
+ */
+final class WindowsSysImplementation extends DefaultSysImplementation {
+ private final static int JNI_VERSION = 22;
+
+ static {
+ Sys.initialize();
+ }
+
+ public int getRequiredJNIVersion() {
+ return JNI_VERSION;
+ }
+
+ public long getTimerResolution() {
+ return 1000;
+ }
+
+ public long getTime() {
+ return nGetTime();
+ }
+ private static native long nGetTime();
+
+ public final boolean has64Bit() {
+ return true;
+ }
+
+ private static long getHwnd() {
+ if (!Display.isCreated())
+ return 0;
+ /* Use reflection since we can't make Display.getImplementation
+ * public
+ */
+ try {
+ Long hwnd_obj = (Long)AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ Method getImplementation_method = Display.class.getDeclaredMethod("getImplementation", null);
+ getImplementation_method.setAccessible(true);
+ Object display_impl = getImplementation_method.invoke(null, null);
+ Class WindowsDisplay_class = Class.forName("org.lwjgl.opengl.WindowsDisplay");
+ Method getHwnd_method = WindowsDisplay_class.getDeclaredMethod("getHwnd", null);
+ getHwnd_method.setAccessible(true);
+ Long hwnd = (Long)getHwnd_method.invoke(display_impl, null);
+ return hwnd;
+ }
+ });
+ return hwnd_obj.longValue();
+ } catch (PrivilegedActionException e) {
+ throw new Error(e);
+ }
+ }
+
+ public void alert(String title, String message) {
+ if(!Display.isCreated()) {
+ initCommonControls();
+ }
+ nAlert(getHwnd(), title, message);
+ }
+ private static native void nAlert(long parent_hwnd, String title, String message);
+ private static native void initCommonControls();
+
+ public boolean openURL(final String url) {
+ try {
+ LWJGLUtil.execPrivileged(new String[]{"rundll32", "url.dll,FileProtocolHandler", url});
+ return true;
+ } catch (Exception e) {
+ LWJGLUtil.log("Failed to open url (" + url + "): " + e.getMessage());
+ return false;
+ }
+ }
+
+ public String getClipboard() {
+ return nGetClipboard();
+ }
+ private static native String nGetClipboard();
+}
diff --git a/src/java/org/lwjgl/examples/Game.java b/src/java/org/lwjgl/examples/Game.java
new file mode 100644
index 0000000..8dc2147
--- /dev/null
+++ b/src/java/org/lwjgl/examples/Game.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2002-2008 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.examples;
+
+import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.openal.AL;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+
+/**
+ *
+ * This is a very basic skeleton to init a game and run it.
+ *
+ * @author $Author: matzon $
+ * @version $Revision: 3108 $
+ * $Id: Game.java 3108 2008-07-02 20:00:49Z matzon $
+ */
+public class Game {
+
+ /** Game title */
+ public static final String GAME_TITLE = "My Game";
+
+ /** Desired frame time */
+ private static final int FRAMERATE = 60;
+
+ /** Exit the game */
+ private static boolean finished;
+
+ /** A rotating square! */
+ private static float angle;
+
+ /**
+ * No constructor needed - this class is static
+ */
+ private Game() {}
+
+ /**
+ * Application init
+ * @param args Commandline args
+ */
+ public static void main(String[] args) {
+ try {
+ init();
+ run();
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ Sys.alert(GAME_TITLE, "An error occured and the game will exit.");
+ } finally {
+ cleanup();
+ }
+
+ System.exit(0);
+ }
+
+ /**
+ * Initialise the game
+ * @throws Exception if init fails
+ */
+ private static void init() throws Exception {
+ // Create a fullscreen window with 1:1 orthographic 2D projection, and with
+ // mouse, keyboard, and gamepad inputs.
+ Display.setTitle(GAME_TITLE);
+ Display.setFullscreen(true);
+
+ // Enable vsync if we can
+ Display.setVSyncEnabled(true);
+
+ Display.create();
+
+ // Start up the sound system
+ AL.create();
+
+ // TODO: Load in your textures etc here
+
+ // Put the window into orthographic projection mode with 1:1 pixel ratio.
+ // We haven't used GLU here to do this to avoid an unnecessary dependency.
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GL11.glOrtho(0.0, Display.getDisplayMode().getWidth(), 0.0, Display.getDisplayMode().getHeight(), -1.0, 1.0);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
+
+ }
+
+ /**
+ * Runs the game (the "main loop")
+ */
+ private static void run() {
+ while (!finished) {
+ // Always call Window.update(), all the time
+ Display.update();
+
+ if (Display.isCloseRequested()) {
+ // Check for O/S close requests
+ finished = true;
+ } else if (Display.isActive()) {
+ // The window is in the foreground, so we should play the game
+ logic();
+ render();
+ Display.sync(FRAMERATE);
+ } else {
+ // The window is not in the foreground, so we can allow other stuff to run and
+ // infrequently update
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ logic();
+ if (Display.isVisible() || Display.isDirty()) {
+ // Only bother rendering if the window is visible or dirty
+ render();
+ }
+ }
+ }
+ }
+
+ /**
+ * Do any game-specific cleanup
+ */
+ private static void cleanup() {
+ // TODO: save anything you want to disk here
+
+ // Stop the sound
+ AL.destroy();
+
+ // Close the window
+ Display.destroy();
+ }
+
+ /**
+ * Do all calculations, handle input, etc.
+ */
+ private static void logic() {
+ // Example input handler: we'll check for the ESC key and finish the game instantly when it's pressed
+ if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
+ finished = true;
+ }
+
+ // TODO: all your game logic goes here.
+ angle += 2.0f % 360;
+ }
+
+ /**
+ * Render the current frame
+ */
+ private static void render() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
+
+ // TODO: all your rendering goes here
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ GL11.glPushMatrix();
+ GL11.glTranslatef(Display.getDisplayMode().getWidth() / 2, Display.getDisplayMode().getHeight() / 2, 0.0f);
+ GL11.glRotatef(angle, 0, 0, 1.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ GL11.glVertex2i(-50, -50);
+ GL11.glVertex2i(50, -50);
+ GL11.glVertex2i(50, 50);
+ GL11.glVertex2i(-50, 50);
+ GL11.glEnd();
+ GL11.glPopMatrix();
+ }
+}
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/AlienEntity.java b/src/java/org/lwjgl/examples/spaceinvaders/AlienEntity.java
new file mode 100644
index 0000000..f1db4b7
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/AlienEntity.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+/**
+ * An entity which represents one of our space invader aliens.
+ *
+ * @author Kevin Glass
+ * @author Brian Matzon
+ */
+public class AlienEntity extends Entity {
+
+ /** Movement made downwards when a border is hit */
+ private static final int DOWNWARD_MOVEMENT = 10;
+
+ /** Border at which player dies */
+ private static final int BOTTOM_BORDER = 570;
+
+ /** Right border at which to shift direction */
+ private static final int RIGHT_BORDER = 750;
+
+ /** Left border at which to shift direction */
+ private static final int LEFT_BORDER = 10;
+
+ /** The speed at which the alient moves horizontally */
+ private float moveSpeed = 75;
+
+ /** The game in which the entity exists */
+ private Game game;
+
+ /** The animation frames */
+ private Sprite[] frames = new Sprite[4];
+
+ /** The time since the last frame change took place */
+ private long lastFrameChange;
+
+ /** The frame duration in milliseconds, i.e. how long any given frame of animation lasts */
+ private long frameDuration = 250;
+
+ /** The current frame of animation being displayed */
+ private int frameNumber;
+
+ /**
+ * Create a new alien entity
+ *
+ * @param game The game in which this entity is being created
+ * @param x The intial x location of this alien
+ * @param y The intial y location of this alient
+ */
+ public AlienEntity(Game game, int x, int y) {
+ super(game.getSprite("alien.gif"), x, y);
+
+ // setup the animatin frames
+ frames[0] = sprite;
+ frames[1] = game.getSprite("alien2.gif");
+ frames[2] = sprite;
+ frames[3] = game.getSprite("alien3.gif");
+
+ this.game = game;
+ dx = -moveSpeed;
+ }
+
+ /**
+ * Request that this alien moved based on time elapsed
+ *
+ * @param delta The time that has elapsed since last move
+ */
+ public void move(long delta) {
+ // since the move tells us how much time has passed
+ // by we can use it to drive the animation, however
+ // its the not the prettiest solution
+ lastFrameChange += delta;
+
+ // if we need to change the frame, update the frame number
+ // and flip over the sprite in use
+ if (lastFrameChange > frameDuration) {
+ // reset our frame change time counter
+ lastFrameChange = 0;
+
+ // update the frame
+ frameNumber++;
+ if (frameNumber >= frames.length) {
+ frameNumber = 0;
+ }
+
+ sprite = frames[frameNumber];
+ }
+
+ // if we have reached the left hand side of the screen and
+ // are moving left then request a logic update
+ if ((dx < 0) && (x < LEFT_BORDER)) {
+ game.updateLogic();
+ }
+ // and vice vesa, if we have reached the right hand side of
+ // the screen and are moving right, request a logic update
+ if ((dx > 0) && (x > RIGHT_BORDER)) {
+ game.updateLogic();
+ }
+
+ // proceed with normal move
+ super.move(delta);
+ }
+
+ /**
+ * Update the game logic related to aliens
+ */
+ public void doLogic() {
+ // swap over horizontal movement and move down the
+ // screen a bit
+ dx = -dx;
+ y += DOWNWARD_MOVEMENT;
+
+ // if we've reached the bottom of the screen then the player
+ // dies
+ if (y > BOTTOM_BORDER) {
+ game.notifyDeath();
+ }
+ }
+
+ /**
+ * Notification that this alien has collided with another entity
+ *
+ * @param other The other entity
+ */
+ public void collidedWith(Entity other) {
+ // collisions with aliens are handled elsewhere
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/Entity.java b/src/java/org/lwjgl/examples/spaceinvaders/Entity.java
new file mode 100644
index 0000000..cfc54ed
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/Entity.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+import java.awt.Rectangle;
+
+/**
+ * An entity represents any element that appears in the game. The
+ * entity is responsible for resolving collisions and movement
+ * based on a set of properties defined either by subclass or externally.
+ *
+ * Note that doubles are used for positions. This may seem strange
+ * given that pixels locations are integers. However, using double means
+ * that an entity can move a partial pixel. It doesn't of course mean that
+ * they will be display half way through a pixel but allows us not lose
+ * accuracy as we move.
+ *
+ * @author Kevin Glass
+ */
+public abstract class Entity {
+
+ /** The current x location of this entity */
+ protected float x;
+
+ /** The current y location of this entity */
+ protected float y;
+
+ /** The sprite that represents this entity */
+ protected Sprite sprite;
+
+ /** The current speed of this entity horizontally (pixels/sec) */
+ protected float dx;
+
+ /** The current speed of this entity vertically (pixels/sec) */
+ protected float dy;
+
+ /** The rectangle used for this entity during collisions resolution */
+ private Rectangle me = new Rectangle();
+
+ /** The rectangle used for other entities during collision resolution */
+ private Rectangle him = new Rectangle();
+
+ /**
+ * Construct a entity based on a sprite image and a location.
+ *
+ * @param ref The reference to the image to be displayed for this entity
+ * @param x The initial x location of this entity
+ * @param y The initial y location of this entity
+ */
+ public Entity(Sprite sprite, int x, int y) {
+ this.sprite = sprite;
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Request that this entity move itself based on a certain ammount
+ * of time passing.
+ *
+ * @param delta The ammount of time that has passed in milliseconds
+ */
+ public void move(long delta) {
+ // update the location of the entity based on move speeds
+ x += (delta * dx) / 1000;
+ y += (delta * dy) / 1000;
+ }
+
+ /**
+ * Set the horizontal speed of this entity
+ *
+ * @param dx The horizontal speed of this entity (pixels/sec)
+ */
+ public void setHorizontalMovement(float dx) {
+ this.dx = dx;
+ }
+
+ /**
+ * Set the vertical speed of this entity
+ *
+ * @param dy The vertical speed of this entity (pixels/sec)
+ */
+ public void setVerticalMovement(float dy) {
+ this.dy = dy;
+ }
+
+ /**
+ * Get the horizontal speed of this entity
+ *
+ * @return The horizontal speed of this entity (pixels/sec)
+ */
+ public float getHorizontalMovement() {
+ return dx;
+ }
+
+ /**
+ * Get the vertical speed of this entity
+ *
+ * @return The vertical speed of this entity (pixels/sec)
+ */
+ public float getVerticalMovement() {
+ return dy;
+ }
+
+ /**
+ * Draw this entity to the graphics context provided
+ */
+ public void draw() {
+ sprite.draw((int) x, (int) y);
+ }
+
+ /**
+ * Do the logic associated with this entity. This method
+ * will be called periodically based on game events
+ */
+ public void doLogic() {
+ }
+
+ /**
+ * Get the x location of this entity
+ *
+ * @return The x location of this entity
+ */
+ public int getX() {
+ return (int) x;
+ }
+
+ /**
+ * Get the y location of this entity
+ *
+ * @return The y location of this entity
+ */
+ public int getY() {
+ return (int) y;
+ }
+
+ /**
+ * Check if this entity collised with another.
+ *
+ * @param other The other entity to check collision against
+ * @return True if the entities collide with each other
+ */
+ public boolean collidesWith(Entity other) {
+ me.setBounds((int) x, (int) y, sprite.getWidth(), sprite.getHeight());
+ him.setBounds((int) other.x, (int) other.y, other.sprite.getWidth(), other.sprite.getHeight());
+
+ return me.intersects(him);
+ }
+
+ /**
+ * Notification that this entity collided with another.
+ *
+ * @param other The entity with which this entity collided.
+ */
+ public abstract void collidedWith(Entity other);
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/Game.java b/src/java/org/lwjgl/examples/spaceinvaders/Game.java
new file mode 100644
index 0000000..f4c9e29
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/Game.java
@@ -0,0 +1,614 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+import java.util.ArrayList;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+
+/**
+ * The main hook of our game. This class with both act as a manager
+ * for the display and central mediator for the game logic.
+ *
+ * Display management will consist of a loop that cycles round all
+ * entities in the game asking them to move and then drawing them
+ * in the appropriate place. With the help of an inner class it
+ * will also allow the player to control the main ship.
+ *
+ * As a mediator it will be informed when entities within our game
+ * detect events (e.g. alient killed, played died) and will take
+ * appropriate game actions.
+ *
+ *
+ * NOTE:
+ * This game is a LWJGLized implementation of the Space Invaders game by Kevin
+ * Glass. The original implementation is renderer agnostic and supports other
+ * OpenGL implementations as well as Java2D. This version has been made specific
+ * for LWJGL, and has added input control as well as sound (which the original doesn't,
+ * at the time of writing).
+ * You can find the original article here:
+ * http://www.cokeandcode.com
+ *
+ *
+ * @author Kevin Glass
+ * @author Brian Matzon
+ */
+public class Game {
+
+ /** The normal title of the window */
+ private String WINDOW_TITLE = "Space Invaders 104 (for LWJGL)";
+
+ /** The width of the game display area */
+ private int width = 800;
+
+ /** The height of the game display area */
+ private int height = 600;
+
+ /** The loader responsible for converting images into OpenGL textures */
+ private TextureLoader textureLoader;
+
+ /** The list of all the entities that exist in our game */
+ private ArrayList entities = new ArrayList();
+
+ /** The list of entities that need to be removed from the game this loop */
+ private ArrayList removeList = new ArrayList();
+
+ /** The entity representing the player */
+ private ShipEntity ship;
+
+ /** List of shots */
+ private ShotEntity[] shots;
+
+ /** The message to display which waiting for a key press */
+ private Sprite message;
+
+ /** The sprite containing the "Press Any Key" message */
+ private Sprite pressAnyKey;
+
+ /** The sprite containing the "You win!" message */
+ private Sprite youWin;
+
+ /** The sprite containing the "You lose!" message */
+ private Sprite gotYou;
+
+ /** Last shot index */
+ private int shotIndex;
+
+ /** The speed at which the player's ship should move (pixels/sec) */
+ private float moveSpeed = 300;
+
+ /** The time at which last fired a shot */
+ private long lastFire = 0;
+
+ /** The interval between our players shot (ms) */
+ private long firingInterval = 500;
+
+ /** The number of aliens left on the screen */
+ private int alienCount;
+
+ /** True if we're holding up game play until a key has been pressed */
+ private boolean waitingForKeyPress = true;
+
+ /** True if game logic needs to be applied this loop, normally as a result of a game event */
+ private boolean logicRequiredThisLoop = false;
+
+ /** The time at which the last rendering looped started from the point of view of the game logic */
+ private long lastLoopTime = getTime();
+
+ /** True if the fire key has been released */
+ private boolean fireHasBeenReleased = false;
+
+ /** The time since the last record of fps */
+ private long lastFpsTime = 0;
+
+ /** The recorded fps */
+ private int fps;
+
+ private static long timerTicksPerSecond = Sys.getTimerResolution();
+
+ /** True if the game is currently "running", i.e. the game loop is looping */
+ public static boolean gameRunning = true;
+
+ /** SoundManager to make sound with */
+ private SoundManager soundManager;
+
+ /** Whether we're running in fullscreen mode */
+ private boolean fullscreen;
+
+ /** ID of shot effect */
+ private int SOUND_SHOT;
+
+ /** ID of hit effect */
+ private int SOUND_HIT;
+
+ /** ID of start sound */
+ private int SOUND_START;
+
+ /** ID of win sound */
+ private int SOUND_WIN;
+
+ /** ID of loose sound */
+ private int SOUND_LOOSE;
+
+ /** Mouse movement on x axis */
+ private int mouseX;
+
+ /** Is this an application or applet */
+ private static boolean isApplication = false;
+
+ /**
+ * Construct our game and set it running.
+ * @param fullscreen
+ *
+ * @param renderingType The type of rendering to use (should be one of the contansts from ResourceFactory)
+ */
+ public Game(boolean fullscreen) {
+ this.fullscreen = fullscreen;
+ initialize();
+ }
+
+ /**
+ * Get the high resolution time in milliseconds
+ *
+ * @return The high resolution time in milliseconds
+ */
+ public static long getTime() {
+ // we get the "timer ticks" from the high resolution timer
+ // multiply by 1000 so our end result is in milliseconds
+ // then divide by the number of ticks in a second giving
+ // us a nice clear time in milliseconds
+ return (Sys.getTime() * 1000) / timerTicksPerSecond;
+ }
+
+ /**
+ * Sleep for a fixed number of milliseconds.
+ *
+ * @param duration The amount of time in milliseconds to sleep for
+ */
+ public static void sleep(long duration) {
+ try {
+ Thread.sleep((duration * timerTicksPerSecond) / 1000);
+ } catch (InterruptedException inte) {
+ }
+ }
+
+ /**
+ * Intialise the common elements for the game
+ */
+ public void initialize() {
+ // initialize the window beforehand
+ try {
+ setDisplayMode();
+ Display.setTitle(WINDOW_TITLE);
+ Display.setFullscreen(fullscreen);
+ Display.create();
+
+ // grab the mouse, dont want that hideous cursor when we're playing!
+ if (isApplication) {
+ Mouse.setGrabbed(true);
+ }
+
+ // enable textures since we're going to use these for our sprites
+ GL11.glEnable(GL11.GL_TEXTURE_2D);
+
+ // disable the OpenGL depth test since we're rendering 2D graphics
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+
+ GL11.glOrtho(0, width, height, 0, -1, 1);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, width, height);
+
+ textureLoader = new TextureLoader();
+
+ // create our sound manager, and initialize it with 7 channels
+ // 1 channel for sounds, 6 for effects - this should be enough
+ // since we have a most 4 shots on screen at any one time, which leaves
+ // us with 2 channels for explosions.
+ soundManager = new SoundManager();
+ soundManager.initialize(8);
+
+ // load our sound data
+ SOUND_SHOT = soundManager.addSound("shot.wav");
+ SOUND_HIT = soundManager.addSound("hit.wav");
+ SOUND_START = soundManager.addSound("start.wav");
+ SOUND_WIN = soundManager.addSound("win.wav");
+ SOUND_LOOSE = soundManager.addSound("loose.wav");
+ } catch (LWJGLException le) {
+ System.out.println("Game exiting - exception in initialization:");
+ le.printStackTrace();
+ Game.gameRunning = false;
+ return;
+ }
+
+ // get our sprites
+ gotYou = getSprite("gotyou.gif");
+ pressAnyKey = getSprite("pressanykey.gif");
+ youWin = getSprite("youwin.gif");
+
+ message = pressAnyKey;
+
+ // setup 5 shots
+ shots = new ShotEntity[5];
+ for (int i = 0; i < shots.length; i++) {
+ shots[i] = new ShotEntity(this, "shot.gif", 0, 0);
+ }
+
+ // setup the initial game state
+ startGame();
+ }
+
+ /**
+ * Sets the display mode for fullscreen mode
+ */
+ private boolean setDisplayMode() {
+ 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,
+ "freq=" + 60,
+ "bpp=" + org.lwjgl.opengl.Display.getDisplayMode().getBitsPerPixel()
+ });
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("Unable to enter fullscreen, continuing in windowed mode");
+ }
+
+ return false;
+ }
+
+ /**
+ * Start a fresh game, this should clear out any old data and
+ * create a new set.
+ */
+ private void startGame() {
+ // clear out any existing entities and intialise a new set
+ entities.clear();
+ initEntities();
+ }
+
+ /**
+ * Initialise the starting state of the entities (ship and aliens). Each
+ * entitiy will be added to the overall list of entities in the game.
+ */
+ private void initEntities() {
+ // create the player ship and place it roughly in the center of the screen
+ ship = new ShipEntity(this, "ship.gif", 370, 550);
+ entities.add(ship);
+
+ // create a block of aliens (5 rows, by 12 aliens, spaced evenly)
+ alienCount = 0;
+ for (int row = 0; row < 5; row++) {
+ for (int x = 0; x < 12; x++) {
+ Entity alien = new AlienEntity(this, 100 + (x * 50), (50) + row * 30);
+ entities.add(alien);
+ alienCount++;
+ }
+ }
+ }
+
+ /**
+ * Notification from a game entity that the logic of the game
+ * should be run at the next opportunity (normally as a result of some
+ * game event)
+ */
+ public void updateLogic() {
+ logicRequiredThisLoop = true;
+ }
+
+ /**
+ * Remove an entity from the game. The entity removed will
+ * no longer move or be drawn.
+ *
+ * @param entity The entity that should be removed
+ */
+ public void removeEntity(Entity entity) {
+ removeList.add(entity);
+ }
+
+ /**
+ * Notification that the player has died.
+ */
+ public void notifyDeath() {
+ if (!waitingForKeyPress) {
+ soundManager.playSound(SOUND_LOOSE);
+ }
+ message = gotYou;
+ waitingForKeyPress = true;
+ }
+
+ /**
+ * Notification that the player has won since all the aliens
+ * are dead.
+ */
+ public void notifyWin() {
+ message = youWin;
+ waitingForKeyPress = true;
+ soundManager.playSound(SOUND_WIN);
+ }
+
+ /**
+ * Notification that an alien has been killed
+ */
+ public void notifyAlienKilled() {
+ // reduce the alient count, if there are none left, the player has won!
+ alienCount--;
+
+ if (alienCount == 0) {
+ notifyWin();
+ }
+
+ // if there are still some aliens left then they all need to get faster, so
+ // speed up all the existing aliens
+ for (int i = 0; i < entities.size(); i++) {
+ Entity entity = (Entity) entities.get(i);
+
+ if (entity instanceof AlienEntity) {
+ // speed up by 2%
+ entity.setHorizontalMovement(entity.getHorizontalMovement() * 1.02f);
+ }
+ }
+
+ soundManager.playEffect(SOUND_HIT);
+ }
+
+ /**
+ * Attempt to fire a shot from the player. Its called "try"
+ * since we must first check that the player can fire at this
+ * point, i.e. has he/she waited long enough between shots
+ */
+ public void tryToFire() {
+ // check that we have waiting long enough to fire
+ if (System.currentTimeMillis() - lastFire < firingInterval) {
+ return;
+ }
+
+ // if we waited long enough, create the shot entity, and record the time.
+ lastFire = System.currentTimeMillis();
+ ShotEntity shot = shots[shotIndex++ % shots.length];
+ shot.reinitialize(ship.getX() + 10, ship.getY() - 30);
+ entities.add(shot);
+
+ soundManager.playEffect(SOUND_SHOT);
+ }
+
+ /**
+ * Run the main game loop. This method keeps rendering the scene
+ * and requesting that the callback update its screen.
+ */
+ private void gameLoop() {
+ while (Game.gameRunning) {
+ // clear screen
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+
+ // let subsystem paint
+ frameRendering();
+
+ // update window contents
+ Display.update();
+ }
+
+ // clean up
+ soundManager.destroy();
+ Display.destroy();
+ }
+
+ /**
+ * Notification that a frame is being rendered. Responsible for
+ * running game logic and rendering the scene.
+ */
+ public void frameRendering() {
+ //SystemTimer.sleep(lastLoopTime+10-SystemTimer.getTime());
+ Display.sync(60);
+
+ // work out how long its been since the last update, this
+ // will be used to calculate how far the entities should
+ // move this loop
+ long delta = getTime() - lastLoopTime;
+ lastLoopTime = getTime();
+ lastFpsTime += delta;
+ fps++;
+
+ // update our FPS counter if a second has passed
+ if (lastFpsTime >= 1000) {
+ Display.setTitle(WINDOW_TITLE + " (FPS: " + fps + ")");
+ lastFpsTime = 0;
+ fps = 0;
+ }
+
+ // cycle round asking each entity to move itself
+ if (!waitingForKeyPress && !soundManager.isPlayingSound()) {
+ for (int i = 0; i < entities.size(); i++) {
+ Entity entity = (Entity) entities.get(i);
+ entity.move(delta);
+ }
+ }
+
+ // cycle round drawing all the entities we have in the game
+ for (int i = 0; i < entities.size(); i++) {
+ Entity entity = (Entity) entities.get(i);
+ entity.draw();
+ }
+
+ // brute force collisions, compare every entity against
+ // every other entity. If any of them collide notify
+ // both entities that the collision has occured
+ for (int p = 0; p < entities.size(); p++) {
+ for (int s = p + 1; s < entities.size(); s++) {
+ Entity me = (Entity) entities.get(p);
+ Entity him = (Entity) entities.get(s);
+
+ if (me.collidesWith(him)) {
+ me.collidedWith(him);
+ him.collidedWith(me);
+ }
+ }
+ }
+
+ // remove any entity that has been marked for clear up
+ entities.removeAll(removeList);
+ removeList.clear();
+
+ // if a game event has indicated that game logic should
+ // be resolved, cycle round every entity requesting that
+ // their personal logic should be considered.
+ if (logicRequiredThisLoop) {
+ for (int i = 0; i < entities.size(); i++) {
+ Entity entity = (Entity) entities.get(i);
+ entity.doLogic();
+ }
+
+ logicRequiredThisLoop = false;
+ }
+
+ // if we're waiting for an "any key" press then draw the
+ // current message
+ if (waitingForKeyPress) {
+ message.draw(325, 250);
+ }
+
+ // resolve the movemfent of the ship. First assume the ship
+ // isn't moving. If either cursor key is pressed then
+ // update the movement appropraitely
+ ship.setHorizontalMovement(0);
+
+ // get mouse movement on x axis. We need to get it now, since
+ // we can only call getDX ONCE! - secondary calls will yield 0, since
+ // there haven't been any movement since last call.
+ mouseX = Mouse.getDX();
+
+ // we delegate input checking to submethod since we want to check
+ // for keyboard, mouse & controller
+ boolean leftPressed = hasInput(Keyboard.KEY_LEFT);
+ boolean rightPressed = hasInput(Keyboard.KEY_RIGHT);
+ boolean firePressed = hasInput(Keyboard.KEY_SPACE);
+
+ if (!waitingForKeyPress && !soundManager.isPlayingSound()) {
+ if ((leftPressed) && (!rightPressed)) {
+ ship.setHorizontalMovement(-moveSpeed);
+ } else if ((rightPressed) && (!leftPressed)) {
+ ship.setHorizontalMovement(moveSpeed);
+ }
+
+ // if we're pressing fire, attempt to fire
+ if (firePressed) {
+ tryToFire();
+ }
+ } else {
+ if (!firePressed) {
+ fireHasBeenReleased = true;
+ }
+ if ((firePressed) && (fireHasBeenReleased) && !soundManager.isPlayingSound()) {
+ waitingForKeyPress = false;
+ fireHasBeenReleased = false;
+ startGame();
+ soundManager.playSound(SOUND_START);
+ }
+ }
+
+ // if escape has been pressed, stop the game
+ if ((Display.isCloseRequested() || Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) && isApplication) {
+ Game.gameRunning = false;
+ }
+ }
+
+ /**
+ * @param key_left
+ * @return
+ */
+ private boolean hasInput(int direction) {
+ switch(direction) {
+ case Keyboard.KEY_LEFT:
+ return
+ Keyboard.isKeyDown(Keyboard.KEY_LEFT) ||
+ mouseX < 0;
+
+ case Keyboard.KEY_RIGHT:
+ return
+ Keyboard.isKeyDown(Keyboard.KEY_RIGHT) ||
+ mouseX > 0;
+
+ case Keyboard.KEY_SPACE:
+ return
+ Keyboard.isKeyDown(Keyboard.KEY_SPACE) ||
+ Mouse.isButtonDown(0);
+ }
+ return false;
+ }
+
+ /**
+ * The entry point into the game. We'll simply create an
+ * instance of class which will start the display and game
+ * loop.
+ *
+ * @param argv The arguments that are passed into our game
+ */
+ public static void main(String argv[]) {
+ isApplication = true;
+ System.out.println("Use -fullscreen for fullscreen mode");
+ new Game((argv.length > 0 && argv[0].equalsIgnoreCase("-fullscreen"))).execute();
+ System.exit(0);
+ }
+
+ /**
+ *
+ */
+ public void execute() {
+ gameLoop();
+ }
+
+ /**
+ * Create or get a sprite which displays the image that is pointed
+ * to in the classpath by "ref"
+ *
+ * @param ref A reference to the image to load
+ * @return A sprite that can be drawn onto the current graphics context.
+ */
+ public Sprite getSprite(String ref) {
+ return new Sprite(textureLoader, ref);
+ }
+}
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/GameApplet.java b/src/java/org/lwjgl/examples/spaceinvaders/GameApplet.java
new file mode 100644
index 0000000..a1ac0cc
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/GameApplet.java
@@ -0,0 +1,104 @@
+package org.lwjgl.examples.spaceinvaders;
+
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Canvas;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Display;
+
+public class GameApplet extends Applet {
+
+ /** The Canvas where the LWJGL Display is added */
+ Canvas display_parent;
+
+ /** Thread which runs the main game loop */
+ Thread gameThread;
+
+ /** The Game instance */
+ Game game;
+
+ /**
+ * Once the Canvas is created its add notify method will call this method to
+ * start the LWJGL Display and game loop in another thread.
+ */
+ public void startLWJGL() {
+ gameThread = new Thread() {
+ public void run() {
+
+ try {
+ Display.setParent(display_parent);
+
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ }
+ // start game
+ game = new Game(false);
+ game.execute();
+ }
+ };
+ gameThread.start();
+ }
+
+
+ /**
+ * Tell game loop to stop running, after which the LWJGL Display will be destoryed.
+ * The main thread will wait for the Display.destroy() to complete
+ */
+ private void stopLWJGL() {
+ Game.gameRunning = false;
+ try {
+ gameThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void start() {
+
+ }
+
+ public void stop() {
+
+ }
+
+ /**
+ * Applet Destroy method will remove the canvas, before canvas is destroyed it will notify
+ * stopLWJGL() to stop main game loop and to destroy the Display
+ */
+ public void destroy() {
+ remove(display_parent);
+ super.destroy();
+ System.out.println("Clear up");
+ }
+
+ /**
+ * initialise applet by adding a canvas to it, this canvas will start the LWJGL Display and game loop
+ * in another thread. It will also stop the game loop and destroy the display on canvas removal when
+ * applet is destroyed.
+ */
+ public void init() {
+ setLayout(new BorderLayout());
+ try {
+ display_parent = new Canvas() {
+ public final void addNotify() {
+ super.addNotify();
+ startLWJGL();
+ }
+ public final void removeNotify() {
+ stopLWJGL();
+ super.removeNotify();
+ }
+ };
+ display_parent.setSize(getWidth(),getHeight());
+ add(display_parent);
+ display_parent.setFocusable(true);
+ display_parent.requestFocus();
+ display_parent.setIgnoreRepaint(true);
+ setVisible(true);
+ } catch (Exception e) {
+ System.err.println(e);
+ throw new RuntimeException("Unable to create display");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/ShipEntity.java b/src/java/org/lwjgl/examples/spaceinvaders/ShipEntity.java
new file mode 100644
index 0000000..0e33a3b
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/ShipEntity.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+/**
+ * The entity that represents the players ship
+ *
+ * @author Kevin Glass
+ * @author Brian Matzon
+ */
+public class ShipEntity extends Entity {
+
+ /** Right border at which to disallow further movement */
+ private static final int RIGHT_BORDER = 750;
+
+ /** Left border at which to disallow further movement */
+ private static final int LEFT_BORDER = 10;
+
+ /** The game in which the ship exists */
+ private Game game;
+
+ /**
+ * Create a new entity to represent the players ship
+ *
+ * @param game The game in which the ship is being created
+ * @param ref The reference to the sprite to show for the ship
+ * @param x The initial x location of the player's ship
+ * @param y The initial y location of the player's ship
+ */
+ public ShipEntity(Game game,String ref,int x,int y) {
+ super(game.getSprite(ref), x, y);
+
+ this.game = game;
+ }
+
+ /**
+ * Request that the ship move itself based on an elapsed ammount of
+ * time
+ *
+ * @param delta The time that has elapsed since last move (ms)
+ */
+ public void move(long delta) {
+ // if we're moving left and have reached the left hand side
+ // of the screen, don't move
+ if ((dx < 0) && (x < LEFT_BORDER)) {
+ return;
+ }
+ // if we're moving right and have reached the right hand side
+ // of the screen, don't move
+ if ((dx > 0) && (x > RIGHT_BORDER)) {
+ return;
+ }
+
+ super.move(delta);
+ }
+
+ /**
+ * Notification that the player's ship has collided with something
+ *
+ * @param other The entity with which the ship has collided
+ */
+ public void collidedWith(Entity other) {
+ // if its an alien, notify the game that the player
+ // is dead
+ if (other instanceof AlienEntity) {
+ game.notifyDeath();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/ShotEntity.java b/src/java/org/lwjgl/examples/spaceinvaders/ShotEntity.java
new file mode 100644
index 0000000..1d3335e
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/ShotEntity.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+/**
+ * An entity representing a shot fired by the player's ship
+ *
+ * @author Kevin Glass
+ * @author Brian Matzon
+ */
+public class ShotEntity extends Entity {
+
+ /** Top border at which shots are outside */
+ private static final int TOP_BORDER = -100;
+
+ /** The vertical speed at which the players shot moves */
+ private float moveSpeed = -300;
+
+ /** The game in which this entity exists */
+ private Game game;
+
+ /** True if this shot has been "used", i.e. its hit something */
+ private boolean used = false;
+
+ /**
+ * Create a new shot from the player
+ *
+ * @param game The game in which the shot has been created
+ * @param sprite The sprite representing this shot
+ * @param x The initial x location of the shot
+ * @param y The initial y location of the shot
+ */
+ public ShotEntity(Game game, String sprite, int x, int y) {
+ super(game.getSprite(sprite), x, y);
+
+ this.game = game;
+ dy = moveSpeed;
+ }
+
+ /**
+ * Reinitializes this entity, for reuse
+ *
+ * @param x new x coordinate
+ * @param y new y coordinate
+ */
+ public void reinitialize(int x, int y) {
+ this.x = x;
+ this.y = y;
+ used = false;
+ }
+
+ /**
+ * Request that this shot moved based on time elapsed
+ *
+ * @param delta The time that has elapsed since last move
+ */
+ public void move(long delta) {
+ // proceed with normal move
+ super.move(delta);
+
+ // if we shot off the screen, remove ourselfs
+ if (y < TOP_BORDER) {
+ game.removeEntity(this);
+ }
+ }
+
+ /**
+ * Notification that this shot has collided with another
+ * entity
+ *
+ * @param other The other entity with which we've collided
+ */
+ public void collidedWith(Entity other) {
+ // prevents double kills, if we've already hit something,
+ // don't collide
+ if (used) {
+ return;
+ }
+
+ // if we've hit an alien, kill it!
+ if (other instanceof AlienEntity) {
+ // remove the affected entities
+ game.removeEntity(this);
+ game.removeEntity(other);
+
+ // notify the game that the alien has been killed
+ game.notifyAlienKilled();
+ used = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/SoundManager.java b/src/java/org/lwjgl/examples/spaceinvaders/SoundManager.java
new file mode 100644
index 0000000..d3bcae3
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/SoundManager.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.util.WaveData;
+
+
+/**
+ *
+ * Simple sound manager for OpenAL using n sources accessed in
+ * a round robin schedule. Source n is reserved for a single buffer and checking for
+ * whether it's playing.
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: SoundManager.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class SoundManager {
+
+ /** We support at most 256 buffers*/
+ private int[] buffers = new int[256];
+
+ /** Number of sources is limited tby user (and hardware) */
+ private int[] sources;
+
+ /** Our internal scratch buffer */
+ private IntBuffer scratchBuffer = BufferUtils.createIntBuffer(256);
+
+ /** Whether we're running in no sound mode */
+ private boolean soundOutput;
+
+ /** Current index in our buffers */
+ private int bufferIndex;
+
+ /** Current index in our source list */
+ private int sourceIndex;
+
+ /**
+ * Creates a new SoundManager
+ */
+ public SoundManager() {
+ }
+
+ /**
+ * Plays a sound effect
+ * @param buffer Buffer index to play gotten from addSound
+ */
+ public void playEffect(int buffer) {
+ if(soundOutput) {
+ // make sure we never choose last channel, since it is used for special sounds
+ int channel = sources[(sourceIndex++ % (sources.length-1))];
+
+ // link buffer and source, and play it
+ AL10.alSourcei(channel, AL10.AL_BUFFER, buffers[buffer]);
+ AL10.alSourcePlay(channel);
+ }
+ }
+
+ /**
+ * Plays a sound on last source
+ * @param buffer Buffer index to play gotten from addSound
+ */
+ public void playSound(int buffer) {
+ if(soundOutput) {
+ AL10.alSourcei(sources[sources.length-1], AL10.AL_BUFFER, buffers[buffer]);
+ AL10.alSourcePlay(sources[sources.length-1]);
+ }
+ }
+
+ /**
+ * Whether a sound is playing on last source
+ * @return true if a source is playing right now on source n
+ */
+ public boolean isPlayingSound() {
+ return AL10.alGetSourcei(sources[sources.length-1], AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING;
+ }
+
+ /**
+ * Initializes the SoundManager
+ *
+ * @param sources Number of sources to create
+ */
+ public void initialize(int channels) {
+ try {
+ AL.create();
+
+ // allocate sources
+ scratchBuffer.limit(channels);
+ AL10.alGenSources(scratchBuffer);
+ scratchBuffer.rewind();
+ scratchBuffer.get(sources = new int[channels]);
+
+ // could we allocate all channels?
+ if(AL10.alGetError() != AL10.AL_NO_ERROR) {
+ throw new LWJGLException("Unable to allocate " + channels + " sources");
+ }
+
+ // we have sound
+ soundOutput = true;
+ } catch (LWJGLException le) {
+ le.printStackTrace();
+ System.out.println("Sound disabled");
+ }
+ }
+
+ /**
+ * Adds a sound to the Sound Managers pool
+ *
+ * @param path Path to file to load
+ * @return index into SoundManagers buffer list
+ */
+ public int addSound(String path) {
+ // Generate 1 buffer entry
+ scratchBuffer.rewind().position(0).limit(1);
+ AL10.alGenBuffers(scratchBuffer);
+ buffers[bufferIndex] = scratchBuffer.get(0);
+
+ // load wave data from buffer
+ WaveData wavefile = WaveData.create("spaceinvaders/" + path);
+
+ // copy to buffers
+ AL10.alBufferData(buffers[bufferIndex], wavefile.format, wavefile.data, wavefile.samplerate);
+
+ // unload file again
+ wavefile.dispose();
+
+ // return index for this sound
+ return bufferIndex++;
+ }
+
+ /**
+ * Destroy this SoundManager
+ */
+ public void destroy() {
+ if(soundOutput) {
+
+ // stop playing sounds
+ scratchBuffer.position(0).limit(sources.length);
+ scratchBuffer.put(sources).flip();
+ AL10.alSourceStop(scratchBuffer);
+
+ // destroy sources
+ AL10.alDeleteSources(scratchBuffer);
+
+ // destroy buffers
+ scratchBuffer.position(0).limit(bufferIndex);
+ scratchBuffer.put(buffers, 0, bufferIndex).flip();
+ AL10.alDeleteBuffers(scratchBuffer);
+
+ // destory OpenAL
+ AL.destroy();
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/Sprite.java b/src/java/org/lwjgl/examples/spaceinvaders/Sprite.java
new file mode 100644
index 0000000..162af89
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/Sprite.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+import java.io.IOException;
+
+import org.lwjgl.opengl.GL11;
+
+/**
+ * Implementation of sprite that uses an OpenGL quad and a texture
+ * to render a given image to the screen.
+ *
+ * @author Kevin Glass
+ * @author Brian Matzon
+ */
+public class Sprite {
+
+ /** The texture that stores the image for this sprite */
+ private Texture texture;
+
+ /** The width in pixels of this sprite */
+ private int width;
+
+ /** The height in pixels of this sprite */
+ private int height;
+
+ /**
+ * Create a new sprite from a specified image.
+ *
+ * @param window The window in which the sprite will be displayed
+ * @param ref A reference to the image on which this sprite should be based
+ */
+ public Sprite(TextureLoader loader, String ref) {
+ try {
+ texture = loader.getTexture("spaceinvaders/" + ref);
+ width = texture.getImageWidth();
+ height = texture.getImageHeight();
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * Get the width of this sprite in pixels
+ *
+ * @return The width of this sprite in pixels
+ */
+ public int getWidth() {
+ return texture.getImageWidth();
+ }
+
+ /**
+ * Get the height of this sprite in pixels
+ *
+ * @return The height of this sprite in pixels
+ */
+ public int getHeight() {
+ return texture.getImageHeight();
+ }
+
+ /**
+ * Draw the sprite at the specified location
+ *
+ * @param x The x location at which to draw this sprite
+ * @param y The y location at which to draw this sprite
+ */
+ public void draw(int x, int y) {
+ // store the current model matrix
+ GL11.glPushMatrix();
+
+ // bind to the appropriate texture for this sprite
+ texture.bind();
+
+ // translate to the right location and prepare to draw
+ GL11.glTranslatef(x, y, 0);
+
+ // draw a quad textured to match the sprite
+ GL11.glBegin(GL11.GL_QUADS);
+ {
+ GL11.glTexCoord2f(0, 0);
+ GL11.glVertex2f(0, 0);
+
+ GL11.glTexCoord2f(0, texture.getHeight());
+ GL11.glVertex2f(0, height);
+
+ GL11.glTexCoord2f(texture.getWidth(), texture.getHeight());
+ GL11.glVertex2f(width, height);
+
+ GL11.glTexCoord2f(texture.getWidth(), 0);
+ GL11.glVertex2f(width, 0);
+ }
+ GL11.glEnd();
+
+ // restore the model view matrix to prevent contamination
+ GL11.glPopMatrix();
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/Texture.java b/src/java/org/lwjgl/examples/spaceinvaders/Texture.java
new file mode 100644
index 0000000..58a964d
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/Texture.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+import org.lwjgl.opengl.GL11;
+
+/**
+ * A texture to be bound within OpenGL. This object is responsible for
+ * keeping track of a given OpenGL texture and for calculating the
+ * texturing mapping coordinates of the full image.
+ *
+ * Since textures need to be powers of 2 the actual texture may be
+ * considerably bigged that the source image and hence the texture
+ * mapping coordinates need to be adjusted to matchup drawing the
+ * sprite against the texture.
+ *
+ * @author Kevin Glass
+ * @author Brian Matzon
+ */
+public class Texture {
+
+ /** The GL target type */
+ private int target;
+
+ /** The GL texture ID */
+ private int textureID;
+
+ /** The height of the image */
+ private int height;
+
+ /** The width of the image */
+ private int width;
+
+ /** The width of the texture */
+ private int texWidth;
+
+ /** The height of the texture */
+ private int texHeight;
+
+ /** The ratio of the width of the image to the texture */
+ private float widthRatio;
+
+ /** The ratio of the height of the image to the texture */
+ private float heightRatio;
+
+ /**
+ * Create a new texture
+ *
+ * @param target The GL target
+ * @param textureID The GL texture ID
+ */
+ public Texture(int target, int textureID) {
+ this.target = target;
+ this.textureID = textureID;
+ }
+
+ /**
+ * Bind the specified GL context to a texture
+ *
+ * @param gl The GL context to bind to
+ */
+ public void bind() {
+ GL11.glBindTexture(target, textureID);
+ }
+
+ /**
+ * Set the height of the image
+ *
+ * @param height The height of the image
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ setHeight();
+ }
+
+ /**
+ * Set the width of the image
+ *
+ * @param width The width of the image
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ setWidth();
+ }
+
+ /**
+ * Get the height of the original image
+ *
+ * @return The height of the original image
+ */
+ public int getImageHeight() {
+ return height;
+ }
+
+ /**
+ * Get the width of the original image
+ *
+ * @return The width of the original image
+ */
+ public int getImageWidth() {
+ return width;
+ }
+
+ /**
+ * Get the height of the physical texture
+ *
+ * @return The height of physical texture
+ */
+ public float getHeight() {
+ return heightRatio;
+ }
+
+ /**
+ * Get the width of the physical texture
+ *
+ * @return The width of physical texture
+ */
+ public float getWidth() {
+ return widthRatio;
+ }
+
+ /**
+ * Set the height of this texture
+ *
+ * @param texHeight The height of the texture
+ */
+ public void setTextureHeight(int texHeight) {
+ this.texHeight = texHeight;
+ setHeight();
+ }
+
+ /**
+ * Set the width of this texture
+ *
+ * @param texWidth The width of the texture
+ */
+ public void setTextureWidth(int texWidth) {
+ this.texWidth = texWidth;
+ setWidth();
+ }
+
+ /**
+ * Set the height of the texture. This will update the
+ * ratio also.
+ */
+ private void setHeight() {
+ if (texHeight != 0) {
+ heightRatio = ((float) height) / texHeight;
+ }
+ }
+
+ /**
+ * Set the width of the texture. This will update the
+ * ratio also.
+ */
+ private void setWidth() {
+ if (texWidth != 0) {
+ widthRatio = ((float) width) / texWidth;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/examples/spaceinvaders/TextureLoader.java b/src/java/org/lwjgl/examples/spaceinvaders/TextureLoader.java
new file mode 100644
index 0000000..fb3af5e
--- /dev/null
+++ b/src/java/org/lwjgl/examples/spaceinvaders/TextureLoader.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2002-2008 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.examples.spaceinvaders;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.util.HashMap;
+import java.util.Hashtable;
+
+import javax.imageio.ImageIO;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+
+/**
+ * A utility class to load textures for OpenGL. This source is based
+ * on a texture that can be found in the Java Gaming (www.javagaming.org)
+ * Wiki. It has been simplified slightly for explicit 2D graphics use.
+ *
+ * OpenGL uses a particular image format. Since the images that are
+ * loaded from disk may not match this format this loader introduces
+ * a intermediate image which the source image is copied into. In turn,
+ * this image is used as source for the OpenGL texture.
+ *
+ * @author Kevin Glass
+ * @author Brian Matzon
+ */
+public class TextureLoader {
+ /** The table of textures that have been loaded in this loader */
+ private HashMap table = new HashMap();
+
+ /** The colour model including alpha for the GL image */
+ private ColorModel glAlphaColorModel;
+
+ /** The colour model for the GL image */
+ private ColorModel glColorModel;
+
+ /** Scratch buffer for texture ID's */
+ private IntBuffer textureIDBuffer = BufferUtils.createIntBuffer(1);
+
+ /**
+ * Create a new texture loader based on the game panel
+ *
+ * @param gl The GL content in which the textures should be loaded
+ */
+ public TextureLoader() {
+ glAlphaColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ new int[] {8,8,8,8},
+ true,
+ false,
+ ComponentColorModel.TRANSLUCENT,
+ DataBuffer.TYPE_BYTE);
+
+ glColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ new int[] {8,8,8,0},
+ false,
+ false,
+ ComponentColorModel.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ }
+
+ /**
+ * Create a new texture ID
+ *
+ * @return A new texture ID
+ */
+ private int createTextureID() {
+ GL11.glGenTextures(textureIDBuffer);
+ return textureIDBuffer.get(0);
+ }
+
+ /**
+ * Load a texture
+ *
+ * @param resourceName The location of the resource to load
+ * @return The loaded texture
+ * @throws IOException Indicates a failure to access the resource
+ */
+ public Texture getTexture(String resourceName) throws IOException {
+ Texture tex = (Texture) table.get(resourceName);
+
+ if (tex != null) {
+ return tex;
+ }
+
+ tex = getTexture(resourceName,
+ GL11.GL_TEXTURE_2D, // target
+ GL11.GL_RGBA, // dst pixel format
+ GL11.GL_LINEAR, // min filter (unused)
+ GL11.GL_LINEAR);
+
+ table.put(resourceName,tex);
+
+ return tex;
+ }
+
+ /**
+ * Load a texture into OpenGL from a image reference on
+ * disk.
+ *
+ * @param resourceName The location of the resource to load
+ * @param target The GL target to load the texture against
+ * @param dstPixelFormat The pixel format of the screen
+ * @param minFilter The minimising filter
+ * @param magFilter The magnification filter
+ * @return The loaded texture
+ * @throws IOException Indicates a failure to access the resource
+ */
+ public Texture getTexture(String resourceName,
+ int target,
+ int dstPixelFormat,
+ int minFilter,
+ int magFilter) throws IOException {
+ int srcPixelFormat = 0;
+
+ // create the texture ID for this texture
+ int textureID = createTextureID();
+ Texture texture = new Texture(target,textureID);
+
+ // bind this texture
+ GL11.glBindTexture(target, textureID);
+
+ BufferedImage bufferedImage = loadImage(resourceName);
+ texture.setWidth(bufferedImage.getWidth());
+ texture.setHeight(bufferedImage.getHeight());
+
+ if (bufferedImage.getColorModel().hasAlpha()) {
+ srcPixelFormat = GL11.GL_RGBA;
+ } else {
+ srcPixelFormat = GL11.GL_RGB;
+ }
+
+ // convert that image into a byte buffer of texture data
+ ByteBuffer textureBuffer = convertImageData(bufferedImage,texture);
+
+ if (target == GL11.GL_TEXTURE_2D) {
+ GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
+ GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
+ }
+
+ // produce a texture from the byte buffer
+ GL11.glTexImage2D(target,
+ 0,
+ dstPixelFormat,
+ get2Fold(bufferedImage.getWidth()),
+ get2Fold(bufferedImage.getHeight()),
+ 0,
+ srcPixelFormat,
+ GL11.GL_UNSIGNED_BYTE,
+ textureBuffer );
+
+ return texture;
+ }
+
+ /**
+ * Get the closest greater power of 2 to the fold number
+ *
+ * @param fold The target number
+ * @return The power of 2
+ */
+ private int get2Fold(int fold) {
+ int ret = 2;
+ while (ret < fold) {
+ ret *= 2;
+ }
+ return ret;
+ }
+
+ /**
+ * Convert the buffered image to a texture
+ *
+ * @param bufferedImage The image to convert to a texture
+ * @param texture The texture to store the data into
+ * @return A buffer containing the data
+ */
+ private ByteBuffer convertImageData(BufferedImage bufferedImage,Texture texture) {
+ ByteBuffer imageBuffer = null;
+ WritableRaster raster;
+ BufferedImage texImage;
+
+ int texWidth = 2;
+ int texHeight = 2;
+
+ // find the closest power of 2 for the width and height
+ // of the produced texture
+ while (texWidth < bufferedImage.getWidth()) {
+ texWidth *= 2;
+ }
+ while (texHeight < bufferedImage.getHeight()) {
+ texHeight *= 2;
+ }
+
+ texture.setTextureHeight(texHeight);
+ texture.setTextureWidth(texWidth);
+
+ // create a raster that can be used by OpenGL as a source
+ // for a texture
+ if (bufferedImage.getColorModel().hasAlpha()) {
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,4,null);
+ texImage = new BufferedImage(glAlphaColorModel,raster,false,new Hashtable());
+ } else {
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,3,null);
+ texImage = new BufferedImage(glColorModel,raster,false,new Hashtable());
+ }
+
+ // copy the source image into the produced image
+ Graphics g = texImage.getGraphics();
+ g.setColor(new Color(0f,0f,0f,0f));
+ g.fillRect(0,0,texWidth,texHeight);
+ g.drawImage(bufferedImage,0,0,null);
+
+ // build a byte buffer from the temporary image
+ // that be used by OpenGL to produce a texture.
+ byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData();
+
+ imageBuffer = ByteBuffer.allocateDirect(data.length);
+ imageBuffer.order(ByteOrder.nativeOrder());
+ imageBuffer.put(data, 0, data.length);
+ imageBuffer.flip();
+
+ return imageBuffer;
+ }
+
+ /**
+ * Load a given resource as a buffered image
+ *
+ * @param ref The location of the resource to load
+ * @return The loaded buffered image
+ * @throws IOException Indicates a failure to find a resource
+ */
+ private BufferedImage loadImage(String ref) throws IOException {
+ URL url = TextureLoader.class.getClassLoader().getResource(ref);
+
+ if (url == null) {
+ throw new IOException("Cannot find: " + ref);
+ }
+
+ BufferedImage bufferedImage = ImageIO.read(new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(ref)));
+
+ return bufferedImage;
+ }
+}
diff --git a/src/java/org/lwjgl/input/Controller.java b/src/java/org/lwjgl/input/Controller.java
new file mode 100644
index 0000000..9649df6
--- /dev/null
+++ b/src/java/org/lwjgl/input/Controller.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2002-2008 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.input;
+
+/**
+ * A game controller of some sort that will provide input. The controller
+ * presents buttons and axes. Buttons are either pressed or not pressed. Axis
+ * provide analogue values.
+ *
+ * @author Kevin Glass
+ */
+public interface Controller {
+ /**
+ * Get the name assigned to this controller.
+ *
+ * @return The name assigned to this controller
+ */
+ public String getName();
+
+ /**
+ * Get the index of this controller in the collection
+ *
+ * @return The index of this controller in the collection
+ */
+ public int getIndex();
+
+ /**
+ * Retrieve the number of buttons available on this controller
+ *
+ * @return The number of butotns available on this controller
+ */
+ public int getButtonCount();
+
+ /**
+ * Get the name of the specified button. Be warned, often this is
+ * as exciting as "Button X"
+ *
+ * @param index The index of the button whose name should be retrieved
+ * @return The name of the button requested
+ */
+ public String getButtonName(int index);
+
+ /**
+ * Check if a button is currently pressed
+ *
+ * @param index The button to check
+ * @return True if the button is currently pressed
+ */
+ public boolean isButtonPressed(int index);
+
+ /**
+ * Poll the controller for new data. This will also update
+ * events
+ */
+ public void poll();
+
+ /**
+ * Get the X-Axis value of the POV on this controller
+ *
+ * @return The X-Axis value of the POV on this controller
+ */
+ public float getPovX();
+
+ /**
+ * Get the Y-Axis value of the POV on this controller
+ *
+ * @return The Y-Axis value of the POV on this controller
+ */
+ public float getPovY();
+
+ /**
+ * Get the dead zone for a specified axis
+ *
+ * @param index The index of the axis for which to retrieve the dead zone
+ * @return The dead zone for the specified axis
+ */
+ public float getDeadZone(int index);
+
+ /**
+ * Set the dead zone for the specified axis
+ *
+ * @param index The index of hte axis for which to set the dead zone
+ * @param zone The dead zone to use for the specified axis
+ */
+ public void setDeadZone(int index,float zone);
+
+ /**
+ * Retrieve the number of axes available on this controller.
+ *
+ * @return The number of axes available on this controller.
+ */
+ public int getAxisCount();
+
+ /**
+ * Get the name that's given to the specified axis
+ *
+ * @param index The index of the axis whose name should be retrieved
+ * @return The name of the specified axis.
+ */
+ public String getAxisName(int index);
+
+ /**
+ * Retrieve the value thats currently available on a specified axis. The
+ * value will always be between 1.0 and -1.0 and will calibrate as values
+ * are passed read. It may be useful to get the player to wiggle the joystick
+ * from side to side to get the calibration right.
+ *
+ * @param index The index of axis to be read
+ * @return The value from the specified axis.
+ */
+ public float getAxisValue(int index);
+
+ /**
+ * Get the value from the X axis if there is one. If no X axis is
+ * defined a zero value will be returned.
+ *
+ * @return The value from the X axis
+ */
+ public float getXAxisValue();
+
+ /**
+ * Get the dead zone for the X axis.
+ *
+ * @return The dead zone for the X axis
+ */
+ public float getXAxisDeadZone();
+
+ /**
+ * Set the dead zone for the X axis
+ *
+ * @param zone The dead zone to use for the X axis
+ */
+ public void setXAxisDeadZone(float zone);
+
+ /**
+ * Get the value from the Y axis if there is one. If no Y axis is
+ * defined a zero value will be returned.
+ *
+ * @return The value from the Y axis
+ */
+ public float getYAxisValue();
+
+ /**
+ * Get the dead zone for the Y axis.
+ *
+ * @return The dead zone for the Y axis
+ */
+ public float getYAxisDeadZone();
+
+ /**
+ * Set the dead zone for the Y axis
+ *
+ * @param zone The dead zone to use for the Y axis
+ */
+ public void setYAxisDeadZone(float zone);
+
+ /**
+ * Get the value from the Z axis if there is one. If no Z axis is
+ * defined a zero value will be returned.
+ *
+ * @return The value from the Z axis
+ */
+ public float getZAxisValue();
+
+ /**
+ * Get the dead zone for the Z axis.
+ *
+ * @return The dead zone for the Z axis
+ */
+ public float getZAxisDeadZone();
+
+ /**
+ * Set the dead zone for the Z axis
+ *
+ * @param zone The dead zone to use for the Z axis
+ */
+ public void setZAxisDeadZone(float zone);
+
+ /**
+ * Get the value from the RX axis if there is one. If no RX axis is
+ * defined a zero value will be returned.
+ *
+ * @return The value from the RX axis
+ */
+ public float getRXAxisValue();
+
+ /**
+ * Get the dead zone for the RX axis.
+ *
+ * @return The dead zone for the RX axis
+ */
+ public float getRXAxisDeadZone();
+
+ /**
+ * Set the dead zone for the RX axis
+ *
+ * @param zone The dead zone to use for the RX axis
+ */
+ public void setRXAxisDeadZone(float zone);
+
+ /**
+ * Get the value from the RY axis if there is one. If no RY axis is
+ * defined a zero value will be returned.
+ *
+ * @return The value from the RY axis
+ */
+ public float getRYAxisValue();
+
+ /**
+ * Get the dead zone for the RY axis.
+ *
+ * @return The dead zone for the RY axis
+ */
+ public float getRYAxisDeadZone();
+
+ /**
+ * Set the dead zone for the RY axis
+ *
+ * @param zone The dead zone to use for the RY axis
+ */
+ public void setRYAxisDeadZone(float zone);
+
+ /**
+ * Get the value from the RZ axis if there is one. If no RZ axis is
+ * defined a zero value will be returned.
+ *
+ * @return The value from the RZ axis
+ */
+ public float getRZAxisValue();
+
+ /**
+ * Get the dead zone for the RZ axis.
+ *
+ * @return The dead zone for the RZ axis
+ */
+ public float getRZAxisDeadZone();
+
+ /**
+ * Set the dead zone for the RZ axis
+ *
+ * @param zone The dead zone to use for the RZ axis
+ */
+ public void setRZAxisDeadZone(float zone);
+}
diff --git a/src/java/org/lwjgl/input/ControllerEvent.java b/src/java/org/lwjgl/input/ControllerEvent.java
new file mode 100644
index 0000000..b4c2d3b
--- /dev/null
+++ b/src/java/org/lwjgl/input/ControllerEvent.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2002-2008 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.input;
+
+/**
+ * An event occuring on a controller.
+ *
+ * @author Kevin Glass
+ */
+class ControllerEvent {
+ /** Indicates the event was caused by a button */
+ public static final int BUTTON = 1;
+ /** Indicates the event was caused by a axis */
+ public static final int AXIS = 2;
+ /** Indicates the event was caused by a pov X */
+ public static final int POVX = 3;
+ /** Indicates the event was caused by a pov Y */
+ public static final int POVY = 4;
+
+ /** The controller generating the event */
+ private Controller source;
+ /** The index of the input (axis or button) that generated the event */
+ private int index;
+ /** Type of control that generated the event */
+ private int type;
+ /** True if this event was caused by the x axis */
+ private boolean xaxis;
+ /** True if this event was caused by the y axis */
+ private boolean yaxis;
+ /** The time stamp of this event */
+ private long timeStamp;
+
+ /**
+ * Create a new event
+ *
+ * @param source The source of the event
+ * @param timeStamp The time stamp given for this event
+ * @param type The type of control generating this event
+ * @param index The index of the input that generated the event
+ * @param xaxis True if this event was caused by the x-axis
+ * @param yaxis True if this event was caused by the y-axis
+ */
+ public ControllerEvent(Controller source,long timeStamp, int type,int index,boolean xaxis,boolean yaxis) {
+ this.source = source;
+ this.timeStamp = timeStamp;
+ this.type = type;
+ this.index = index;
+ this.xaxis = xaxis;
+ this.yaxis = yaxis;
+ }
+
+ /**
+ * Get the time stamp given for this event. As with nanoTime()
+ * this value means nothing other than giving ordering
+ *
+ * @return The time stamp given for this event
+ */
+ public long getTimeStamp() {
+ return timeStamp;
+ }
+
+ /**
+ * Get the controller that generated this event
+ *
+ * @return The controller that generated this event
+ */
+ public Controller getSource() {
+ return source;
+ }
+
+ /**
+ * Get the index of the control generating this event
+ *
+ * @return The index of the control generating this event
+ */
+ public int getControlIndex() {
+ return index;
+ }
+
+ /**
+ * Check if this event was generated by a button
+ *
+ * @return True if this event was generated by a button
+ */
+ public boolean isButton() {
+ return type == BUTTON;
+ }
+
+ /**
+ * Check if this event was generated by a axis
+ *
+ * @return True if this event was generated by a axis
+ */
+ public boolean isAxis() {
+ return type == AXIS;
+ }
+
+ /**
+ * Check if this event was generated by a pov
+ *
+ * @return True if this event was generated by a pov
+ */
+ public boolean isPovY() {
+ return type == POVY;
+ }
+ /**
+ *
+ * Check if this event was generated by a pov
+ *
+ * @return True if this event was generated by a pov
+ */
+ public boolean isPovX() {
+ return type == POVX;
+ }
+
+ /**
+ * Check if this event was caused by the X axis
+ *
+ * @return True if this event was caused by the X axis
+ */
+ public boolean isXAxis() {
+ return xaxis;
+ }
+
+ /**
+ * Check if this event was caused by the Y axis
+ *
+ * @return True if this event was caused by the Y axis
+ */
+ public boolean isYAxis() {
+ return yaxis;
+ }
+
+ /*
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return "["+source+" type="+type+" xaxis="+xaxis+" yaxis="+yaxis+"]";
+ }
+}
diff --git a/src/java/org/lwjgl/input/Controllers.java b/src/java/org/lwjgl/input/Controllers.java
new file mode 100644
index 0000000..c43bfc0
--- /dev/null
+++ b/src/java/org/lwjgl/input/Controllers.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2002-2008 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.input;
+
+import java.util.ArrayList;
+
+import net.java.games.input.ControllerEnvironment;
+
+import org.lwjgl.LWJGLException;
+
+/**
+ * The collection of controllers currently connected.
+ *
+ * @author Kevin Glass
+ */
+public class Controllers {
+ /** The controllers available */
+ private static ArrayList controllers = new ArrayList();
+ /** The number of controllers */
+ private static int controllerCount;
+
+ /** The current list of events */
+ private static ArrayList events = new ArrayList();
+ /** The current event */
+ private static ControllerEvent event;
+
+ /** Whether controllers were created */
+ private static boolean created;
+
+ /**
+ * Initialise the controllers collection
+ *
+ * @throws LWJGLException Indicates a failure to initialise the controller library.
+ */
+ public static void create() throws LWJGLException {
+ if (created)
+ return;
+
+ try {
+ ControllerEnvironment env = ControllerEnvironment.getDefaultEnvironment();
+
+ net.java.games.input.Controller[] found = env.getControllers();
+ ArrayList lollers = new ArrayList();
+ for (int i=0;i
+ * @version $Revision: 2983 $
+ * $Id: Cursor.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+public class Cursor {
+ /** 1 bit transparency for native cursor */
+ public static final int CURSOR_ONE_BIT_TRANSPARENCY = 1;
+
+ /** 8 bit alhpa native cursor */
+ public static final int CURSOR_8_BIT_ALPHA = 2;
+
+ /** animation native cursor */
+ public static final int CURSOR_ANIMATION = 4;
+
+ /** First element to display */
+ private final CursorElement[] cursors;
+
+ /** 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
+ * Cursor objects. Cursor images are in ARGB format, but only one bit transparancy is guaranteed to be supported.
+ * So to maximize portability, lwjgl applications should only create cursor images with 0x00 or 0xff as alpha values.
+ * The constructor will copy the images and delays, so there's no need to keep them around.
+ *
+ * @param width cursor image width
+ * @param height cursor image height
+ * @param xHotspot the x coordinate of the cursor hotspot
+ * @param yHotspot the y coordinate of the cursor hotspot
+ * @param numImages number of cursor images specified. Must be 1 if animations are not supported.
+ * @param images A buffer containing the images. The origin is at the lower left corner, like OpenGL.
+ * @param delays An int buffer of animation frame delays, if numImages is greater than 1, else null
+ * @throws LWJGLException if the cursor could not be created for any reason
+ */
+ public Cursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if ((getCapabilities() & CURSOR_ONE_BIT_TRANSPARENCY) == 0)
+ throw new LWJGLException("Native cursors not supported");
+ images = NondirectBufferWrapper.wrapBuffer(images, width*height*numImages);
+ if (delays != null)
+ delays = NondirectBufferWrapper.wrapBuffer(delays, numImages);
+ if (!Mouse.isCreated())
+ throw new IllegalStateException("Mouse must be created before creating cursor objects");
+ if (width*height*numImages > images.remaining())
+ throw new IllegalArgumentException("width*height*numImages > images.remaining()");
+ if (xHotspot >= width || xHotspot < 0)
+ throw new IllegalArgumentException("xHotspot > width || xHotspot < 0");
+ if (yHotspot >= height || yHotspot < 0)
+ throw new IllegalArgumentException("yHotspot > height || yHotspot < 0");
+
+ Sys.initialize();
+
+ // Hmm
+ yHotspot = height - 1 - yHotspot;
+
+ // create cursor (or cursors if multiple images supplied)
+ cursors = createCursors(width, height, xHotspot, yHotspot, numImages, images, delays);
+ }
+ }
+
+ /**
+ * Gets the minimum size of a native cursor. Can only be called if
+ * The Mouse is created and cursor caps includes at least
+ * CURSOR_ONE_BIT_TRANSPARANCY.
+ *
+ * @return the maximum size of a native cursor
+ */
+ public static int getMinCursorSize() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!Mouse.isCreated())
+ throw new IllegalStateException("Mouse must be created.");
+ return Mouse.getImplementation().getMinCursorSize();
+ }
+ }
+
+ /**
+ * Gets the maximum size of a native cursor. Can only be called if
+ * The Mouse is created and cursor caps includes at least
+ * CURSOR_ONE_BIT_TRANSPARANCY.
+ *
+ * @return the maximum size of a native cursor
+ */
+ public static int getMaxCursorSize() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!Mouse.isCreated())
+ throw new IllegalStateException("Mouse must be created.");
+ return Mouse.getImplementation().getMaxCursorSize();
+ }
+ }
+
+ /**
+ * Get the capabilities of the native cursor. Return a bit mask of the native cursor capabilities.
+ * The CURSOR_ONE_BIT_TRANSPARANCY indicates support for cursors with one bit transparancy,
+ * the CURSOR_8_BIT_ALPHA indicates support for 8 bit alpha and CURSOR_ANIMATION indicates
+ * support for cursor animations.
+ *
+ * @return A bit mask with native cursor capabilities.
+ */
+ public static int getCapabilities() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (Mouse.getImplementation() != null)
+ return Mouse.getImplementation().getNativeCursorCapabilities();
+ else
+ return OpenGLPackageAccess.createImplementation().getNativeCursorCapabilities();
+ }
+ }
+
+ /**
+ * Creates the actual cursor, using a platform specific class
+ */
+ private static CursorElement[] createCursors(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
+ // create copy and flip images to match ogl
+ IntBuffer images_copy = BufferUtils.createIntBuffer(images.remaining());
+ flipImages(width, height, numImages, images, images_copy);
+
+ // Win32 doesn't (afaik) allow for animation based cursors, except when they're
+ // in the .ani format, which we don't support.
+ // The cursor animation was therefor developed using java side time tracking.
+ // unfortunately X flickers when changing cursor. We therefore check for either
+ // Win32 or X and do accordingly. This hasn't been implemented on Mac, but we
+ // might want to split it into a X/Win/Mac cursor if it gets too cluttered
+
+ CursorElement[] cursors;
+ switch (LWJGLUtil.getPlatform()) {
+ case LWJGLUtil.PLATFORM_MACOSX:
+ /* Fall through */
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ // create our cursor elements
+ cursors = new CursorElement[numImages];
+ for(int i=0; i> 24 & 0xff;
+ if(alpha != 0xff) {
+ images_copy.put(index, 0);
+ }
+ }
+
+ Object handle = Mouse.getImplementation().createCursor(width, height, xHotspot, yHotspot, 1, images_copy, null);
+ long delay = (delays != null) ? delays.get(i) : 0;
+ long timeout = System.currentTimeMillis();
+ cursors[i] = new CursorElement(handle, delay, timeout);
+
+ // offset to next image
+ images_copy.position(width*height*(i+1));
+ }
+ break;
+ case LWJGLUtil.PLATFORM_LINUX:
+ // create our cursor elements
+ Object handle = Mouse.getImplementation().createCursor(width, height, xHotspot, yHotspot, numImages, images_copy, delays);
+ CursorElement cursor_element = new CursorElement(handle, -1, -1);
+ cursors = new CursorElement[]{cursor_element};
+ break;
+ default:
+ throw new RuntimeException("Unknown OS");
+ }
+ return cursors;
+ }
+
+ /**
+ * Flips the images so they're oriented according to opengl
+ *
+ * @param width Width of image
+ * @param height Height of images
+ * @param numImages How many images to flip
+ * @param images Source images
+ * @param images_copy Destination images
+ */
+ private static void flipImages(int width, int height, int numImages, IntBuffer images, IntBuffer images_copy) {
+ for (int i = 0; i < numImages; i++) {
+ int start_index = i*width*height;
+ flipImage(width, height, start_index, images, images_copy);
+ }
+ }
+
+ /**
+ * @param width Width of image
+ * @param height Height of images
+ * @param start_index index into source buffer to copy to
+ * @param images Source images
+ * @param images_copy Destination images
+ */
+ private static void flipImage(int width, int height, int start_index, IntBuffer images, IntBuffer images_copy) {
+ for (int y = 0; y < height>>1; y++) {
+ int index_y_1 = y*width + start_index;
+ int index_y_2 = (height - y - 1)*width + start_index;
+ for (int x = 0; x < width; x++) {
+ int index1 = index_y_1 + x;
+ int index2 = index_y_2 + x;
+ int temp_pixel = images.get(index1 + images.position());
+ images_copy.put(index1, images.get(index2 + images.position()));
+ images_copy.put(index2, temp_pixel);
+ }
+ }
+ }
+
+ /**
+ * 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() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (destroyed)
+ return;
+ if (Mouse.getNativeCursor() == this) {
+ try {
+ Mouse.setNativeCursor(null);
+ } catch (LWJGLException e) {
+ // ignore
+ }
+ }
+ for(int i=0; i 1 && cursors[index].timeout < System.currentTimeMillis();
+ }
+
+ /**
+ * Changes to the next cursor
+ */
+ protected void nextCursor() {
+ checkValid();
+ index = ++index % cursors.length;
+ }
+
+ /**
+ * A single cursor element, used when animating
+ */
+ private static class CursorElement {
+ /** Handle to cursor */
+ final Object cursorHandle;
+
+ /** How long a delay this element should have */
+ final long delay;
+
+ /** Absolute time this element times out */
+ long timeout;
+
+ CursorElement(Object cursorHandle, long delay, long timeout) {
+ this.cursorHandle = cursorHandle;
+ this.delay = delay;
+ this.timeout = timeout;
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/input/JInputController.java b/src/java/org/lwjgl/input/JInputController.java
new file mode 100644
index 0000000..7a9aba9
--- /dev/null
+++ b/src/java/org/lwjgl/input/JInputController.java
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2002-2008 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.input;
+
+import java.util.ArrayList;
+
+import net.java.games.input.Component;
+import net.java.games.input.Event;
+import net.java.games.input.EventQueue;
+
+/**
+ * A wrapper round a JInput controller that attempts to make the interface
+ * more useable.
+ *
+ * @author Kevin Glass
+ */
+class JInputController implements Controller {
+ /** The JInput controller this class is wrapping */
+ private net.java.games.input.Controller target;
+ /** The index that has been assigned to this controller */
+ private int index;
+ /** The Buttons that have been detected on the JInput controller */
+ private ArrayList buttons = new ArrayList();
+ /** The Axes that have been detected on the JInput controller */
+ private ArrayList axes = new ArrayList();
+ /** The POVs that have been detected on the JInput controller */
+ private ArrayList pov = new ArrayList();
+ /** The state of the buttons last check */
+ private boolean[] buttonState;
+ /** The values that were read from the pov last check */
+ private float[] povValues;
+ /** The values that were read from the axes last check */
+ private float[] axesValue;
+ /** The maximum values read for each axis */
+ private float[] axesMax;
+ /** The dead zones for each axis */
+ private float[] deadZones;
+ /** The index of the X axis or -1 if no X axis is defined */
+ private int xaxis = -1;
+ /** The index of the Y axis or -1 if no Y axis is defined */
+ private int yaxis = -1;
+ /** The index of the X axis or -1 if no Z axis is defined */
+ private int zaxis = -1;
+ /** The index of the RX axis or -1 if no RX axis is defined */
+ private int rxaxis = -1;
+ /** The index of the RY axis or -1 if no RY axis is defined */
+ private int ryaxis = -1;
+ /** The index of the RZ axis or -1 if no RZ axis is defined */
+ private int rzaxis = -1;
+
+ /**
+ * Create a new controller that wraps round a JInput controller and hopefully
+ * makes it easier to use.
+ *
+ * @param index The index this controller has been assigned to
+ * @param target The target JInput controller this class is wrapping
+ */
+ public JInputController(int index,net.java.games.input.Controller target) {
+ this.target = target;
+ this.index = index;
+
+ Component[] sourceAxes = target.getComponents();
+
+ for (int i=0;i axesMax[axisIndex]) {
+ axesMax[axisIndex] = Math.abs(value);
+ }
+
+ // normalize the value based on maximum value read in the past
+ value /= axesMax[axisIndex];
+ // fire event
+ Controllers.addEvent(new ControllerEvent(this,event.getNanos(),ControllerEvent.AXIS,axisIndex,
+ axisIndex == xaxis,axisIndex == yaxis));
+ axesValue[axisIndex] = value;
+ }
+ }
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getAxisCount()
+ */
+ public int getAxisCount() {
+ return axes.size();
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getAxisName(int)
+ */
+ public String getAxisName(int index) {
+ Component axis = (Component) axes.get(index);
+
+ return axis.getName();
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getAxisValue(int)
+ */
+ public float getAxisValue(int index) {
+ return axesValue[index];
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getXAxisValue()
+ */
+ public float getXAxisValue() {
+ if (xaxis == -1) {
+ return 0;
+ }
+
+ return getAxisValue(xaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getYAxisValue()
+ */
+ public float getYAxisValue() {
+ if (yaxis == -1) {
+ return 0;
+ }
+
+ return getAxisValue(yaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getXAxisDeadZone()
+ */
+ public float getXAxisDeadZone() {
+ if (xaxis == -1) {
+ return 0;
+ }
+
+ return getDeadZone(xaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getYAxisDeadZone()
+ */
+ public float getYAxisDeadZone() {
+ if (yaxis == -1) {
+ return 0;
+ }
+
+ return getDeadZone(yaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#setXAxisDeadZone(float)
+ */
+ public void setXAxisDeadZone(float zone) {
+ setDeadZone(xaxis,zone);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#setYAxisDeadZone(float)
+ */
+ public void setYAxisDeadZone(float zone) {
+ setDeadZone(yaxis,zone);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getDeadZone(int)
+ */
+ public float getDeadZone(int index) {
+ return deadZones[index];
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#setDeadZone(int, float)
+ */
+ public void setDeadZone(int index, float zone) {
+ deadZones[index] = zone;
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getZAxisValue()
+ */
+ public float getZAxisValue() {
+ if (zaxis == -1) {
+ return 0;
+ }
+
+ return getAxisValue(zaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getZAxisDeadZone()
+ */
+ public float getZAxisDeadZone() {
+ if (zaxis == -1) {
+ return 0;
+ }
+
+ return getDeadZone(zaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#setZAxisDeadZone(float)
+ */
+ public void setZAxisDeadZone(float zone) {
+ setDeadZone(zaxis,zone);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getRXAxisValue()
+ */
+ public float getRXAxisValue() {
+ if (rxaxis == -1) {
+ return 0;
+ }
+
+ return getAxisValue(rxaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getRXAxisDeadZone()
+ */
+ public float getRXAxisDeadZone() {
+ if (rxaxis == -1) {
+ return 0;
+ }
+
+ return getDeadZone(rxaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#setRXAxisDeadZone(float)
+ */
+ public void setRXAxisDeadZone(float zone) {
+ setDeadZone(rxaxis,zone);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getRYAxisValue()
+ */
+ public float getRYAxisValue() {
+ if (ryaxis == -1) {
+ return 0;
+ }
+
+ return getAxisValue(ryaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getRYAxisDeadZone()
+ */
+ public float getRYAxisDeadZone() {
+ if (ryaxis == -1) {
+ return 0;
+ }
+
+ return getDeadZone(ryaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#setRYAxisDeadZone(float)
+ */
+ public void setRYAxisDeadZone(float zone) {
+ setDeadZone(ryaxis,zone);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getRZAxisValue()
+ */
+ public float getRZAxisValue() {
+ if (rzaxis == -1) {
+ return 0;
+ }
+
+ return getAxisValue(rzaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getRZAxisDeadZone()
+ */
+ public float getRZAxisDeadZone() {
+ if (rzaxis == -1) {
+ return 0;
+ }
+
+ return getDeadZone(rzaxis);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#setRZAxisDeadZone(float)
+ */
+ public void setRZAxisDeadZone(float zone) {
+ setDeadZone(rzaxis,zone);
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getPovX()
+ */
+ public float getPovX() {
+ if (pov.size() == 0) {
+ return 0;
+ }
+
+ float value = povValues[0];
+
+ if ((value == Component.POV.DOWN_LEFT) ||
+ (value == Component.POV.UP_LEFT) ||
+ (value == Component.POV.LEFT)) {
+ return -1;
+ }
+ if ((value == Component.POV.DOWN_RIGHT) ||
+ (value == Component.POV.UP_RIGHT) ||
+ (value == Component.POV.RIGHT)) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /*
+ * @see org.lwjgl.input.Controller#getPovY()
+ */
+ public float getPovY() {
+ if (pov.size() == 0) {
+ return 0;
+ }
+
+ float value = povValues[0];
+
+ if ((value == Component.POV.DOWN_LEFT) ||
+ (value == Component.POV.DOWN_RIGHT) ||
+ (value == Component.POV.DOWN)) {
+ return 1;
+ }
+ if ((value == Component.POV.UP_LEFT) ||
+ (value == Component.POV.UP_RIGHT) ||
+ (value == Component.POV.UP)) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+
+}
diff --git a/src/java/org/lwjgl/input/Keyboard.java b/src/java/org/lwjgl/input/Keyboard.java
new file mode 100644
index 0000000..bc7ee26
--- /dev/null
+++ b/src/java/org/lwjgl/input/Keyboard.java
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2002-2008 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.input;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.Sys;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.InputImplementation;
+
+/**
+ *
+ * A raw Keyboard interface. This can be used to poll the current state of the
+ * keys, or read all the keyboard presses / releases since the last read.
+ *
+ * @author cix_foo
+ * @author elias_naur
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: Keyboard.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class Keyboard {
+ /** Internal use - event size in bytes */
+ public static final int EVENT_SIZE = 4 + 1 + 4 + 8 + 1;
+
+ /**
+ * The special character meaning that no
+ * character was translated for the event.
+ */
+ public static final int CHAR_NONE = '\0';
+
+ /**
+ * The special keycode meaning that only the
+ * translated character is valid.
+ */
+ public static final int KEY_NONE = 0x00;
+
+ public static final int KEY_ESCAPE = 0x01;
+ public static final int KEY_1 = 0x02;
+ public static final int KEY_2 = 0x03;
+ public static final int KEY_3 = 0x04;
+ public static final int KEY_4 = 0x05;
+ public static final int KEY_5 = 0x06;
+ public static final int KEY_6 = 0x07;
+ public static final int KEY_7 = 0x08;
+ public static final int KEY_8 = 0x09;
+ public static final int KEY_9 = 0x0A;
+ public static final int KEY_0 = 0x0B;
+ public static final int KEY_MINUS = 0x0C; /* - on main keyboard */
+ public static final int KEY_EQUALS = 0x0D;
+ public static final int KEY_BACK = 0x0E; /* backspace */
+ public static final int KEY_TAB = 0x0F;
+ public static final int KEY_Q = 0x10;
+ public static final int KEY_W = 0x11;
+ public static final int KEY_E = 0x12;
+ public static final int KEY_R = 0x13;
+ public static final int KEY_T = 0x14;
+ public static final int KEY_Y = 0x15;
+ public static final int KEY_U = 0x16;
+ public static final int KEY_I = 0x17;
+ public static final int KEY_O = 0x18;
+ public static final int KEY_P = 0x19;
+ public static final int KEY_LBRACKET = 0x1A;
+ public static final int KEY_RBRACKET = 0x1B;
+ public static final int KEY_RETURN = 0x1C; /* Enter on main keyboard */
+ public static final int KEY_LCONTROL = 0x1D;
+ public static final int KEY_A = 0x1E;
+ public static final int KEY_S = 0x1F;
+ public static final int KEY_D = 0x20;
+ public static final int KEY_F = 0x21;
+ public static final int KEY_G = 0x22;
+ public static final int KEY_H = 0x23;
+ public static final int KEY_J = 0x24;
+ public static final int KEY_K = 0x25;
+ public static final int KEY_L = 0x26;
+ public static final int KEY_SEMICOLON = 0x27;
+ public static final int KEY_APOSTROPHE = 0x28;
+ public static final int KEY_GRAVE = 0x29; /* accent grave */
+ public static final int KEY_LSHIFT = 0x2A;
+ public static final int KEY_BACKSLASH = 0x2B;
+ public static final int KEY_Z = 0x2C;
+ public static final int KEY_X = 0x2D;
+ public static final int KEY_C = 0x2E;
+ public static final int KEY_V = 0x2F;
+ public static final int KEY_B = 0x30;
+ public static final int KEY_N = 0x31;
+ public static final int KEY_M = 0x32;
+ public static final int KEY_COMMA = 0x33;
+ public static final int KEY_PERIOD = 0x34; /* . on main keyboard */
+ public static final int KEY_SLASH = 0x35; /* / on main keyboard */
+ public static final int KEY_RSHIFT = 0x36;
+ public static final int KEY_MULTIPLY = 0x37; /* * on numeric keypad */
+ public static final int KEY_LMENU = 0x38; /* left Alt */
+ public static final int KEY_SPACE = 0x39;
+ public static final int KEY_CAPITAL = 0x3A;
+ public static final int KEY_F1 = 0x3B;
+ public static final int KEY_F2 = 0x3C;
+ public static final int KEY_F3 = 0x3D;
+ public static final int KEY_F4 = 0x3E;
+ public static final int KEY_F5 = 0x3F;
+ public static final int KEY_F6 = 0x40;
+ public static final int KEY_F7 = 0x41;
+ public static final int KEY_F8 = 0x42;
+ public static final int KEY_F9 = 0x43;
+ public static final int KEY_F10 = 0x44;
+ public static final int KEY_NUMLOCK = 0x45;
+ public static final int KEY_SCROLL = 0x46; /* Scroll Lock */
+ public static final int KEY_NUMPAD7 = 0x47;
+ public static final int KEY_NUMPAD8 = 0x48;
+ public static final int KEY_NUMPAD9 = 0x49;
+ public static final int KEY_SUBTRACT = 0x4A; /* - on numeric keypad */
+ public static final int KEY_NUMPAD4 = 0x4B;
+ public static final int KEY_NUMPAD5 = 0x4C;
+ public static final int KEY_NUMPAD6 = 0x4D;
+ public static final int KEY_ADD = 0x4E; /* + on numeric keypad */
+ public static final int KEY_NUMPAD1 = 0x4F;
+ public static final int KEY_NUMPAD2 = 0x50;
+ public static final int KEY_NUMPAD3 = 0x51;
+ public static final int KEY_NUMPAD0 = 0x52;
+ public static final int KEY_DECIMAL = 0x53; /* . on numeric keypad */
+ public static final int KEY_F11 = 0x57;
+ public static final int KEY_F12 = 0x58;
+ public static final int KEY_F13 = 0x64; /* (NEC PC98) */
+ public static final int KEY_F14 = 0x65; /* (NEC PC98) */
+ public static final int KEY_F15 = 0x66; /* (NEC PC98) */
+ public static final int KEY_KANA = 0x70; /* (Japanese keyboard) */
+ public static final int KEY_CONVERT = 0x79; /* (Japanese keyboard) */
+ public static final int KEY_NOCONVERT = 0x7B; /* (Japanese keyboard) */
+ public static final int KEY_YEN = 0x7D; /* (Japanese keyboard) */
+ public static final int KEY_NUMPADEQUALS = 0x8D; /* = on numeric keypad (NEC PC98) */
+ public static final int KEY_CIRCUMFLEX = 0x90; /* (Japanese keyboard) */
+ public static final int KEY_AT = 0x91; /* (NEC PC98) */
+ public static final int KEY_COLON = 0x92; /* (NEC PC98) */
+ public static final int KEY_UNDERLINE = 0x93; /* (NEC PC98) */
+ public static final int KEY_KANJI = 0x94; /* (Japanese keyboard) */
+ public static final int KEY_STOP = 0x95; /* (NEC PC98) */
+ public static final int KEY_AX = 0x96; /* (Japan AX) */
+ public static final int KEY_UNLABELED = 0x97; /* (J3100) */
+ public static final int KEY_NUMPADENTER = 0x9C; /* Enter on numeric keypad */
+ public static final int KEY_RCONTROL = 0x9D;
+ public static final int KEY_NUMPADCOMMA = 0xB3; /* , on numeric keypad (NEC PC98) */
+ public static final int KEY_DIVIDE = 0xB5; /* / on numeric keypad */
+ public static final int KEY_SYSRQ = 0xB7;
+ public static final int KEY_RMENU = 0xB8; /* right Alt */
+ public static final int KEY_PAUSE = 0xC5; /* Pause */
+ public static final int KEY_HOME = 0xC7; /* Home on arrow keypad */
+ public static final int KEY_UP = 0xC8; /* UpArrow on arrow keypad */
+ public static final int KEY_PRIOR = 0xC9; /* PgUp on arrow keypad */
+ public static final int KEY_LEFT = 0xCB; /* LeftArrow on arrow keypad */
+ public static final int KEY_RIGHT = 0xCD; /* RightArrow on arrow keypad */
+ public static final int KEY_END = 0xCF; /* End on arrow keypad */
+ public static final int KEY_DOWN = 0xD0; /* DownArrow on arrow keypad */
+ public static final int KEY_NEXT = 0xD1; /* PgDn on arrow keypad */
+ public static final int KEY_INSERT = 0xD2; /* Insert on arrow keypad */
+ public static final int KEY_DELETE = 0xD3; /* Delete on arrow keypad */
+ public static final int KEY_LMETA = 0xDB; /* Left Windows/Option key */
+ /**
+ * The left windows key, mapped to KEY_LMETA
+ *
+ * @deprecated Use KEY_LMETA instead
+ */
+ public static final int KEY_LWIN = KEY_LMETA; /* Left Windows key */
+ public static final int KEY_RMETA = 0xDC; /* Right Windows/Option key */
+ /**
+ * The right windows key, mapped to KEY_RMETA
+ *
+ * @deprecated Use KEY_RMETA instead
+ */
+ public static final int KEY_RWIN = KEY_RMETA; /* Right Windows key */
+ public static final int KEY_APPS = 0xDD; /* AppMenu key */
+ public static final int KEY_POWER = 0xDE;
+ public static final int KEY_SLEEP = 0xDF;
+
+/* public static final int STATE_ON = 0;
+ public static final int STATE_OFF = 1;
+ public static final int STATE_UNKNOWN = 2;
+*/
+ public static final int KEYBOARD_SIZE = 256;
+
+ /** Buffer size in events */
+ private static final int BUFFER_SIZE = 50;
+
+ /** Key names */
+ private static final String[] keyName = new String[255];
+ private static final Map keyMap = new HashMap(253);
+ private static int counter;
+
+ static {
+ // Use reflection to find out key names
+ Field[] field = Keyboard.class.getFields();
+ try {
+ for (int i = 0; i < field.length; i++) {
+ if (Modifier.isStatic(field[i].getModifiers())
+ && Modifier.isPublic(field[i].getModifiers())
+ && Modifier.isFinal(field[i].getModifiers())
+ && field[i].getType().equals(int.class)
+ && field[i].getName().startsWith("KEY_")) {
+
+ int key = field[i].getInt(null);
+ String name = field[i].getName().substring(4);
+ keyName[key] = name;
+ keyMap.put(name, new Integer(key));
+ counter ++;
+ }
+
+ }
+ } catch (Exception e) {
+ }
+
+ }
+
+ /** The number of keys supported */
+ private static final int keyCount = counter;
+
+ /** Has the keyboard been created? */
+ private static boolean created;
+
+ /** Are repeat events enabled? */
+ private static boolean repeat_enabled;
+
+ /** The keys status from the last poll */
+ private static final ByteBuffer keyDownBuffer = BufferUtils.createByteBuffer(KEYBOARD_SIZE);
+
+ /**
+ * The key events from the last read: a sequence of pairs of key number,
+ * followed by state. The state is followed by
+ * a 4 byte code point representing the translated character.
+ */
+ private static ByteBuffer readBuffer;
+
+ /** current event */
+ private static KeyEvent current_event = new KeyEvent();
+
+ /** scratch event */
+ private static KeyEvent tmp_event = new KeyEvent();
+
+ /** One time initialization */
+ private static boolean initialized;
+
+ private static InputImplementation implementation;
+
+ /**
+ * Keyboard cannot be constructed.
+ */
+ private Keyboard() {
+ }
+
+ /**
+ * Static initialization
+ */
+ private static void initialize() {
+ if (initialized)
+ return;
+ Sys.initialize();
+ initialized = true;
+ }
+
+ /**
+ * "Create" the keyboard with the given implementation. This is used
+ * reflectively from AWTInputAdapter.
+ *
+ * @throws LWJGLException if the keyboard could not be created for any reason
+ */
+ private static void create(InputImplementation impl) throws LWJGLException {
+ if (created)
+ return;
+ if (!initialized)
+ initialize();
+ implementation = impl;
+ implementation.createKeyboard();
+ created = true;
+ readBuffer = ByteBuffer.allocate(EVENT_SIZE*BUFFER_SIZE);
+ reset();
+ }
+
+ /**
+ * "Create" the keyboard. The display must first have been created. The
+ * reason for this is so the keyboard has a window to "focus" in.
+ *
+ * @throws LWJGLException if the keyboard could not be created for any reason
+ */
+ public static void create() throws LWJGLException {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!Display.isCreated()) throw new IllegalStateException("Display must be created.");
+
+ create(OpenGLPackageAccess.createImplementation());
+ }
+ }
+
+ private static void reset() {
+ readBuffer.limit(0);
+ for (int i = 0; i < keyDownBuffer.remaining(); i++)
+ keyDownBuffer.put(i, (byte)0);
+ current_event.reset();
+ }
+
+ /**
+ * @return true if the keyboard has been created
+ */
+ public static boolean isCreated() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return created;
+ }
+ }
+
+ /**
+ * "Destroy" the keyboard
+ */
+ public static void destroy() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created)
+ return;
+ created = false;
+ implementation.destroyKeyboard();
+ reset();
+ }
+ }
+
+ /**
+ * Polls the keyboard for its current state. Access the polled values using the
+ * isKeyDown
method.
+ * By using this method, it is possible to "miss" keyboard keys if you don't
+ * poll fast enough.
+ *
+ * To use buffered values, you have to call next
for each event you
+ * want to read. You can query which key caused the event by using
+ * getEventKey
. To get the state of that key, for that event, use
+ * getEventKeyState
- finally use getEventCharacter
to get the
+ * character for that event.
+ *
+ * NOTE: This method does not query the operating system for new events. To do that,
+ * Display.processMessages() (or Display.update()) must be called first.
+ *
+ * @see org.lwjgl.input.Keyboard#isKeyDown(int key)
+ * @see org.lwjgl.input.Keyboard#next()
+ * @see org.lwjgl.input.Keyboard#getEventKey()
+ * @see org.lwjgl.input.Keyboard#getEventKeyState()
+ * @see org.lwjgl.input.Keyboard#getEventCharacter()
+ */
+ public static void poll() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created)
+ throw new IllegalStateException("Keyboard must be created before you can poll the device");
+ implementation.pollKeyboard(keyDownBuffer);
+ read();
+ }
+ }
+
+ private static void read() {
+ readBuffer.compact();
+ implementation.readKeyboard(readBuffer);
+ readBuffer.flip();
+ }
+
+ /**
+ * Checks to see if a key is down.
+ * @param key Keycode to check
+ * @return true if the key is down according to the last poll()
+ */
+ public static boolean isKeyDown(int key) {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created)
+ throw new IllegalStateException("Keyboard must be created before you can query key state");
+ return keyDownBuffer.get(key) != 0;
+ }
+ }
+
+ /**
+ * Checks whether one of the state keys are "active"
+ *
+ * @param key State key to test (KEY_CAPITAL | KEY_NUMLOCK | KEY_SYSRQ)
+ * @return STATE_ON if on, STATE_OFF if off and STATE_UNKNOWN if the state is unknown
+ */
+/* public static int isStateKeySet(int key) {
+ if (!created)
+ throw new IllegalStateException("Keyboard must be created before you can query key state");
+ return implementation.isStateKeySet(key);
+ }
+*/
+ /**
+ * Gets a key's name
+ * @param key The key
+ * @return a String with the key's human readable name in it or null if the key is unnamed
+ */
+ public static synchronized String getKeyName(int key) {
+ return keyName[key];
+ }
+
+ /**
+ * Get's a key's index. If the key is unrecognised then KEY_NONE is returned.
+ * @param keyName The key name
+ */
+ public static synchronized int getKeyIndex(String keyName) {
+ Integer ret = (Integer) keyMap.get(keyName);
+ if (ret == null)
+ return KEY_NONE;
+ else
+ return ret.intValue();
+ }
+
+ /**
+ * Gets the number of keyboard events waiting after doing a buffer enabled poll().
+ * @return the number of keyboard events
+ */
+ public static int getNumKeyboardEvents() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created)
+ throw new IllegalStateException("Keyboard must be created before you can read events");
+ int old_position = readBuffer.position();
+ int num_events = 0;
+ while (readNext(tmp_event) && (!tmp_event.repeat || repeat_enabled))
+ num_events++;
+ readBuffer.position(old_position);
+ return num_events;
+ }
+ }
+
+ /**
+ * Gets the next keyboard event. You can query which key caused the event by using
+ * getEventKey
. To get the state of that key, for that event, use
+ * getEventKeyState
- finally use getEventCharacter
to get the
+ * character for that event.
+ *
+ * @see org.lwjgl.input.Keyboard#getEventKey()
+ * @see org.lwjgl.input.Keyboard#getEventKeyState()
+ * @see org.lwjgl.input.Keyboard#getEventCharacter()
+ * @return true if a keyboard event was read, false otherwise
+ */
+ public static boolean next() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created)
+ throw new IllegalStateException("Keyboard must be created before you can read events");
+
+ boolean result;
+ while ((result = readNext(current_event)) && current_event.repeat && !repeat_enabled)
+ ;
+ return result;
+ }
+ }
+
+ /**
+ * Controls whether repeat events are reported or not. If repeat events
+ * are enabled, key down events are reported when a key is pressed and held for
+ * a OS dependent amount of time. To distinguish a repeat event from a normal event,
+ * use isRepeatEvent().
+ *
+ * @see org.lwjgl.input.Keyboard#getEventKey()
+ */
+ public static void enableRepeatEvents(boolean enable) {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ repeat_enabled = enable;
+ }
+ }
+
+ /**
+ * Check whether repeat events are currently reported or not.
+ *
+ * @return true is repeat events are reported, false if not.
+ * @see org.lwjgl.input.Keyboard#getEventKey()
+ */
+ public static boolean areRepeatEventsEnabled() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return repeat_enabled;
+ }
+ }
+
+ private static boolean readNext(KeyEvent event) {
+ if (readBuffer.hasRemaining()) {
+ event.key = readBuffer.getInt() & 0xFF;
+ event.state = readBuffer.get() != 0;
+ event.character = readBuffer.getInt();
+ event.nanos = readBuffer.getLong();
+ event.repeat = readBuffer.get() == 1;
+ return true;
+ } else
+ return false;
+ }
+
+ /**
+ * @return Number of keys on this keyboard
+ */
+ public static int getKeyCount() {
+ return keyCount;
+ }
+
+ /**
+ * @return The character from the current event
+ */
+ public static char getEventCharacter() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return (char)current_event.character;
+ }
+ }
+
+ /**
+ * Please note that the key code returned is NOT valid against the
+ * current keyboard layout. To get the actual character pressed call
+ * getEventCharacter
+ *
+ * @return The key from the current event
+ */
+ public static int getEventKey() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return current_event.key;
+ }
+ }
+
+ /**
+ * Gets the state of the tkey that generated the
+ * current event
+ *
+ * @return True if key was down, or false if released
+ */
+ public static boolean getEventKeyState() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return current_event.state;
+ }
+ }
+
+ /**
+ * Gets the time in nanoseconds of the current event.
+ * Only useful for relative comparisons with other
+ * Keyboard events, as the absolute time has no defined
+ * origin.
+ * @return The time in nanoseconds of the current event
+ */
+ public static long getEventNanoseconds() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return current_event.nanos;
+ }
+ }
+
+ /**
+ * @see org.lwjgl.input.Keyboard#enableRepeatEvents(boolean)
+ * @return true if the current event is a repeat event, false if
+ * the current event is not a repeat even or if repeat events are disabled.
+ */
+ public static boolean isRepeatEvent() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return current_event.repeat;
+ }
+ }
+
+ private final static class KeyEvent {
+ /** The current keyboard character being examined */
+ private int character;
+
+ /** The current keyboard event key being examined */
+ private int key;
+
+ /** The current state of the key being examined in the event queue */
+ private boolean state;
+
+ /** The current event time */
+ private long nanos;
+
+ /** Is the current event a repeated event? */
+ private boolean repeat;
+
+ private void reset() {
+ character = 0;
+ key = 0;
+ state = false;
+ repeat = false;
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/input/Mouse.java b/src/java/org/lwjgl/input/Mouse.java
new file mode 100644
index 0000000..9195a2e
--- /dev/null
+++ b/src/java/org/lwjgl/input/Mouse.java
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 2002-2008 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.input;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.InputImplementation;
+
+
+/**
+ *
+ * A raw Mouse interface. This can be used to poll the current state of the
+ * mouse buttons, and determine the mouse movement delta since the last poll.
+ *
+ * n buttons supported, n being a native limit. A scrolly wheel is also
+ * supported, if one such is available. Movement is reported as delta from
+ * last position or as an absolute position. If the window has been created
+ * the absolute position will be clamped to 0 - width | height.
+ *
+ * @author cix_foo
+ * @author elias_naur
+ * @author Brian Matzon
+ * @version $Revision: 3297 $
+ * $Id: Mouse.java 3297 2010-03-27 16:04:30Z kappa1 $
+ */
+public class Mouse {
+ /** Internal use - event size in bytes */
+ public static final int EVENT_SIZE = 1 + 1 + 4 + 4 + 4 + 8;
+
+ /** Has the mouse been created? */
+ private static boolean created;
+
+ /** The mouse buttons status from the last poll */
+ private static ByteBuffer buttons;
+
+ /** Mouse absolute X position in pixels */
+ private static int x;
+
+ /** Mouse absolute Y position in pixels */
+ private static int y;
+
+ /** Buffer to hold the deltas dx, dy and dwheel */
+ private static IntBuffer coord_buffer;
+
+ /** Delta X */
+ private static int dx;
+
+ /** Delta Y */
+ private static int dy;
+
+ /** Delta Z */
+ private static int dwheel;
+
+ /** Number of buttons supported by the mouse */
+ private static int buttonCount = -1;
+
+ /** Does this mouse support a scroll wheel */
+ private static boolean hasWheel;
+
+ /** The current native cursor, if any */
+ private static Cursor currentCursor;
+
+ /** Button names. These are set upon create(), to names like BUTTON0, BUTTON1, etc. */
+ private static String[] buttonName;
+
+ /** hashmap of button names, for fast lookup */
+ private static final Map buttonMap = new HashMap(16);
+
+ /** Lazy initialization */
+ private static boolean initialized;
+
+ /** The mouse button events from the last read */
+ private static ByteBuffer readBuffer;
+
+ /** The current mouse event button being examined */
+ private static int eventButton;
+
+ /** The current state of the button being examined in the event queue */
+ private static boolean eventState;
+
+ /** The current delta of the mouse in the event queue */
+ private static int event_dx;
+ private static int event_dy;
+ private static int event_dwheel;
+ /** The current absolute position of the mouse in the event queue */
+ private static int event_x;
+ private static int event_y;
+ private static long event_nanos;
+ /** The position of the mouse it was grabbed at */
+ private static int grab_x;
+ private static int grab_y;
+
+ /** Buffer size in events */
+ private static final int BUFFER_SIZE = 50;
+
+ private static boolean isGrabbed;
+
+ private static InputImplementation implementation;
+
+ /** Whether we need cursor animation emulation */
+ private static final boolean emulateCursorAnimation = LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_WINDOWS ||
+ LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_MACOSX;
+
+ private static final boolean allowNegativeMouseCoords = getPrivilegedBoolean("org.lwjgl.input.Mouse.allowNegativeMouseCoords");
+
+ /**
+ * Mouse cannot be constructed.
+ */
+ private Mouse() {
+ }
+
+ /**
+ * Gets the currently bound native cursor, if any.
+ *
+ * @return the currently bound native cursor, if any.
+ */
+ public static Cursor getNativeCursor() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return currentCursor;
+ }
+ }
+
+ /**
+ * Binds a native cursor. If the cursor argument is null, any
+ * currently bound native cursor is disabled, and the cursor reverts
+ * to the default operating system supplied cursor.
+ *
+ * NOTE: The native cursor is not constrained to the window, but
+ * relative events will not be generated if the cursor is outside.
+ *
+ * @param cursor the native cursor object to bind. May be null.
+ * @return The previous Cursor object set, or null.
+ * @throws LWJGLException if the cursor could not be set for any reason
+ */
+ public static Cursor setNativeCursor(Cursor cursor) throws LWJGLException {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if ((Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) == 0)
+ throw new IllegalStateException("Mouse doesn't support native cursors");
+ Cursor oldCursor = currentCursor;
+ currentCursor = cursor;
+ if (isCreated()) {
+ if (currentCursor != null) {
+ implementation.setNativeCursor(currentCursor.getHandle());
+ currentCursor.setTimeout();
+ } else {
+ implementation.setNativeCursor(null);
+ }
+ }
+ return oldCursor;
+ }
+ }
+
+ /**
+ * Set the position of the cursor. If the cursor is not grabbed,
+ * the native cursor is moved to the new position.
+ *
+ * @param new_x The x coordinate of the new cursor position in OpenGL coordinates relative
+ * to the window origin.
+ * @param new_y The y coordinate of the new cursor position in OpenGL coordinates relative
+ * to the window origin.
+ */
+ public static void setCursorPosition(int new_x, int new_y) {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!isCreated())
+ throw new IllegalStateException("Mouse is not created");
+ x = event_x = new_x;
+ y = event_y = new_y;
+ if (!isGrabbed() && (Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) != 0) {
+ implementation.setCursorPosition(x, y);
+ }
+ else {
+ grab_x = new_x;
+ grab_y = new_y;
+ }
+ }
+ }
+
+ /**
+ * Static initialization
+ */
+ private static void initialize() {
+ Sys.initialize();
+
+ // Assign names to all the buttons
+ buttonName = new String[16];
+ for (int i = 0; i < 16; i++) {
+ buttonName[i] = "BUTTON" + i;
+ buttonMap.put(buttonName[i], new Integer(i));
+ }
+
+ initialized = true;
+ }
+
+ private static void resetMouse() {
+ dx = dy = dwheel = 0;
+ readBuffer.position(readBuffer.limit());
+ }
+
+ static InputImplementation getImplementation() {
+ return implementation;
+ }
+
+ /**
+ * "Create" the mouse with the given custom implementation. This is used
+ * reflectively by AWTInputAdapter.
+ *
+ * @throws LWJGLException if the mouse could not be created for any reason
+ */
+ private static void create(InputImplementation impl) throws LWJGLException {
+ if (created)
+ return;
+ if (!initialized)
+ initialize();
+ implementation = impl;
+ implementation.createMouse();
+ hasWheel = implementation.hasWheel();
+ created = true;
+
+ // set mouse buttons
+ buttonCount = implementation.getButtonCount();
+ buttons = BufferUtils.createByteBuffer(buttonCount);
+ coord_buffer = BufferUtils.createIntBuffer(3);
+ if (currentCursor != null && implementation.getNativeCursorCapabilities() != 0)
+ setNativeCursor(currentCursor);
+ readBuffer = ByteBuffer.allocate(EVENT_SIZE * BUFFER_SIZE);
+ readBuffer.limit(0);
+ setGrabbed(isGrabbed);
+ }
+
+ /**
+ * "Create" the mouse. The display must first have been created.
+ * Initially, the mouse is not grabbed and the delta values are reported
+ * with respect to the center of the display.
+ *
+ * @throws LWJGLException if the mouse could not be created for any reason
+ */
+ public static void create() throws LWJGLException {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!Display.isCreated()) throw new IllegalStateException("Display must be created.");
+
+ create(OpenGLPackageAccess.createImplementation());
+ }
+ }
+
+ /**
+ * @return true if the mouse has been created
+ */
+ public static boolean isCreated() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return created;
+ }
+ }
+
+ /**
+ * "Destroy" the mouse.
+ */
+ public static void destroy() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created) return;
+ created = false;
+ buttons = null;
+ coord_buffer = null;
+
+ implementation.destroyMouse();
+ }
+ }
+
+ /**
+ * Polls the mouse for its current state. Access the polled values using the
+ * get methods.
+ * By using this method, it is possible to "miss" mouse click events if you don't
+ * poll fast enough.
+ *
+ * To use buffered values, you have to call next
for each event you
+ * want to read. You can query which button caused the event by using
+ * getEventButton
. To get the state of that button, for that event, use
+ * getEventButtonState
.
+ *
+ * NOTE: This method does not query the operating system for new events. To do that,
+ * Display.processMessages() (or Display.update()) must be called first.
+ *
+ * @see org.lwjgl.input.Mouse#next()
+ * @see org.lwjgl.input.Mouse#getEventButton()
+ * @see org.lwjgl.input.Mouse#getEventButtonState()
+ * @see org.lwjgl.input.Mouse#isButtonDown(int button)
+ * @see org.lwjgl.input.Mouse#getX()
+ * @see org.lwjgl.input.Mouse#getY()
+ * @see org.lwjgl.input.Mouse#getDX()
+ * @see org.lwjgl.input.Mouse#getDY()
+ * @see org.lwjgl.input.Mouse#getDWheel()
+ */
+ public static void poll() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created) throw new IllegalStateException("Mouse must be created before you can poll it");
+ implementation.pollMouse(coord_buffer, buttons);
+
+ /* If we're grabbed, poll returns mouse deltas, if not it returns absolute coordinates */
+ int poll_coord1 = coord_buffer.get(0);
+ int poll_coord2 = coord_buffer.get(1);
+ /* The wheel is always relative */
+ int poll_dwheel = coord_buffer.get(2);
+
+ if (isGrabbed()) {
+ dx += poll_coord1;
+ dy += poll_coord2;
+ x += poll_coord1;
+ y += poll_coord2;
+ } else {
+ dx = poll_coord1 - x;
+ dy = poll_coord2 - y;
+ x = poll_coord1;
+ y = poll_coord2;
+ }
+ if(!allowNegativeMouseCoords) {
+ x = Math.min(implementation.getWidth() - 1, Math.max(0, x));
+ y = Math.min(implementation.getHeight() - 1, Math.max(0, y));
+ }
+ dwheel += poll_dwheel;
+ read();
+ }
+ }
+
+ private static void read() {
+ readBuffer.compact();
+ implementation.readMouse(readBuffer);
+ readBuffer.flip();
+ }
+
+ /**
+ * See if a particular mouse button is down.
+ *
+ * @param button The index of the button you wish to test (0..getButtonCount-1)
+ * @return true if the specified button is down
+ */
+ public static boolean isButtonDown(int button) {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created) throw new IllegalStateException("Mouse must be created before you can poll the button state");
+ if (button >= buttonCount || button < 0)
+ return false;
+ else
+ return buttons.get(button) == 1;
+ }
+ }
+
+ /**
+ * Gets a button's name
+ * @param button The button
+ * @return a String with the button's human readable name in it or null if the button is unnamed
+ */
+ public static String getButtonName(int button) {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (button >= buttonName.length || button < 0)
+ return null;
+ else
+ return buttonName[button];
+ }
+ }
+
+ /**
+ * Get's a button's index. If the button is unrecognised then -1 is returned.
+ * @param buttonName The button name
+ */
+ public static int getButtonIndex(String buttonName) {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ Integer ret = (Integer) buttonMap.get(buttonName);
+ if (ret == null)
+ return -1;
+ else
+ return ret.intValue();
+ }
+ }
+
+ /**
+ * Gets the next mouse event. You can query which button caused the event by using
+ * getEventButton()
(if any). To get the state of that key, for that event, use
+ * getEventButtonState
. To get the current mouse delta values use getEventDX()
,
+ * getEventDY()
and getEventDZ()
.
+ * @see org.lwjgl.input.Mouse#getEventButton()
+ * @see org.lwjgl.input.Mouse#getEventButtonState()
+ * @return true if a mouse event was read, false otherwise
+ */
+ public static boolean next() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (!created) throw new IllegalStateException("Mouse must be created before you can read events");
+ if (readBuffer.hasRemaining()) {
+ eventButton = readBuffer.get();
+ eventState = readBuffer.get() != 0;
+ if (isGrabbed()) {
+ event_dx = readBuffer.getInt();
+ event_dy = readBuffer.getInt();
+ event_x += event_dx;
+ event_y += event_dy;
+ } else {
+ int new_event_x = readBuffer.getInt();
+ int new_event_y = readBuffer.getInt();
+ event_dx = new_event_x - event_x;
+ event_dy = new_event_y - event_y;
+ event_x = new_event_x;
+ event_y = new_event_y;
+ }
+ event_x = Math.min(implementation.getWidth() - 1, Math.max(0, event_x));
+ event_y = Math.min(implementation.getHeight() - 1, Math.max(0, event_y));
+ event_dwheel = readBuffer.getInt();
+ event_nanos = readBuffer.getLong();
+ return true;
+ } else
+ return false;
+ }
+ }
+
+ /**
+ * @return Current events button. Returns -1 if no button state was changed
+ */
+ public static int getEventButton() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return eventButton;
+ }
+ }
+
+ /**
+ * Get the current events button state.
+ * @return Current events button state.
+ */
+ public static boolean getEventButtonState() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return eventState;
+ }
+ }
+
+ /**
+ * @return Current events delta x. Only valid when the mouse is grabbed.
+ */
+ public static int getEventDX() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return event_dx;
+ }
+ }
+
+ /**
+ * @return Current events delta y. Only valid when the mouse is grabbed.
+ */
+ public static int getEventDY() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return event_dy;
+ }
+ }
+
+ /**
+ * @return Current events absolute x. Only valid when the mouse is not grabbed.
+ */
+ public static int getEventX() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return event_x;
+ }
+ }
+
+ /**
+ * @return Current events absolute y. Only valid when the mouse is not grabbed.
+ */
+ public static int getEventY() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return event_y;
+ }
+ }
+
+ /**
+ * @return Current events delta z
+ */
+ public static int getEventDWheel() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return event_dwheel;
+ }
+ }
+
+ /**
+ * Gets the time in nanoseconds of the current event.
+ * Only useful for relative comparisons with other
+ * Mouse events, as the absolute time has no defined
+ * origin.
+ *
+ * @return The time in nanoseconds of the current event
+ */
+ public static long getEventNanoseconds() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return event_nanos;
+ }
+ }
+
+ /**
+ * Retrieves the absolute position. It will be clamped to
+ * 0...width-1.
+ *
+ * @return Absolute x axis position of mouse
+ */
+ public static int getX() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return x;
+ }
+ }
+
+ /**
+ * Retrieves the absolute position. It will be clamped to
+ * 0...height-1.
+ *
+ * @return Absolute y axis position of mouse
+ */
+ public static int getY() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return y;
+ }
+ }
+
+ /**
+ * @return Movement on the x axis since last time getDX() was called. Only valid when the mouse is grabbed.
+ */
+ public static int getDX() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ int result = dx;
+ dx = 0;
+ return result;
+ }
+ }
+
+ /**
+ * @return Movement on the y axis since last time getDY() was called. Only valid when the mouse is grabbed.
+ */
+ public static int getDY() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ int result = dy;
+ dy = 0;
+ return result;
+ }
+ }
+
+ /**
+ * @return Movement of the wheel since last time getDWheel() was called
+ */
+ public static int getDWheel() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ int result = dwheel;
+ dwheel = 0;
+ return result;
+ }
+ }
+
+ /**
+ * @return Number of buttons on this mouse
+ */
+ public static int getButtonCount() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return buttonCount;
+ }
+ }
+
+ /**
+ * @return Whether or not this mouse has wheel support
+ */
+ public static boolean hasWheel() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return hasWheel;
+ }
+ }
+
+ /**
+ * @return whether or not the mouse has grabbed the cursor
+ */
+ public static boolean isGrabbed() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ return isGrabbed;
+ }
+ }
+
+ /**
+ * Sets whether or not the mouse has grabbed the cursor
+ * (and thus hidden). If grab is false, the getX() and getY()
+ * will return delta movement in pixels clamped to the display
+ * dimensions, from the center of the display.
+ *
+ * @param grab whether the mouse should be grabbed
+ */
+ public static void setGrabbed(boolean grab) {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ boolean grabbed = isGrabbed;
+ isGrabbed = grab;
+ if (isCreated()) {
+ if (grab && !grabbed) {
+ // store location mouse was grabbed
+ grab_x = x;
+ grab_y = y;
+ }
+ else if (!grab && grabbed) {
+ // move mouse back to location it was grabbed before ungrabbing
+ if ((Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) != 0)
+ implementation.setCursorPosition(grab_x, grab_y);
+ }
+
+ implementation.grabMouse(grab);
+ // Get latest values from native side
+ poll();
+ event_x = x;
+ event_y = y;
+ resetMouse();
+ }
+ }
+ }
+
+ /**
+ * Updates the cursor, so that animation can be changed if needed.
+ * This method is called automatically by the window on its update, and
+ * shouldn't be called otherwise
+ */
+ public static void updateCursor() {
+ synchronized (OpenGLPackageAccess.global_lock) {
+ if (emulateCursorAnimation && currentCursor != null && currentCursor.hasTimedOut() && Mouse.isInsideWindow()) {
+ currentCursor.nextCursor();
+ try {
+ setNativeCursor(currentCursor);
+ } catch (LWJGLException e) {
+ if (LWJGLUtil.DEBUG) e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /** Gets a boolean property as a privileged action. */
+ static boolean getPrivilegedBoolean(final String property_name) {
+ Boolean value = (Boolean)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return new Boolean(Boolean.getBoolean(property_name));
+ }
+ });
+ return value.booleanValue();
+ }
+
+ /**
+ * Retrieves whether or not the mouse cursor is within the bounds of the window.
+ * If the mouse cursor was moved outside the display during a drag, then the result of calling
+ * this method will be true until the button is released.
+ * @return true if mouse is inside display, false otherwise.
+ */
+ public static boolean isInsideWindow() {
+ return implementation.isInsideWindow();
+ }
+}
diff --git a/src/java/org/lwjgl/input/OpenGLPackageAccess.java b/src/java/org/lwjgl/input/OpenGLPackageAccess.java
new file mode 100644
index 0000000..c4cb792
--- /dev/null
+++ b/src/java/org/lwjgl/input/OpenGLPackageAccess.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2002-2008 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.input;
+
+import org.lwjgl.opengl.InputImplementation;
+import org.lwjgl.opengl.Display;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+
+/**
+ * This class contains utilities for accessing the org.lwjgl.opengl
+ * package through (privileged) reflection.
+ */
+final class OpenGLPackageAccess {
+ final static Object global_lock;
+
+ static {
+ try {
+ global_lock = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ Field lock_field = Class.forName("org.lwjgl.opengl.GlobalLock").getDeclaredField("lock");
+ lock_field.setAccessible(true);
+ return lock_field.get(null);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw new Error(e);
+ }
+ }
+
+ static InputImplementation createImplementation() {
+ /* Use reflection since we can't make Display.getImplementation
+ * public
+ */
+ try {
+ return (InputImplementation)AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ Method getImplementation_method = Display.class.getDeclaredMethod("getImplementation", null);
+ getImplementation_method.setAccessible(true);
+ return getImplementation_method.invoke(null, null);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw new Error(e);
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/openal/AL.java b/src/java/org/lwjgl/openal/AL.java
new file mode 100644
index 0000000..a25a080
--- /dev/null
+++ b/src/java/org/lwjgl/openal/AL.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2002-2008 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.openal;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+
+/**
+ *
+ * The AL class implements the actual creation code for linking to the native library
+ * OpenAL.
+ *
+ *
+ * @author Brian Matzon
+ * @version $Revision: 3182 $
+ * $Id: AL.java 3182 2009-03-17 21:36:18Z matzon $
+ */
+public final class AL {
+ /** ALCdevice instance. */
+ protected static ALCdevice device;
+
+ /** Current ALCcontext. */
+ protected static ALCcontext context;
+
+ /** Have we been created? */
+ private static boolean created;
+
+ static {
+ Sys.initialize();
+ }
+
+ private AL() {
+ }
+
+ /**
+ * Native method to create AL instance
+ *
+ * @param oalPaths Array of strings containing paths to search for OpenAL library
+ */
+ private static native void nCreate(String oalPath) throws LWJGLException;
+
+ /**
+ * Native method to create AL instance from the Mac OS X 10.4 OpenAL framework.
+ * It is only defined in the Mac OS X native library.
+ *
+ * @param oalPaths Array of strings containing paths to search for OpenAL library
+ */
+ private static native void nCreateDefault() throws LWJGLException;
+
+ /**
+ * Native method the destroy the AL
+ */
+ private static native void nDestroy();
+
+ /**
+ * @return true if AL has been created
+ */
+ public static boolean isCreated() {
+ return created;
+ }
+
+ /**
+ * Creates an OpenAL instance. Using this constructor will cause OpenAL to
+ * open the device using supplied device argument, and create a context using the context values
+ * supplied.
+ *
+ * @param deviceArguments Arguments supplied to native device
+ * @param contextFrequency Frequency for mixing output buffer, in units of Hz (Common values include 11025, 22050, and 44100).
+ * @param contextRefresh Refresh intervalls, in units of Hz.
+ * @param contextSynchronized Flag, indicating a synchronous context.*
+ */
+ public static void create(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized)
+ throws LWJGLException {
+ create(deviceArguments, contextFrequency, contextRefresh, contextSynchronized, true);
+ }
+
+ /**
+ * @param openDevice Whether to automatically open the device
+ * @see #create(String, int, int, boolean)
+ */
+ public static void create(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized, boolean openDevice)
+ throws LWJGLException {
+
+ if (created)
+ throw new IllegalStateException("Only one OpenAL context may be instantiated at any one time.");
+ String libname;
+ String[] library_names;
+ switch (LWJGLUtil.getPlatform()) {
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ libname = "OpenAL32";
+ library_names = new String[]{"OpenAL64.dll", "OpenAL32.dll"};
+ break;
+ case LWJGLUtil.PLATFORM_LINUX:
+ libname = "openal";
+ library_names = new String[]{"libopenal64.so", "libopenal.so", "libopenal.so.0"};
+ break;
+ case LWJGLUtil.PLATFORM_MACOSX:
+ libname = "openal";
+ library_names = new String[]{"openal.dylib"};
+ break;
+ default:
+ throw new LWJGLException("Unknown platform: " + LWJGLUtil.getPlatform());
+ }
+ String[] oalPaths = LWJGLUtil.getLibraryPaths(libname, library_names, AL.class.getClassLoader());
+ LWJGLUtil.log("Found " + oalPaths.length + " OpenAL paths");
+ for (int i = 0; i < oalPaths.length; i++) {
+ try {
+ nCreate(oalPaths[i]);
+ created = true;
+ init(deviceArguments, contextFrequency, contextRefresh, contextSynchronized, openDevice);
+ break;
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to load " + oalPaths[i] + ": " + e.getMessage());
+ }
+ }
+ if (!created && LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_MACOSX) {
+ // Try to load OpenAL from the framework instead
+ nCreateDefault();
+ created = true;
+ init(deviceArguments, contextFrequency, contextRefresh, contextSynchronized, openDevice);
+ }
+ if (!created)
+ throw new LWJGLException("Could not locate OpenAL library.");
+ }
+
+ private static void init(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized, boolean openDevice) throws LWJGLException {
+ try {
+ AL10.initNativeStubs();
+ ALC10.initNativeStubs();
+
+ if(openDevice) {
+ device = ALC10.alcOpenDevice(deviceArguments);
+ if (device == null)
+ throw new LWJGLException("Could not open ALC device");
+
+ if (contextFrequency == -1) {
+ context = ALC10.alcCreateContext(device, null);
+ } else {
+ context = ALC10.alcCreateContext(device,
+ ALCcontext.createAttributeList(contextFrequency, contextRefresh,
+ contextSynchronized ? ALC10.ALC_TRUE : ALC10.ALC_FALSE));
+ }
+ ALC10.alcMakeContextCurrent(context);
+ }
+ } catch (LWJGLException e) {
+ destroy();
+ throw e;
+ }
+
+ ALC11.initialize();
+ }
+
+ /**
+ * Creates an OpenAL instance. The empty create will cause OpenAL to
+ * open the default device, and create a context using default values.
+ * This method used to use default values that the OpenAL implementation
+ * chose but this produces unexpected results on some systems; so now
+ * it defaults to 44100Hz mixing @ 60Hz refresh.
+ */
+ public static void create() throws LWJGLException {
+ create(null, 44100, 60, false);
+ }
+
+ /**
+ * Exit cleanly by calling destroy.
+ */
+ public static void destroy() {
+ if (context != null) {
+ ALC10.alcMakeContextCurrent(null);
+ ALC10.alcDestroyContext(context);
+ context = null;
+ }
+ if (device != null) {
+ boolean result = ALC10.alcCloseDevice(device);
+ device = null;
+ }
+ resetNativeStubs(AL10.class);
+ resetNativeStubs(ALC10.class);
+ resetNativeStubs(ALC11.class);
+
+ if (created)
+ nDestroy();
+ created = false;
+ }
+
+ private static native void resetNativeStubs(Class clazz);
+
+ /**
+ * @return handle to the default AL context.
+ */
+ public static ALCcontext getContext() {
+ return context;
+ }
+
+ /**
+ * @return handle to the default AL device.
+ */
+ public static ALCdevice getDevice() {
+ return device;
+ }
+}
diff --git a/src/java/org/lwjgl/openal/ALC10.java b/src/java/org/lwjgl/openal/ALC10.java
new file mode 100644
index 0000000..45f81b8
--- /dev/null
+++ b/src/java/org/lwjgl/openal/ALC10.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2002-2008 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.openal;
+
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+import java.util.HashMap;
+
+import org.lwjgl.BufferChecks;
+import org.lwjgl.LWJGLException;
+
+/**
+ *
+ *
+ * ALC introduces the notion of a Device. A Device can be, depending on the
+ * implementation, a hardware device, or a daemon/OS service/actual server. This
+ * mechanism also permits different drivers (and hardware) to coexist within the same
+ * system, as well as allowing several applications to share system resources for audio,
+ * including a single hardware output device. The details are left to the
+ * implementation, which has to map the available backends to unique device
+ * specifiers (represented as strings).
+ *
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2286 $
+ * $Id: ALC.java 2286 2006-03-23 19:32:21 +0000 (to, 23 mar 2006) matzon $
+ */
+public final class ALC10 {
+
+ /** List of active contexts */
+ static HashMap contexts = new HashMap();
+
+ /** List of active devices */
+ static HashMap devices = new HashMap();
+
+ /** Bad value */
+ public static final int ALC_INVALID = 0;
+
+ /** Boolean False */
+ public static final int ALC_FALSE = 0;
+
+ /** Boolean True */
+ public static final int ALC_TRUE = 1;
+
+ /** Errors: No Error */
+ public static final int ALC_NO_ERROR = ALC_FALSE;
+
+ /** Major version query. */
+ public static final int ALC_MAJOR_VERSION = 0x1000;
+
+ /** Minor version query. */
+ public static final int ALC_MINOR_VERSION = 0x1001;
+
+ /**
+ * The size required for the zero-terminated attributes list, for the current context.
+ **/
+ public static final int ALC_ATTRIBUTES_SIZE = 0x1002;
+
+ /**
+ * Expects a destination of ALC_CURRENT_ATTRIBUTES_SIZE,
+ * and provides the attribute list for the current context of the specified device.
+ */
+ public static final int ALC_ALL_ATTRIBUTES = 0x1003;
+
+ /** The specifier string for the default device */
+ public static final int ALC_DEFAULT_DEVICE_SPECIFIER = 0x1004;
+
+ /** The specifier string for the device */
+ public static final int ALC_DEVICE_SPECIFIER = 0x1005;
+
+ /** The extensions string for diagnostics and printing */
+ public static final int ALC_EXTENSIONS = 0x1006;
+
+ /** Frequency for mixing output buffer, in units of Hz. */
+ public static final int ALC_FREQUENCY = 0x1007;
+
+ /** Refresh intervalls, in units of Hz. */
+ public static final int ALC_REFRESH = 0x1008;
+
+ /** Flag, indicating a synchronous context. */
+ public static final int ALC_SYNC = 0x1009;
+
+ /** The device argument does not name a valid device */
+ public static final int ALC_INVALID_DEVICE = 0xA001;
+
+ /** The context argument does not name a valid context */
+ public static final int ALC_INVALID_CONTEXT = 0xA002;
+
+ /**
+ * A function was called at inappropriate time, or in an inappropriate way,
+ * causing an illegal state. This can be an incompatible ALenum, object ID,
+ * and/or function.
+ */
+ public static final int ALC_INVALID_ENUM = 0xA003;
+
+ /**
+ * Illegal value passed as an argument to an AL call.
+ * Applies to parameter values, but not to enumerations.
+ */
+ public static final int ALC_INVALID_VALUE = 0xA004;
+
+ /**
+ * A function could not be completed, because there is not enough
+ * memory available.
+ */
+ public static final int ALC_OUT_OF_MEMORY = 0xA005;
+
+ static native void initNativeStubs() throws LWJGLException;
+
+ /**
+ * The application can obtain certain strings from ALC.
+ *
+ * ALC_DEFAULT_DEVICE_SPECIFIER
- The specifer string for the default device
+ * ALC_DEVICE_SPECIFIER
- The specifer string for the device
+ * ALC_EXTENSIONS
- The extensions string for diagnostics and printing.
+ *
+ * In addition, printable error message strings are provided for all valid error tokens,
+ * including ALC_NO_ERROR
,ALC_INVALID_DEVICE
, ALC_INVALID_CONTEXT
,
+ * ALC_INVALID_ENUM
, ALC_INVALID_VALUE
.
+ *
+ * @param pname Property to get
+ * @return String property from device
+ */
+ public static String alcGetString(ALCdevice device, int pname) {
+ String result;
+ result = nalcGetString(getDevice(device), pname);
+ Util.checkALCError(device);
+ return result;
+ }
+ native static String nalcGetString(long device, int pname);
+
+ /**
+ * The application can query ALC for information using an integer query function.
+ * For some tokens, null
is a legal deviceHandle. In other cases, specifying a null
+ * device will generate an ALC_INVALID_DEVICE
error. The application has to
+ * specify the size of the destination buffer provided. A null
destination or a zero
+ * size parameter will cause ALC to ignore the query.
+ *
+ * ALC_MAJOR_VERSION
- Major version query.
+ * ALC_MINOR_VERSION
- Minor version query.
+ * ALC_ATTRIBUTES_SIZE
- The size required for the zero-terminated attributes list,
+ * for the current context. null
is an invalid device. null
(no current context
+ * for the specified device) is legal.
+ * ALC_ALL_ATTRIBUTES
- Expects a destination of ALC_CURRENT_ATTRIBUTES_SIZE
,
+ * and provides the attribute list for the current context of the specified device.
+ * null
is an invalid device. null
(no current context for the specified device)
+ * will return the default attributes defined by the specified device.
+ *
+ * @param pname Property to get
+ * @param integerdata ByteBuffer to write integers to
+ */
+ public static void alcGetInteger(ALCdevice device, int pname, IntBuffer integerdata) {
+ BufferChecks.checkDirect(integerdata);
+ nalcGetIntegerv(getDevice(device), pname, integerdata.remaining(), integerdata, integerdata.position());
+ Util.checkALCError(device);
+ }
+ native static void nalcGetIntegerv(long device, int pname, int size, Buffer integerdata, int offset);
+
+ /**
+ * The alcOpenDevice
function allows the application (i.e. the client program) to
+ * connect to a device (i.e. the server).
+ *
+ * If the function returns null
, then no sound driver/device has been found. The
+ * argument is a null terminated string that requests a certain device or device
+ * configuration. If null
is specified, the implementation will provide an
+ * implementation specific default.
+ *
+ * @param devicename name of device to open
+ * @return opened device, or null
+ */
+ public static ALCdevice alcOpenDevice(String devicename) {
+ long device_address = nalcOpenDevice(devicename);
+ if(device_address != 0) {
+ ALCdevice device = new ALCdevice(device_address);
+ synchronized (ALC10.devices) {
+ devices.put(new Long(device_address), device);
+ }
+ return device;
+ }
+ return null;
+ }
+ native static long nalcOpenDevice(String devicename);
+
+ /**
+ * The alcCloseDevice
function allows the application (i.e. the client program) to
+ * disconnect from a device (i.e. the server).
+ *
+ * If deviceHandle is null
or invalid, an ALC_INVALID_DEVICE
error will be
+ * generated. Once closed, a deviceHandle is invalid.
+ *
+ * @param device address of native device to close
+ */
+ public static boolean alcCloseDevice(ALCdevice device) {
+ boolean result = nalcCloseDevice(getDevice(device));
+ synchronized (devices) {
+ device.setInvalid();
+ devices.remove(new Long(device.device));
+ }
+ return result;
+
+ }
+ native static boolean nalcCloseDevice(long device);
+
+ /**
+ * A context is created using alcCreateContext
. The device parameter has to be a valid
+ * device. The attribute list can be null
, or a zero terminated list of integer pairs
+ * composed of valid ALC attribute tokens and requested values.
+ *
+ * Context creation will fail if the application requests attributes that, by themselves,
+ * can not be provided. Context creation will fail if the combination of specified
+ * attributes can not be provided. Context creation will fail if a specified attribute, or
+ * the combination of attributes, does not match the default values for unspecified
+ * attributes.
+ *
+ * @param device address of device to associate context to
+ * @param attrList Buffer to read attributes from
+ * @return New context, or null if creation failed
+ */
+ public static ALCcontext alcCreateContext(ALCdevice device, IntBuffer attrList) {
+ long context_address = nalcCreateContext(getDevice(device), attrList);
+ Util.checkALCError(device);
+
+ if(context_address != 0) {
+ ALCcontext context = new ALCcontext(context_address);
+ synchronized (ALC10.contexts) {
+ contexts.put(new Long(context_address), context);
+ device.addContext(context);
+ }
+ return context;
+ }
+ return null;
+ }
+ native static long nalcCreateContext(long device, IntBuffer attrList);
+
+ /**
+ * To make a Context current with respect to AL Operation (state changes by issueing
+ * commands), alcMakeContextCurrent
is used. The context parameter can be null
+ * or a valid context pointer. The operation will apply to the device that the context
+ * was created for.
+ *
+ * For each OS process (usually this means for each application), only one context can
+ * be current at any given time. All AL commands apply to the current context.
+ * Commands that affect objects shared among contexts (e.g. buffers) have side effects
+ * on other contexts.
+ *
+ * @param context address of context to make current
+ * @return true if successfull, false if not
+ */
+ public static int alcMakeContextCurrent(ALCcontext context) {
+ return nalcMakeContextCurrent(getContext(context));
+ }
+ native static int nalcMakeContextCurrent(long context);
+
+ /**
+ * The current context is the only context accessible to state changes by AL commands
+ * (aside from state changes affecting shared objects). However, multiple contexts can
+ * be processed at the same time. To indicate that a context should be processed (i.e.
+ * that internal execution state like offset increments are supposed to be performed),
+ * the application has to use alcProcessContext
.
+ *
+ * Repeated calls to alcProcessContext
are legal, and do not affect a context that is
+ * already marked as processing. The default state of a context created by
+ * alcCreateContext is that it is not marked as processing.
+ */
+ public static void alcProcessContext(ALCcontext context) {
+ nalcProcessContext(getContext(context));
+ }
+ native static void nalcProcessContext(long context);
+
+ /**
+ * The application can query for, and obtain an handle to, the current context for the
+ * application. If there is no current context, null
is returned.
+ *
+ * @return Current ALCcontext
+ */
+ public static ALCcontext alcGetCurrentContext() {
+ ALCcontext context = null;
+ long context_address = nalcGetCurrentContext();
+ if(context_address != 0) {
+ synchronized (ALC10.contexts) {
+ context = (ALCcontext) ALC10.contexts.get(new Long(context_address));
+ }
+ }
+ return context;
+ }
+ native static long nalcGetCurrentContext();
+
+ /**
+ * The application can query for, and obtain an handle to, the device of a given context.
+ *
+ * @param context address of context to get device for
+ */
+ public static ALCdevice alcGetContextsDevice(ALCcontext context) {
+ ALCdevice device = null;
+ long device_address = nalcGetContextsDevice(getContext(context));
+ if (device_address != 0) {
+ synchronized (ALC10.devices) {
+ device = (ALCdevice) ALC10.devices.get(new Long(device_address));
+ }
+ }
+ return device;
+ }
+ native static long nalcGetContextsDevice(long context);
+
+ /**
+ * The application can suspend any context from processing (including the current
+ * one). To indicate that a context should be suspended from processing (i.e. that
+ * internal execution state like offset increments is not supposed to be changed), the
+ * application has to use alcSuspendContext
.
+ *
+ * Repeated calls to alcSuspendContext
are legal, and do not affect a context that is
+ * already marked as suspended. The default state of a context created by
+ * alcCreateContext
is that it is marked as suspended.
+ *
+ * @param context address of context to suspend
+ */
+ public static void alcSuspendContext(ALCcontext context) {
+ nalcSuspendContext(getContext(context));
+ }
+ native static void nalcSuspendContext(long context);
+
+ /**
+ * The correct way to destroy a context is to first release it using alcMakeCurrent
and
+ * null
. Applications should not attempt to destroy a current context.
+ *
+ * @param context address of context to Destroy
+ */
+ public static void alcDestroyContext(ALCcontext context) {
+ synchronized(ALC10.contexts) {
+ ALCdevice device = alcGetContextsDevice(context);
+ nalcDestroyContext(getContext(context));
+ device.removeContext(context);
+ context.setInvalid();
+ }
+ }
+ native static void nalcDestroyContext(long context);
+
+ /**
+ * ALC uses the same conventions and mechanisms as AL for error handling. In
+ * particular, ALC does not use conventions derived from X11 (GLX) or Windows
+ * (WGL). The alcGetError
function can be used to query ALC errors.
+ *
+ * Error conditions are specific to the device.
+ *
+ * ALC_NO_ERROR - The device handle or specifier does name an accessible driver/server.
+ * ALC_INVALID_DEVICE
- The Context argument does not name a valid context.
+ * ALC_INVALID_CONTEXT
- The Context argument does not name a valid context.
+ * ALC_INVALID_ENUM
- A token used is not valid, or not applicable.
+ * ALC_INVALID_VALUE
- An value (e.g. attribute) is not valid, or not applicable.
+ *
+ * @return Errorcode from ALC statemachine
+ */
+ public static int alcGetError(ALCdevice device) {
+ return nalcGetError(getDevice(device));
+ }
+ native static int nalcGetError(long device);
+
+ /**
+ * Verify that a given extension is available for the current context and the device it
+ * is associated with.
+ * A null
name argument returns ALC_FALSE
, as do invalid and unsupported string
+ * tokens.
+ *
+ * @param extName name of extension to find
+ * @return true if extension is available, false if not
+ */
+ public static boolean alcIsExtensionPresent(ALCdevice device, String extName) {
+ boolean result = nalcIsExtensionPresent(getDevice(device), extName);
+ Util.checkALCError(device);
+ return result;
+ }
+ native static boolean nalcIsExtensionPresent(long device, String extName);
+
+ /**
+ * Enumeration/token values are device independend, but tokens defined for
+ * extensions might not be present for a given device. But only the tokens defined
+ * by the AL core are guaranteed. Availability of extension tokens dependends on the ALC extension.
+ *
+ * Specifying a null
name parameter will cause an ALC_INVALID_VALUE
error.
+ *
+ * @param enumName name of enum to find
+ * @return value of enumeration
+ */
+ public static int alcGetEnumValue(ALCdevice device, String enumName) {
+ int result = nalcGetEnumValue(getDevice(device), enumName);
+ Util.checkALCError(device);
+ return result;
+ }
+ native static int nalcGetEnumValue(long device, String enumName);
+
+ static long getDevice(ALCdevice device) {
+ if(device != null) {
+ Util.checkALCValidDevice(device);
+ return device.device;
+ }
+ return 0L;
+ }
+
+ static long getContext(ALCcontext context) {
+ if(context != null) {
+ Util.checkALCValidContext(context);
+ return context.context;
+ }
+ return 0L;
+ }
+
+}
diff --git a/src/java/org/lwjgl/openal/ALC11.java b/src/java/org/lwjgl/openal/ALC11.java
new file mode 100644
index 0000000..9b0bf09
--- /dev/null
+++ b/src/java/org/lwjgl/openal/ALC11.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2002-2008 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.openal;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+
+
+/**
+ *
+ * The ALC11 class implements features in OpenAL 1.1, specifically
+ * ALC methods and properties.
+ *
+ *
+ * @author Brian Matzon
+ * @see ALC10
+ * @version $Revision: 2286 $
+ * $Id: ALC.java 2286 2006-03-23 19:32:21 +0000 (to, 23 mar 2006) matzon $
+ */
+public final class ALC11 {
+
+ public static final int ALC_DEFAULT_ALL_DEVICES_SPECIFIER = 0x1012;
+ public static final int ALC_ALL_DEVICES_SPECIFIER = 0x1013;
+
+ public static final int ALC_CAPTURE_DEVICE_SPECIFIER = 0x310;
+ public static final int ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER = 0x311;
+ public static final int ALC_CAPTURE_SAMPLES = 0x312;
+
+ /**
+ * The alcCaptureOpenDevice function allows the application to connect to a capture
+ * device. To obtain a list of all available capture devices, use getCaptureDevices a list of all
+ * capture devices will be returned. Retrieving ALC_CAPTURE_DEVICE_SPECIFIER with a valid capture device specified will result
+ * in the name of that device being returned as a single string.
+ *
+ * If the function returns null, then no sound driver/device has been found, or the
+ * requested format could not be fulfilled.
+ * The "deviceName" argument is a string that requests a certain device or
+ * device configuration. If null is specified, the implementation will provide an
+ * implementation specific default. The "frequency" and "format" arguments specify the format that
+ * audio data will be presented to the application, and match the values that can be passed to
+ * alBufferData. The implementation is expected to convert and resample to this format on
+ * behalf of the application. The "buffersize" argument specifies the number of sample frames
+ * to buffer in the AL, for example, requesting a format of AL_FORMAT_STEREO16 and
+ * a buffer size of 1024 would require the AL to store up to 1024 * 4 bytes of audio data.
+ * Note that the implementation may use a larger buffer than requested if it needs to, but the
+ * implementation will set up a buffer of at least the requested size.
+ * Specifying a compressed or extension-supplied format may result in failure, even if the
+ * extension is supplied for rendering.
+ *
+ * LWJGL SPECIFIC: the actual created device is managed internally in lwjgl
+ *
+ * @param devicename Name of device to open for capture
+ * @param frequency Frequency of samples to capture
+ * @param format Format of samples to capture
+ * @param buffersize Size of buffer to capture to
+ * @return ALCdevice if it was possible to open a device
+ */
+ public static ALCdevice alcCaptureOpenDevice(String devicename, int frequency, int format, int buffersize) {
+ long device_address = nalcCaptureOpenDevice(devicename, frequency, format, buffersize);
+ if(device_address != 0) {
+ ALCdevice device = new ALCdevice(device_address);
+ synchronized (ALC10.devices) {
+ ALC10.devices.put(new Long(device_address), device);
+ }
+ return device;
+ }
+ return null;
+ }
+ static native long nalcCaptureOpenDevice( String devicename, int frequency, int format, int buffersize);
+
+ /**
+ * The alcCaptureCloseDevice function allows the application to disconnect from a capture
+ * device.
+ *
+ * The return code will be true or false, indicating success or failure. If
+ * the device is null or invalid, an ALC_INVALID_DEVICE error will be generated.
+ * Once closed, a capture device is invalid.
+ * @return true if device was successfully closed
+ */
+ public static boolean alcCaptureCloseDevice(ALCdevice device) {
+ boolean result = nalcCaptureCloseDevice(ALC10.getDevice(device));
+ synchronized (ALC10.devices) {
+ device.setInvalid();
+ ALC10.devices.remove(new Long(device.device));
+ }
+ return result;
+ }
+ static native boolean nalcCaptureCloseDevice(long device);
+
+ /**
+ * Once a capture device has been opened via alcCaptureOpenDevice, it is made to start
+ * recording audio via the alcCaptureStart entry point:
+ *
+ * Once started, the device will record audio to an internal ring buffer, the size of which was
+ * specified when opening the device.
+ * The application may query the capture device to discover how much data is currently
+ * available via the alcGetInteger with the ALC_CAPTURE_SAMPLES token. This will
+ * report the number of sample frames currently available.
+ */
+ public static void alcCaptureStart(ALCdevice device) {
+ nalcCaptureStart(ALC10.getDevice(device));
+ }
+ static native void nalcCaptureStart(long device);
+
+ /**
+ * If the application doesn't need to capture more audio for an amount of time, they can halt
+ * the device without closing it via the alcCaptureStop entry point.
+ * The implementation is encouraged to optimize for this case. The amount of audio
+ * samples available after restarting a stopped capture device is reset to zero. The
+ * application does not need to stop the capture device to read from it.
+ */
+ public static void alcCaptureStop(ALCdevice device) {
+ nalcCaptureStop(ALC10.getDevice(device));
+ }
+ static native void nalcCaptureStop(long device);
+
+ /**
+ * When the application feels there are enough samples available to process, it can obtain
+ * them from the AL via the alcCaptureSamples entry point.
+ *
+ * The "buffer" argument specifies an application-allocated buffer that can contain at least
+ * "samples" sample frames. The implementation may defer conversion and resampling until
+ * this point. Requesting more sample frames than are currently available is an error.
+ *
+ * @param buffer Buffer to store samples in
+ * @param samples Number of samples to request
+ */
+ public static void alcCaptureSamples(ALCdevice device, ByteBuffer buffer, int samples ) {
+ nalcCaptureSamples(ALC10.getDevice(device), buffer, buffer.position(), samples);
+ }
+ static native void nalcCaptureSamples(long device, ByteBuffer buffer, int position, int samples );
+
+ static native void initNativeStubs() throws LWJGLException;
+
+ /**
+ * Initializes ALC11, including any extensions
+ * @return true if initialization was successfull
+ */
+ static boolean initialize() {
+ try {
+ IntBuffer ib = BufferUtils.createIntBuffer(2);
+ ALC10.alcGetInteger(AL.getDevice(), ALC10.ALC_MAJOR_VERSION, ib);
+ ib.position(1);
+ ALC10.alcGetInteger(AL.getDevice(), ALC10.ALC_MINOR_VERSION, ib);
+
+ int major = ib.get(0);
+ int minor = ib.get(1);
+
+ // checking for version 1.x+
+ if(major >= 1) {
+
+ // checking for version 1.1+
+ if(major > 1 || minor >= 1) {
+ ALC11.initNativeStubs();
+ AL11.initNativeStubs();
+ }
+ }
+ } catch (LWJGLException le) {
+ LWJGLUtil.log("failed to initialize ALC11: " + le);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/java/org/lwjgl/openal/ALCcontext.java b/src/java/org/lwjgl/openal/ALCcontext.java
new file mode 100644
index 0000000..b587f8c
--- /dev/null
+++ b/src/java/org/lwjgl/openal/ALCcontext.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2002-2008 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.openal;
+
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+
+/**
+ * The ALCcontext class represents a context opened in OpenAL space.
+ *
+ * All operations of the AL core API affect a current AL context. Within the scope of AL,
+ * the ALC is implied - it is not visible as a handle or function parameter. Only one AL
+ * Context per process can be current at a time. Applications maintaining multiple AL
+ * Contexts, whether threaded or not, have to set the current context accordingly.
+ * Applications can have multiple threads that share one more or contexts. In other words,
+ * AL and ALC are threadsafe.
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: ALCcontext.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public final class ALCcontext {
+
+ /** Address of actual context */
+ final long context;
+
+ /** Whether this context is valid */
+ private boolean valid = false;
+
+ /**
+ * Creates a new instance of ALCcontext
+ *
+ * @param context address of actual context
+ */
+ ALCcontext(long context) {
+ this.context = context;
+ this.valid = true;
+ }
+
+ /*
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object context) {
+ if(context instanceof ALCcontext) {
+ return ((ALCcontext)context).context == this.context;
+ }
+ return super.equals(context);
+ }
+
+ /**
+ * Creates an attribute list in a ByteBuffer
+ * @param contextFrequency Frequency to add
+ * @param contextRefresh Refresh rate to add
+ * @param contextSynchronized Whether to synchronize the context
+ * @return
+ */
+ static IntBuffer createAttributeList(int contextFrequency, int contextRefresh, int contextSynchronized) {
+ IntBuffer attribList = BufferUtils.createIntBuffer(7);
+
+ attribList.put(ALC10.ALC_FREQUENCY);
+ attribList.put(contextFrequency);
+ attribList.put(ALC10.ALC_REFRESH);
+ attribList.put(contextRefresh);
+ attribList.put(ALC10.ALC_SYNC);
+ attribList.put(contextSynchronized);
+ attribList.put(0); //terminating int
+
+ return attribList;
+ }
+
+ /**
+ * Marks this context as invalid
+ *
+ */
+ void setInvalid() {
+ valid = false;
+ }
+
+ /**
+ * @return true if this context is still valid
+ */
+ public boolean isValid() {
+ return valid;
+ }
+}
diff --git a/src/java/org/lwjgl/openal/ALCdevice.java b/src/java/org/lwjgl/openal/ALCdevice.java
new file mode 100644
index 0000000..4a6b535
--- /dev/null
+++ b/src/java/org/lwjgl/openal/ALCdevice.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2002-2008 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.openal;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * The ALCdevice class represents a device opened in OpenAL space.
+ *
+ * ALC introduces the notion of a Device. A Device can be, depending on the
+ * implementation, a hardware device, or a daemon/OS service/actual server. This
+ * mechanism also permits different drivers (and hardware) to coexist within the same
+ * system, as well as allowing several applications to share system resources for audio,
+ * including a single hardware output device. The details are left to the implementation,
+ * which has to map the available backends to unique device specifiers.
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: ALCdevice.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public final class ALCdevice {
+
+ /** Address of actual device */
+ final long device;
+
+ /** Whether this device is valid */
+ private boolean valid = false;
+
+ /** List of contexts belonging to the device */
+ private HashMap contexts = new HashMap();
+
+ /**
+ * Creates a new instance of ALCdevice
+ *
+ * @param device address of actual device
+ */
+ ALCdevice(long device) {
+ this.device = device;
+ this.valid = true;
+ }
+
+ /*
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object device) {
+ if(device instanceof ALCdevice) {
+ return ((ALCdevice)device).device == this.device;
+ }
+ return super.equals(device);
+ }
+
+ /**
+ * Adds a context to the device
+ *
+ * @param context context to add to the list of contexts for this device
+ */
+ void addContext(ALCcontext context) {
+ synchronized (contexts) {
+ contexts.put(new Long(context.context), context);
+ }
+ }
+
+ /**
+ * Remove context associated with device
+ *
+ * @param context Context to disassociate with device
+ */
+ void removeContext(ALCcontext context) {
+ synchronized (contexts) {
+ contexts.remove(new Long(context.context));
+ }
+ }
+
+ /**
+ * Marks this device and all of its contexts invalid
+ */
+ void setInvalid() {
+ valid = false;
+ synchronized (contexts) {
+ for(Iterator i = contexts.values().iterator(); i.hasNext();) {
+ ALCcontext context = (ALCcontext) i.next();
+ context.setInvalid();
+ }
+ }
+ contexts.clear();
+ }
+
+ /**
+ * @return true if this device is still valid
+ */
+ public boolean isValid() {
+ return valid;
+ }
+}
diff --git a/src/java/org/lwjgl/openal/OpenALException.java b/src/java/org/lwjgl/openal/OpenALException.java
new file mode 100644
index 0000000..dcbcf1e
--- /dev/null
+++ b/src/java/org/lwjgl/openal/OpenALException.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002-2008 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.openal;
+
+/**
+ *
+ * Thrown by the debug build library of the LWJGL if any OpenAL operation
+ * causes an error.
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: OpenALException.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class OpenALException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor for OpenALException.
+ */
+ public OpenALException() {
+ super();
+ }
+
+ /**
+ * Constructor that takes an AL error number
+ */
+ public OpenALException(int error_code) {
+ super("OpenAL error: " + AL10.alGetString(error_code) + " (" + error_code + ")");
+ }
+
+ /**
+ * Constructor for OpenALException.
+ * @param message
+ */
+ public OpenALException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor for OpenALException.
+ * @param message
+ * @param cause
+ */
+ public OpenALException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructor for OpenALException.
+ * @param cause
+ */
+ public OpenALException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/java/org/lwjgl/openal/Util.java b/src/java/org/lwjgl/openal/Util.java
new file mode 100644
index 0000000..3d8bf9a
--- /dev/null
+++ b/src/java/org/lwjgl/openal/Util.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2002-2008 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.openal;
+
+
+/**
+ * Simple utility class for checking AL/ALC errors
+ *
+ * @author cix_foo
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ */
+
+public final class Util {
+ /** No c'tor */
+ private Util() {
+ }
+
+ /**
+ * Checks for any ALC errors and throws an unchecked exception on errors
+ * @param device Device for which to check ALC errors
+ */
+ public static void checkALCError(ALCdevice device) {
+ int err = ALC10.alcGetError(device);
+ if (err != ALC10.ALC_NO_ERROR)
+ throw new OpenALException(ALC10.alcGetString(AL.getDevice(), err));
+ }
+
+ /**
+ * Checks for any AL errors and throws an unchecked exception on errors
+ */
+ public static void checkALError() {
+ int err = AL10.alGetError();
+ if (err != AL10.AL_NO_ERROR)
+ throw new OpenALException(err);
+ }
+
+ /**
+ * Checks for a valid device
+ * @param device ALCdevice to check the validity of
+ */
+ public static void checkALCValidDevice(ALCdevice device) {
+ if(!device.isValid()) {
+ throw new OpenALException("Invalid device: " + device);
+ }
+ }
+
+ /**
+ * Checks for a valid context
+ * @param context ALCcontext to check the validity of
+ */
+ public static void checkALCValidContext(ALCcontext context) {
+ if(!context.isValid()) {
+ throw new OpenALException("Invalid context: " + context);
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/APIUtils.java b/src/java/org/lwjgl/opengl/APIUtils.java
new file mode 100644
index 0000000..730b801
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/APIUtils.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.BufferUtils;
+
+import java.nio.*;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+
+/** @author spasi */
+final class APIUtils {
+
+ private static final int INITIAL_BUFFER_SIZE = 256;
+ private static final int INITIAL_LENGTHS_SIZE = 4;
+
+ private static final int BUFFERS_SIZE = 32;
+
+ private static final ThreadLocal arrayTL = new ThreadLocal() {
+ protected Object initialValue() { return new char[INITIAL_BUFFER_SIZE]; }
+ };
+
+ private static final ThreadLocal bufferTL = new ThreadLocal() {
+ protected Object initialValue() { return BufferUtils.createByteBuffer(INITIAL_BUFFER_SIZE); }
+ };
+
+ private static final ThreadLocal lengthsTL = new ThreadLocal() {
+ protected Object initialValue() { return BufferUtils.createIntBuffer(INITIAL_LENGTHS_SIZE); }
+ };
+
+ private static final ThreadLocal infiniteSeqTL = new ThreadLocal() {
+ protected Object initialValue() { return new InfiniteCharSequence(); }
+ };
+
+ private static final ThreadLocal buffersTL = new ThreadLocal() {
+ protected Object initialValue() { return new Buffers(); }
+ };
+
+ private static CharsetEncoder encoder = Charset.forName("US-ASCII").newEncoder();
+
+ private APIUtils() {
+ }
+
+ private static char[] getArray(final int size) {
+ char[] array = (char[])arrayTL.get();
+
+ if ( array.length < size ) {
+ int sizeNew = array.length << 1;
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ array = new char[size];
+ arrayTL.set(array);
+ }
+
+ return array;
+ }
+
+ static ByteBuffer getBufferByte(final int size) {
+ ByteBuffer buffer = (ByteBuffer)bufferTL.get();
+
+ if ( buffer.capacity() < size ) {
+ int sizeNew = buffer.capacity() << 1;
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ buffer = BufferUtils.createByteBuffer(size);
+ bufferTL.set(buffer);
+ } else
+ buffer.clear();
+
+ return buffer;
+ }
+
+ private static ByteBuffer getBufferByteOffset(final int size) {
+ ByteBuffer buffer = (ByteBuffer)bufferTL.get();
+
+ if ( buffer.capacity() < size ) {
+ int sizeNew = buffer.capacity() << 1;
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ final ByteBuffer bufferNew = BufferUtils.createByteBuffer(size);
+ bufferNew.put(buffer);
+ bufferTL.set(buffer = bufferNew);
+ } else {
+ buffer.position(buffer.limit());
+ buffer.limit(buffer.capacity());
+ }
+
+ return buffer;
+ }
+
+ static ShortBuffer getBufferShort() { return ((Buffers)buffersTL.get()).shorts; }
+
+ static IntBuffer getBufferInt() { return ((Buffers)buffersTL.get()).ints; }
+
+ static LongBuffer getBufferLong() { return ((Buffers)buffersTL.get()).longs; }
+
+ static FloatBuffer getBufferFloat() { return ((Buffers)buffersTL.get()).floats; }
+
+ static DoubleBuffer getBufferDouble() { return ((Buffers)buffersTL.get()).doubles; }
+
+ static IntBuffer getLengths() {
+ return getLengths(1);
+ }
+
+ static IntBuffer getLengths(final int size) {
+ IntBuffer lengths = (IntBuffer)lengthsTL.get();
+
+ if ( lengths.capacity() < size ) {
+ int sizeNew = lengths.capacity();
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ lengths = BufferUtils.createIntBuffer(size);
+ lengthsTL.set(lengths);
+ } else
+ lengths.clear();
+
+ return lengths;
+ }
+
+ private static InfiniteCharSequence getInfiniteSeq() {
+ return (InfiniteCharSequence)infiniteSeqTL.get();
+ }
+
+ private static void encode(final ByteBuffer buffer, final CharSequence string) {
+ final InfiniteCharSequence infiniteSeq = getInfiniteSeq();
+ infiniteSeq.setString(string);
+ encoder.encode(infiniteSeq.buffer, buffer, true);
+ }
+
+ /**
+ * Reads a byte string from the specified buffer.
+ *
+ * @param buffer
+ *
+ * @return the buffer as a String.
+ */
+ static String getString(final ByteBuffer buffer) {
+ final int length = buffer.remaining();
+ final char[] charArray = getArray(length);
+
+ for ( int i = buffer.position(); i < buffer.limit(); i++ )
+ charArray[i - buffer.position()] = (char)buffer.get(i);
+
+ return new String(charArray, 0, length);
+ }
+
+ /**
+ * Returns a buffer containing the specified string as bytes.
+ *
+ * @param string
+ *
+ * @return the String as a ByteBuffer
+ */
+ static ByteBuffer getBuffer(final CharSequence string) {
+ final ByteBuffer buffer = getBufferByte(string.length());
+
+ encode(buffer, string);
+
+ buffer.flip();
+ return buffer;
+ }
+
+ /**
+ * Returns a buffer containing the specified string as bytes, starting at the specified offset.
+ *
+ * @param string
+ *
+ * @return the String as a ByteBuffer
+ */
+ static ByteBuffer getBuffer(final CharSequence string, final int offset) {
+ final ByteBuffer buffer = getBufferByteOffset(offset + string.length());
+
+ encode(buffer, string);
+
+ buffer.flip();
+ return buffer;
+ }
+
+ /**
+ * Returns a buffer containing the specified string as bytes, including null-termination.
+ *
+ * @param string
+ *
+ * @return the String as a ByteBuffer
+ */
+ static ByteBuffer getBufferNT(final CharSequence string) {
+ final ByteBuffer buffer = getBufferByte(string.length() + 1);
+
+ encode(buffer, string);
+
+ buffer.put((byte)0);
+ buffer.flip();
+ return buffer;
+ }
+
+ static int getTotalLength(final CharSequence[] strings) {
+ int length = 0;
+ for ( int i = 0; i < strings.length; i++ )
+ length += strings[i].length();
+
+ return length;
+ }
+
+ /**
+ * Returns a buffer containing the specified strings as bytes.
+ *
+ * @param strings
+ *
+ * @return the Strings as a ByteBuffer
+ */
+ static ByteBuffer getBuffer(final CharSequence[] strings) {
+ final ByteBuffer buffer = getBufferByte(getTotalLength(strings));
+
+ final InfiniteCharSequence infiniteSeq = getInfiniteSeq();
+ for ( int i = 0; i < strings.length; i++ ) {
+ infiniteSeq.setString(strings[i]);
+ encoder.encode(infiniteSeq.buffer, buffer, true);
+ }
+ infiniteSeq.clear();
+
+ buffer.flip();
+ return buffer;
+ }
+
+ /**
+ * Returns a buffer containing the specified strings as bytes, including null-termination.
+ *
+ * @param strings
+ *
+ * @return the Strings as a ByteBuffer
+ */
+ static ByteBuffer getBufferNT(final CharSequence[] strings) {
+ final ByteBuffer buffer = getBufferByte(getTotalLength(strings) + strings.length);
+
+ final InfiniteCharSequence infiniteSeq = getInfiniteSeq();
+ for ( int i = 0; i < strings.length; i++ ) {
+ infiniteSeq.setString(strings[i]);
+ encoder.encode(infiniteSeq.buffer, buffer, true);
+ buffer.put((byte)0);
+ }
+ infiniteSeq.clear();
+
+ buffer.flip();
+ return buffer;
+ }
+
+ /**
+ * Returns a buffer containing the lengths of the specified strings.
+ *
+ * @param strings
+ *
+ * @return the String lengths in an IntBuffer
+ */
+ static IntBuffer getLengths(final CharSequence[] strings) {
+ IntBuffer buffer = getLengths(strings.length);
+
+ for ( int i = 0; i < strings.length; i++ )
+ buffer.put(strings[i].length());
+
+ buffer.flip();
+ return buffer;
+ }
+
+ /**
+ * A mutable CharSequence with very large initial length. We can wrap this in a re-usable CharBuffer for decoding.
+ * We cannot subclass CharBuffer because of {@link CharBuffer#toString(int,int)}.
+ */
+ private static class InfiniteCharSequence implements CharSequence {
+
+ final CharBuffer buffer;
+
+ CharSequence string;
+
+ InfiniteCharSequence() {
+ buffer = CharBuffer.wrap(this);
+ }
+
+ void setString(final CharSequence string) {
+ this.string = string;
+ this.buffer.position(0);
+ this.buffer.limit(string.length());
+ }
+
+ void clear() {
+ this.string = null;
+ }
+
+ public int length() {
+ return Integer.MAX_VALUE;
+ }
+
+ public char charAt(final int index) {
+ return string.charAt(index);
+ }
+
+ public CharSequence subSequence(final int start, final int end) {
+ return string.subSequence(start, end);
+ }
+ }
+
+ private static class Buffers {
+
+ final ShortBuffer shorts;
+ final IntBuffer ints;
+ final LongBuffer longs;
+
+ final FloatBuffer floats;
+ final DoubleBuffer doubles;
+
+ Buffers() {
+ shorts = BufferUtils.createShortBuffer(BUFFERS_SIZE);
+ ints = BufferUtils.createIntBuffer(BUFFERS_SIZE);
+ longs = BufferUtils.createLongBuffer(BUFFERS_SIZE);
+
+ floats = BufferUtils.createFloatBuffer(BUFFERS_SIZE);
+ doubles = BufferUtils.createDoubleBuffer(BUFFERS_SIZE);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java b/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java
new file mode 100644
index 0000000..b51b811
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2002-2008 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.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Canvas;
+
+import org.lwjgl.LWJGLException;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3002 $
+ * $Id: AWTCanvasImplementation.java 3002 2008-04-10 20:25:54Z elias_naur $
+ */
+interface AWTCanvasImplementation {
+ /**
+ * Return an opaque handle to the canvas peer information required to create a context from it.
+ */
+ PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) 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.
+ */
+ 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
new file mode 100644
index 0000000..2121247
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/AWTGLCanvas.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+
+import java.awt.*;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+
+/**
+ *
+ * An AWT rendering context.
+ *
+ *
+ * @author $Author: spasi $
+ * $Id: AWTGLCanvas.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision: 3116 $
+ */
+public class AWTGLCanvas extends Canvas implements Drawable, ComponentListener, HierarchyListener {
+
+ private static final long serialVersionUID = 1L;
+
+ private final static AWTCanvasImplementation implementation;
+ private boolean update_context;
+ private Object SYNC_LOCK = new Object();
+
+ /** The requested pixel format */
+ private final PixelFormat pixel_format;
+
+ /** The drawable to share context with */
+ private final Drawable drawable;
+
+ /** The ContextAttribs to use when creating the context */
+ private final ContextAttribs attribs;
+
+ /** Context handle */
+ private PeerInfo peer_info;
+ private Context context;
+
+ /**
+ * re-entry counter for support for re-entrant
+ * redrawing in paint(). It happens when using dialog boxes.
+ */
+ private int reentry_count;
+
+ /** Tracks whether initGL() needs to be called */
+ private boolean first_run;
+
+ static {
+ Sys.initialize();
+ implementation = createImplementation();
+ }
+
+ static AWTCanvasImplementation createImplementation() {
+ switch ( LWJGLUtil.getPlatform() ) {
+ case LWJGLUtil.PLATFORM_LINUX:
+ return new LinuxCanvasImplementation();
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ return new WindowsCanvasImplementation();
+ case LWJGLUtil.PLATFORM_MACOSX:
+ return new MacOSXCanvasImplementation();
+ default:
+ throw new IllegalStateException("Unsupported platform");
+ }
+ }
+
+ private void setUpdate() {
+ synchronized ( SYNC_LOCK ) {
+ update_context = true;
+ }
+ }
+
+ /** This method should only be called internally. */
+ public Context getContext() {
+ return context;
+ }
+
+ /** Constructor using the default PixelFormat. */
+ public AWTGLCanvas() throws LWJGLException {
+ this(new PixelFormat());
+ }
+
+ /**
+ * Create an AWTGLCanvas with the requested PixelFormat on the default GraphicsDevice.
+ *
+ * @param pixel_format The desired pixel format. May not be null
+ */
+ 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 device the device to create the canvas on.
+ * @param pixel_format The desired pixel format. May not be null
+ */
+ 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 pixel_format The desired pixel format. May not be null
+ * @param drawable The Drawable to share context with
+ */
+ public AWTGLCanvas(GraphicsDevice device, PixelFormat pixel_format, Drawable drawable) throws LWJGLException {
+ this(device, pixel_format, drawable, null);
+ }
+
+ /**
+ * Create an AWTGLCanvas with the requested PixelFormat on the specified GraphicsDevice.
+ *
+ * @param device the device to create the canvas on.
+ * @param pixel_format The desired pixel format. May not be null
+ * @param drawable The Drawable to share context with
+ * @param attribs The ContextAttribs to use when creating the context. (optional, may be null)
+ */
+ public AWTGLCanvas(GraphicsDevice device, PixelFormat pixel_format, Drawable drawable, ContextAttribs attribs) throws LWJGLException {
+ super(implementation.findConfiguration(device, pixel_format));
+ if ( pixel_format == null )
+ throw new NullPointerException("Pixel format must be non-null");
+ addHierarchyListener(this);
+ addComponentListener(this);
+ this.drawable = drawable;
+ this.pixel_format = pixel_format;
+ this.attribs = attribs;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.Canvas#addNotify()
+ */
+ public void addNotify() {
+ super.addNotify();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.Component#removeNotify()
+ */
+ public void removeNotify() {
+ synchronized ( SYNC_LOCK ) {
+ destroyContext();
+ super.removeNotify();
+ }
+ }
+
+ /** Set swap interval. */
+ public void setSwapInterval(int swap_interval) {
+ synchronized ( SYNC_LOCK ) {
+ if ( context == null )
+ throw new IllegalStateException("Canvas not yet displayable");
+ Context.setSwapInterval(swap_interval);
+ }
+ }
+
+ /** Enable vsync */
+ public void setVSyncEnabled(boolean enabled) {
+ setSwapInterval(enabled ? 1 : 0);
+ }
+
+ /** Swap the canvas' buffer */
+ public void swapBuffers() throws LWJGLException {
+ synchronized ( SYNC_LOCK ) {
+ if ( context == null )
+ throw new IllegalStateException("Canvas not yet displayable");
+ Context.swapBuffers();
+ }
+ }
+
+ public void releaseContext() throws LWJGLException {
+ synchronized ( SYNC_LOCK ) {
+ 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 paintGL()).
+ */
+ public void makeCurrent() throws LWJGLException {
+ synchronized ( SYNC_LOCK ) {
+ if ( context == null )
+ throw new IllegalStateException("Canvas not yet displayable");
+ context.makeCurrent();
+ }
+ }
+
+ /** Destroy the OpenGL context. This happens when the component becomes undisplayable */
+ private void destroyContext() {
+ synchronized ( SYNC_LOCK ) {
+ try {
+ if ( context != null ) {
+ context.forceDestroy();
+ context = null;
+ reentry_count = 0;
+ peer_info.destroy();
+ peer_info = null;
+ }
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Override this to do initialising of the context.
+ * It will be called once from paint(), immediately after
+ * the context is created and made current.
+ */
+ protected void initGL() {
+ }
+
+ /** Override this to do painting */
+ protected void paintGL() {
+ }
+
+ /**
+ * The default paint() operation makes the context current and calls paintGL() which should
+ * be overridden to do GL operations.
+ */
+ public final void paint(Graphics g) {
+ LWJGLException exception = null;
+ synchronized ( SYNC_LOCK ) {
+ if ( !isDisplayable() )
+ return;
+ try {
+ if ( peer_info == null ) {
+ this.peer_info = implementation.createPeerInfo(this, pixel_format);
+ }
+ peer_info.lockAndGetHandle();
+ try {
+ if ( context == null ) {
+ this.context = new Context(peer_info, attribs, drawable != null ? drawable.getContext() : null);
+ first_run = true;
+ }
+
+ if ( reentry_count == 0 )
+ context.makeCurrent();
+ reentry_count++;
+ try {
+ if ( update_context ) {
+ context.update();
+ update_context = false;
+ }
+ if ( first_run ) {
+ first_run = false;
+ initGL();
+ }
+ paintGL();
+ } finally {
+ reentry_count--;
+ if ( reentry_count == 0 )
+ Context.releaseCurrentContext();
+ }
+ } finally {
+ peer_info.unlock();
+ }
+ } catch (LWJGLException e) {
+ exception = e;
+ }
+ }
+ if ( exception != null )
+ exceptionOccurred(exception);
+ }
+
+ /**
+ * This method will be called if an unhandled LWJGLException occurs in paint().
+ * Override this method to be notified of this.
+ *
+ * @param exception The exception that occurred.
+ */
+ protected void exceptionOccurred(LWJGLException exception) {
+ LWJGLUtil.log("Unhandled exception occurred, skipping paint(): " + exception);
+ }
+
+ /** override update to avoid clearing */
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+ public void componentShown(ComponentEvent e) {
+ }
+
+ public void componentHidden(ComponentEvent e) {
+ }
+
+ public void componentResized(ComponentEvent e) {
+ setUpdate();
+ }
+
+ public void componentMoved(ComponentEvent e) {
+ setUpdate();
+ }
+
+ public void setLocation(int x, int y) {
+ super.setLocation(x, y);
+ setUpdate();
+ }
+
+ public void setLocation(Point p) {
+ super.setLocation(p);
+ setUpdate();
+ }
+
+ public void setSize(Dimension d) {
+ super.setSize(d);
+ setUpdate();
+ }
+
+ public void setSize(int width, int height) {
+ super.setSize(width, height);
+ setUpdate();
+ }
+
+ public void setBounds(int x, int y, int width, int height) {
+ super.setBounds(x, y, width, height);
+ setUpdate();
+ }
+
+ public void hierarchyChanged(HierarchyEvent e) {
+ setUpdate();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/AWTSurfaceLock.java b/src/java/org/lwjgl/opengl/AWTSurfaceLock.java
new file mode 100644
index 0000000..64f02c6
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/AWTSurfaceLock.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2002-2008 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.awt.Canvas;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: AWTSurfaceLock.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class AWTSurfaceLock {
+
+ private final static int WAIT_DELAY_MILLIS = 100;
+
+ private final ByteBuffer lock_buffer;
+
+ private boolean firstLockSucceeded = false;
+
+ AWTSurfaceLock() {
+ lock_buffer = createHandle();
+ }
+
+ private static native ByteBuffer createHandle();
+
+ public ByteBuffer lockAndGetHandle(Canvas component) throws LWJGLException {
+ while (!privilegedLockAndInitHandle(component)) {
+ LWJGLUtil.log("Could not get drawing surface info, retrying...");
+ try {
+ Thread.sleep(WAIT_DELAY_MILLIS);
+ } catch (InterruptedException e) {
+ LWJGLUtil.log("Interrupted while retrying: " + e);
+ }
+ }
+
+ return lock_buffer;
+ }
+
+ private boolean privilegedLockAndInitHandle(final Canvas component) throws LWJGLException {
+ // Workaround for Sun JDK bug 4796548 which still exists in java for OS X
+ // We need to elevate privileges because of an AWT bug. Please see
+ // http://192.18.37.44/forums/index.php?topic=10572 for a discussion.
+ // It is only needed on first call, so we avoid it on all subsequent calls
+ // due to performance.
+ if (firstLockSucceeded)
+ return lockAndInitHandle(lock_buffer, component);
+ else
+ try {
+ final Object result = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+
+ public Object run() throws LWJGLException {
+ return Boolean.valueOf(lockAndInitHandle(lock_buffer, component));
+ }
+ });
+ firstLockSucceeded = ((Boolean) result).booleanValue();
+ return firstLockSucceeded;
+ } catch (PrivilegedActionException e) {
+ throw (LWJGLException) e.getException();
+ }
+ }
+
+ private static native boolean lockAndInitHandle(ByteBuffer lock_buffer, Canvas component) throws LWJGLException;
+
+ 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/AWTUtil.java b/src/java/org/lwjgl/opengl/AWTUtil.java
new file mode 100644
index 0000000..1185523
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/AWTUtil.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * @author elias_naur
+ */
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.IllegalComponentStateException;
+import java.awt.MouseInfo;
+import java.awt.Point;
+import java.awt.PointerInfo;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.nio.IntBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+
+final class AWTUtil {
+ public static boolean hasWheel() {
+ return true;
+ }
+
+ public static int getButtonCount() {
+ return MouseEventQueue.NUM_BUTTONS;
+ }
+
+ public static int getNativeCursorCapabilities() {
+ if (LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_MACOSX || LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 4)) {
+ int cursor_colors = Toolkit.getDefaultToolkit().getMaximumCursorColors();
+ boolean supported = cursor_colors >= Short.MAX_VALUE && getMaxCursorSize() > 0;
+ int caps = supported ? org.lwjgl.input.Cursor.CURSOR_8_BIT_ALPHA | org.lwjgl.input.Cursor.CURSOR_ONE_BIT_TRANSPARENCY: 0 | org.lwjgl.input.Cursor.CURSOR_ANIMATION;
+ return caps;
+ } else {
+ /* Return no capability in Mac OS X 10.3 and earlier , as there are two unsolved bugs (both reported to apple along with
+ minimal test case):
+ 1. When a custom cursor (or some standard) java.awt.Cursor is assigned to a
+ Componennt, it is reset to the default pointer cursor when the window is de-
+ activated and the re-activated. The Cursor can not be reset to the custom cursor,
+ with another setCursor.
+ 2. When the cursor is moving in the top pixel row (y = 0 in AWT coordinates) in fullscreen
+ mode, no mouse moved events are reported, even though mouse pressed/released and dragged
+ events are reported
+ */
+ return 0;
+ }
+ }
+
+ public static Robot createRobot(final Component component) {
+ try {
+ Robot robot = (Robot)AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return new Robot(component.getGraphicsConfiguration().getDevice());
+ }
+ });
+ return robot;
+ } catch (PrivilegedActionException e) {
+ LWJGLUtil.log("Got exception while creating robot: " + e.getCause());
+ return null;
+ }
+ }
+
+ private static int transformY(Component component, int y) {
+ return component.getHeight() - 1 - y;
+ }
+
+ /**
+ * Use reflection to access the JDK 1.5 pointer location, if possible and
+ * only if the given component is on the same screen as the cursor. Return
+ * null otherwise.
+ */
+ private static Point getPointerLocation(final Component component) {
+ try {
+ final GraphicsConfiguration config = component.getGraphicsConfiguration();
+ if (config != null) {
+ PointerInfo pointer_info = (PointerInfo)AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return MouseInfo.getPointerInfo();
+ }
+ });
+ GraphicsDevice device = pointer_info.getDevice();
+ if (device == config.getDevice()) {
+ return pointer_info.getLocation();
+ }
+ return null;
+ }
+ } catch (PrivilegedActionException e) {
+ LWJGLUtil.log("Failed to query pointer location: " + e.getCause());
+ }
+ return null;
+ }
+
+ /**
+ * Use the 1.5 API to get the cursor position relative to the component. Return null
+ * if it fails (JDK <= 1.4).
+ */
+ public static Point getCursorPosition(Component component) {
+ try {
+ Point pointer_location = getPointerLocation(component);
+ if (pointer_location != null) {
+ Point location = component.getLocationOnScreen();
+ pointer_location.translate(-location.x, -location.y);
+ pointer_location.move(pointer_location.x, transformY(component, pointer_location.y));
+ return pointer_location;
+ }
+ } catch (IllegalComponentStateException e) {
+ LWJGLUtil.log("Failed to set cursor position: " + e);
+ } catch (NoClassDefFoundError e) { // Not JDK 1.5
+ LWJGLUtil.log("Failed to query cursor position: " + e);
+ }
+ return null;
+ }
+
+ public static void setCursorPosition(Component component, Robot robot, int x, int y) {
+ if (robot != null) {
+ try {
+ Point location = component.getLocationOnScreen();
+ int transformed_x = location.x + x;
+ int transformed_y = location.y + transformY(component, y);
+ robot.mouseMove(transformed_x, transformed_y);
+ } catch (IllegalComponentStateException e) {
+ LWJGLUtil.log("Failed to set cursor position: " + e);
+ }
+ }
+ }
+
+ public static int getMinCursorSize() {
+ Dimension min_size = Toolkit.getDefaultToolkit().getBestCursorSize(0, 0);
+ return Math.max(min_size.width, min_size.height);
+ }
+
+ public static int getMaxCursorSize() {
+ Dimension max_size = Toolkit.getDefaultToolkit().getBestCursorSize(10000, 10000);
+ return Math.min(max_size.width, max_size.height);
+ }
+
+ /** Native cursor handles */
+ public static Cursor createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
+ BufferedImage cursor_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ int[] pixels = new int[images.remaining()];
+ int old_position = images.position();
+ images.get(pixels);
+ images.position(old_position);
+ cursor_image.setRGB(0, 0, width, height, pixels, 0, width);
+ return Toolkit.getDefaultToolkit().createCustomCursor(cursor_image, new Point(xHotspot, yHotspot), "LWJGL Custom cursor");
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/BaseReferences.java b/src/java/org/lwjgl/opengl/BaseReferences.java
new file mode 100644
index 0000000..343b2c9
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/BaseReferences.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2002-2008 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.Buffer;
+import java.nio.IntBuffer;
+import java.util.Arrays;
+
+class BaseReferences {
+
+ int elementArrayBuffer;
+ int arrayBuffer;
+ Buffer[] glVertexAttribPointer_buffer;
+ Buffer[] glTexCoordPointer_buffer;
+ int glClientActiveTexture;
+
+ int pixelPackBuffer;
+ int pixelUnpackBuffer;
+
+ int indirectBuffer;
+
+ BaseReferences(ContextCapabilities caps) {
+ IntBuffer temp = caps.scratch_int_buffer;
+
+ int max_vertex_attribs;
+ if (caps.OpenGL20 || caps.GL_ARB_vertex_shader) {
+ GL11.glGetInteger(ARBVertexShader.GL_MAX_VERTEX_ATTRIBS_ARB, temp);
+ max_vertex_attribs = temp.get(0);
+ } else
+ max_vertex_attribs = 0;
+ glVertexAttribPointer_buffer = new Buffer[max_vertex_attribs];
+
+ int max_texture_units;
+ if (caps.OpenGL20) {
+ GL11.glGetInteger(GL20.GL_MAX_TEXTURE_IMAGE_UNITS, temp);
+ max_texture_units = temp.get(0);
+ } else if (caps.OpenGL13 || caps.GL_ARB_multitexture) {
+ GL11.glGetInteger(GL13.GL_MAX_TEXTURE_UNITS, temp);
+ max_texture_units = temp.get(0);
+ } else
+ max_texture_units = 1;
+ glTexCoordPointer_buffer = new Buffer[max_texture_units];
+ }
+
+ void clear() {
+ this.elementArrayBuffer = 0;
+ this.arrayBuffer = 0;
+ this.glClientActiveTexture = 0;
+ Arrays.fill(glVertexAttribPointer_buffer, null);
+ Arrays.fill(glTexCoordPointer_buffer, null);
+
+ this.pixelPackBuffer = 0;
+ this.pixelUnpackBuffer = 0;
+
+ this.indirectBuffer = 0;
+ }
+
+ void copy(BaseReferences references, int mask) {
+ if ( (mask & GL11.GL_CLIENT_VERTEX_ARRAY_BIT) != 0 ) {
+ this.elementArrayBuffer = references.elementArrayBuffer;
+ this.arrayBuffer = references.arrayBuffer;
+ this.glClientActiveTexture = references.glClientActiveTexture;
+ System.arraycopy(references.glVertexAttribPointer_buffer, 0, glVertexAttribPointer_buffer, 0, glVertexAttribPointer_buffer.length);
+ System.arraycopy(references.glTexCoordPointer_buffer, 0, glTexCoordPointer_buffer, 0, glTexCoordPointer_buffer.length);
+
+ this.indirectBuffer = references.indirectBuffer;
+ }
+
+ if ( (mask & GL11.GL_CLIENT_PIXEL_STORE_BIT) != 0 ) {
+ this.pixelPackBuffer = references.pixelPackBuffer;
+ this.pixelUnpackBuffer = references.pixelUnpackBuffer;
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/Context.java b/src/java/org/lwjgl/opengl/Context.java
new file mode 100644
index 0000000..36119ab
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/Context.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+/**
+ *
+ * Context encapsulates an OpenGL context.
+ *
+ *
+ * This class is thread-safe.
+ *
+ * @author elias_naur
+ * @version $Revision: 3117 $
+ * $Id: Context.java 3117 2008-08-19 17:47:24Z spasi $
+ */
+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;
+
+ private final IntBuffer attribList;
+ private final boolean forwardCompatible;
+
+ /** 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();
+ implementation = createImplementation();
+ }
+
+ private static ContextImplementation createImplementation() {
+ switch ( LWJGLUtil.getPlatform() ) {
+ case LWJGLUtil.PLATFORM_LINUX:
+ return new LinuxContextImplementation();
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ return new WindowsContextImplementation();
+ case LWJGLUtil.PLATFORM_MACOSX:
+ return new MacOSXContextImplementation();
+ default:
+ throw new IllegalStateException("Unsupported platform");
+ }
+ }
+
+ 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 */
+ Context(PeerInfo peer_info, ContextAttribs attribs, 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;
+ if ( attribs != null ) {
+ attribList = attribs.getAttribList();
+ forwardCompatible = attribs.isForwardCompatible();
+ } else {
+ attribList = null;
+ forwardCompatible = false;
+ }
+
+ this.handle = implementation.create(peer_info, attribList, 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();
+ }
+ }
+ }
+
+ /**
+ * Release the context from its drawable. This is necessary on some platforms,
+ * like Mac OS X, where binding the context to a drawable and binding the context
+ * for rendering are two distinct actions and where calling releaseDrawable
+ * on every releaseCurrentContext results in artifacts.
+ */
+ public synchronized void releaseDrawable() throws LWJGLException {
+ if ( destroyed )
+ throw new IllegalStateException("Context is destroyed");
+ implementation.releaseDrawable(getHandle());
+ }
+
+ /** Update the context. Should be called whenever it's drawable is moved or resized */
+ public synchronized void update() {
+ if ( destroyed )
+ throw new IllegalStateException("Context is destroyed");
+ implementation.update(getHandle());
+ }
+
+ /** 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, forwardCompatible);
+ }
+
+ ByteBuffer getHandle() {
+ return handle;
+ }
+
+ /** 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 {
+ releaseDrawable();
+ implementation.destroy(peer_info, handle);
+ destroyed = true;
+ thread = null;
+ GLContext.unloadOpenGLLibrary();
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while destroying context: " + e);
+ }
+ }
+ }
+
+ /**
+ * Set the buffer swap interval. This call is a best-attempt at changing
+ * the monitor swap interval, which is the minimum periodicity of color buffer swaps,
+ * measured in video frame periods, and is not guaranteed to be successful.
+ *
+ * A video frame period is the time required to display a full frame of video data.
+ */
+ public static void setSwapInterval(int value) {
+ implementation.setSwapInterval(value);
+ }
+
+ /**
+ * 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 ) {
+ if ( GLContext.getCapabilities() != null && GLContext.getCapabilities().OpenGL11 )
+ error = GL11.glGetError();
+ releaseCurrentContext();
+ }
+ checkDestroy();
+ if ( was_current && error != GL11.GL_NO_ERROR )
+ throw new OpenGLException(error);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/ContextAttribs.java b/src/java/org/lwjgl/opengl/ContextAttribs.java
new file mode 100644
index 0000000..59d951f
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/ContextAttribs.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLUtil;
+
+import java.nio.IntBuffer;
+
+/**
+ * This class represents the context attributes passed to CreateContextAttribs of the XGL_create_context extension.
+ * These attributes can be used to indicate at context creation which OpenGL interface will be used. This includes the
+ * OpenGL version, the layer plane on which rendering takes place and also optional debug and forward combatibility modes.
+ * (read the XGL_create_context spec for details)
+ *
+ * Use of this class is optional. If an OpenGL context is created without passing an instance of this class
+ * (or XGL_create_context is not supported), the old context creation code will be used. Use of ContextAttribs is required
+ * to create an OpenGL 3.0 or newer context. Support for debug and forward compatible mobes is not guaranteed by the OpenGL
+ * implementation. Developers may encounter debug contexts being the same as non-debug contexts or forward compatible
+ * contexts having support for deprecated functionality.
+ *
+ * If the forwardCompatible
+ * attribute is used, LWJGL will not load the deprecated functionality (as defined in the OpenGL 3.0 specification). This
+ * means that developers can start working on cleaning up their applications without an OpenGL 3.0 complaint driver.
+ *
+ * @author spasi
+ */
+public final class ContextAttribs {
+
+ private int majorVersion;
+ private int minorVersion;
+
+ private int layerPlane;
+
+ private boolean debug;
+ private boolean forwardCompatible;
+
+ private boolean profileCore;
+ private boolean profileCompatibility;
+
+ public ContextAttribs() {
+ this(1, 0);
+ }
+
+ public ContextAttribs(final int majorVersion, final int minorVersion) {
+ if ( majorVersion < 0 ||
+ 3 < majorVersion ||
+ minorVersion < 0 ||
+ (majorVersion == 3 && 2 < minorVersion) ||
+ (majorVersion == 2 && 1 < minorVersion) ||
+ (majorVersion == 1 && 5 < minorVersion) )
+ throw new IllegalArgumentException("Invalid OpenGL version specified: " + majorVersion + '.' + minorVersion);
+
+ this.majorVersion = majorVersion;
+ this.minorVersion = minorVersion;
+
+ this.layerPlane = 0;
+
+ this.debug = false;
+ this.forwardCompatible = false;
+
+ this.profileCore = 3 < majorVersion || (majorVersion == 3 && 2 <= minorVersion) ? true : false;
+ this.profileCompatibility = false;
+ }
+
+ private ContextAttribs(final ContextAttribs attribs) {
+ this.majorVersion = attribs.majorVersion;
+ this.minorVersion = attribs.minorVersion;
+
+ this.layerPlane = attribs.layerPlane;
+
+ this.debug = attribs.debug;
+ this.forwardCompatible = attribs.forwardCompatible;
+
+ this.profileCore = attribs.profileCore;
+ this.profileCompatibility = attribs.profileCompatibility;
+ }
+
+ public int getMajorVersion() {
+ return majorVersion;
+ }
+
+ public int getMinorVersion() {
+ return minorVersion;
+ }
+
+ public int getLayerPlane() {
+ return layerPlane;
+ }
+
+ public boolean isDebug() {
+ return debug;
+ }
+
+ public boolean isForwardCompatible() {
+ return forwardCompatible;
+ }
+
+ public boolean isProfileCore() {
+ return profileCore;
+ }
+
+ public boolean isProfileCompatibility() {
+ return profileCompatibility;
+ }
+
+ public ContextAttribs withLayer(final int layerPlane) {
+ if ( layerPlane < 0 )
+ throw new IllegalArgumentException("Invalid layer plane specified: " + layerPlane);
+
+ if ( layerPlane == this.layerPlane )
+ return this;
+
+ final ContextAttribs attribs = new ContextAttribs(this);
+ attribs.layerPlane = layerPlane;
+ return attribs;
+ }
+
+ public ContextAttribs withDebug(final boolean debug) {
+ if ( debug == this.debug )
+ return this;
+
+ final ContextAttribs attribs = new ContextAttribs(this);
+ attribs.debug = debug;
+ return attribs;
+ }
+
+ public ContextAttribs withForwardCompatible(final boolean forwardCompatible) {
+ if ( forwardCompatible == this.forwardCompatible )
+ return this;
+
+ final ContextAttribs attribs = new ContextAttribs(this);
+ attribs.forwardCompatible = forwardCompatible;
+ return attribs;
+ }
+
+ public ContextAttribs withProfileCore(final boolean profileCore) {
+ if ( majorVersion < 3 || (majorVersion == 3 && minorVersion < 2) )
+ throw new IllegalArgumentException("Profiles are only supported on OpenGL version 3.2 or higher.");
+
+ if ( profileCore == this.profileCore )
+ return this;
+
+ final ContextAttribs attribs = new ContextAttribs(this);
+ attribs.profileCore = profileCore;
+ if ( profileCore )
+ attribs.profileCompatibility = false;
+
+ return attribs;
+ }
+
+ public ContextAttribs withProfileCompatibility(final boolean profileCompatibility) {
+ if ( majorVersion < 3 || (majorVersion == 3 && minorVersion < 2) )
+ throw new IllegalArgumentException("Profiles are only supported on OpenGL version 3.2 or higher.");
+
+ if ( profileCompatibility == this.profileCompatibility )
+ return this;
+
+ final ContextAttribs attribs = new ContextAttribs(this);
+ attribs.profileCompatibility = profileCompatibility;
+ if ( profileCompatibility )
+ attribs.profileCore = false;
+
+ return attribs;
+ }
+
+ private static ContextAttribsImplementation getImplementation() {
+ switch ( LWJGLUtil.getPlatform() ) {
+ case LWJGLUtil.PLATFORM_LINUX:
+ return new LinuxContextAttribs();
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ return new WindowsContextAttribs();
+ case LWJGLUtil.PLATFORM_MACOSX:
+ return new MacOSXContextAttribs();
+ default:
+ throw new IllegalStateException("Unsupported platform");
+ }
+ }
+
+ IntBuffer getAttribList() {
+ ContextAttribsImplementation implementation = getImplementation();
+
+ int attribCount = 0;
+
+ if ( !(majorVersion == 1 && minorVersion == 0) )
+ attribCount += 2;
+ if ( 0 < layerPlane )
+ attribCount++;
+
+ int flags = 0;
+ if ( debug )
+ flags |= implementation.getDebugBit();
+ if ( forwardCompatible )
+ flags |= implementation.getForwardCompatibleBit();
+ if ( 0 < flags )
+ attribCount++;
+
+ int profileMask = 0;
+ if ( profileCore )
+ profileMask |= implementation.getProfileCoreBit();
+ else if ( profileCompatibility )
+ profileMask |= implementation.getProfileCompatibilityBit();
+ if ( 0 < profileMask )
+ attribCount++;
+
+ if ( attribCount == 0 )
+ return null;
+
+ final IntBuffer attribs = BufferUtils.createIntBuffer((attribCount * 2) + 1);
+
+ if ( !(majorVersion == 1 && minorVersion == 0) ) {
+ attribs.put(implementation.getMajorVersionAttrib()).put(majorVersion);
+ attribs.put(implementation.getMinorVersionAttrib()).put(minorVersion);
+ }
+ if ( 0 < layerPlane )
+ attribs.put(implementation.getLayerPlaneAttrib()).put(layerPlane);
+ if ( 0 < flags )
+ attribs.put(implementation.getFlagsAttrib()).put(flags);
+ if ( 0 < profileMask )
+ attribs.put(implementation.getProfileMaskAttrib()).put(profileMask);
+
+ attribs.put(0);
+ attribs.rewind();
+ return attribs;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer(32);
+
+ sb.append("ContextAttribs:");
+ sb.append(" Version=").append(majorVersion).append('.').append(minorVersion);
+ sb.append(" - Layer=").append(layerPlane);
+ sb.append(" - Debug=").append(debug);
+ sb.append(" - ForwardCompatible=").append(forwardCompatible);
+ sb.append(" - Profile=");
+ if ( profileCore )
+ sb.append("Core");
+ else if ( profileCompatibility )
+ sb.append("Compatibility");
+ else
+ sb.append("None");
+
+ return sb.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/ContextAttribsImplementation.java b/src/java/org/lwjgl/opengl/ContextAttribsImplementation.java
new file mode 100644
index 0000000..44c320d
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/ContextAttribsImplementation.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/** @author spasi */
+interface ContextAttribsImplementation {
+
+ int getMajorVersionAttrib();
+
+ int getMinorVersionAttrib();
+
+ int getLayerPlaneAttrib();
+
+ int getFlagsAttrib();
+
+ int getDebugBit();
+
+ int getForwardCompatibleBit();
+
+ int getProfileMaskAttrib();
+
+ int getProfileCoreBit();
+
+ int getProfileCompatibilityBit();
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/ContextImplementation.java b/src/java/org/lwjgl/opengl/ContextImplementation.java
new file mode 100644
index 0000000..2e98fbf
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/ContextImplementation.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2002-2008 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 java.nio.IntBuffer;
+
+import org.lwjgl.LWJGLException;
+
+/**
+ *
+ * Context implementation interface.
+ *
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: ContextImplementation.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+interface ContextImplementation {
+ /**
+ * Create a context.
+ */
+ ByteBuffer create(PeerInfo peer_info, IntBuffer attribs, ByteBuffer shared_context_handle) throws LWJGLException;
+
+ /**
+ * Swap the buffers of the current context. Only valid for double-buffered contexts.
+ */
+ void swapBuffers() throws LWJGLException;
+
+ /**
+ * Release the context from its drawable, if any.
+ */
+ void releaseDrawable(ByteBuffer context_handle) throws LWJGLException;
+
+ /**
+ * Release the current context (if any). After this call, no context is current.
+ */
+ void releaseCurrentContext() throws LWJGLException;
+
+ /**
+ * Update the context. Should be called whenever it's drawable is moved or resized
+ */
+ void update(ByteBuffer context_handle);
+
+ /**
+ * Query whether the context is current
+ */
+ void makeCurrent(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException;
+
+ /**
+ * Query whether the context is current
+ */
+ boolean isCurrent(ByteBuffer handle) throws LWJGLException;
+
+ void setSwapInterval(int value);
+
+ /**
+ * Destroys the Context.
+ */
+ 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
new file mode 100644
index 0000000..c9b960e
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/Display.java
@@ -0,0 +1,1127 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is the abstract class for a Display in LWJGL. LWJGL displays have some
+ * peculiar characteristics:
+ *
+ * - the display may be closeable by the user or operating system, and may be minimized
+ * by the user or operating system
+ * - only one display may ever be open at once
+ * - the operating system may or may not be able to do fullscreen or windowed displays.
+ *
+ * @author foo
+ */
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+import org.lwjgl.input.Controllers;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.HashSet;
+
+public final class Display {
+
+ private static final Thread shutdown_hook = new Thread() {
+ public void run() {
+ reset();
+ }
+ };
+
+ /** The display implementor */
+ private static final DisplayImplementation display_impl;
+
+ /** The initial display mode */
+ private static final DisplayMode initial_mode;
+
+ /** The parent, if any */
+ private static Canvas parent;
+
+ /** The current display mode, if created */
+ private static DisplayMode current_mode;
+
+ /** Timer for sync() */
+ private static long timeThen;
+
+ /** X coordinate of the window */
+ private static int x = -1;
+
+ /** Cached window icons, for when Display is recreated */
+ private static ByteBuffer[] cached_icons;
+
+ /**
+ * Y coordinate of the window. Y in window coordinates is from the top of the display down,
+ * unlike GL, where it is typically at the bottom of the display.
+ */
+ private static int y = -1;
+
+ /** Title of the window (never null) */
+ private static String title = "Game";
+
+ /** Fullscreen */
+ private static boolean fullscreen;
+
+ /** Swap interval */
+ private static int swap_interval;
+
+ /** A unique context object, so we can track different contexts between creates() and destroys() */
+ private static PeerInfo peer_info;
+ private static Context context;
+
+ /** The Drawable instance that tracks the current Display context */
+ private final static Drawable drawable;
+
+ private static boolean window_created = false;
+
+ private static boolean parent_resized;
+
+ /** Initial Background Color of Display */
+ private static float r = 0, g = 0, b = 0;
+
+ private static ComponentListener component_listener = new ComponentAdapter() {
+ public void componentResized(ComponentEvent e) {
+ synchronized ( GlobalLock.lock ) {
+ parent_resized = true;
+ }
+ }
+ };
+
+ static {
+ Sys.initialize();
+ display_impl = createDisplayImplementation();
+ try {
+ current_mode = initial_mode = display_impl.init();
+ LWJGLUtil.log("Initial mode: " + initial_mode);
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+ drawable = new Drawable() {
+ public Context getContext() {
+ synchronized ( GlobalLock.lock ) {
+ return isCreated() ? context : null;
+ }
+ }
+ };
+ }
+
+ /**
+ * Fetch the Drawable from the Display.
+ *
+ * @return the Drawable corresponding to the Display context
+ */
+ public static Drawable getDrawable() {
+ return drawable;
+ }
+
+ private static DisplayImplementation createDisplayImplementation() {
+ switch ( LWJGLUtil.getPlatform() ) {
+ case LWJGLUtil.PLATFORM_LINUX:
+ return new LinuxDisplay();
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ return new WindowsDisplay();
+ case LWJGLUtil.PLATFORM_MACOSX:
+ return new MacOSXDisplay();
+ default:
+ throw new IllegalStateException("Unsupported platform");
+ }
+ }
+
+ /** Only constructed by ourselves */
+ private Display() {
+ }
+
+ /**
+ * Returns the entire list of possible fullscreen display modes as an array, in no
+ * particular order. Although best attempts to filter out invalid modes are done, any
+ * given mode is not guaranteed to be available nor is it guaranteed to be within the
+ * current monitor specs (this is especially a problem with the frequency parameter).
+ * Furthermore, it is not guaranteed that create() will detect an illegal display mode.
+ *
+ * The only certain way to check
+ * is to call create() and make sure it works.
+ * Only non-palette-indexed modes are returned (ie. bpp will be 16, 24, or 32).
+ * Only DisplayModes from this call can be used when the Display is in fullscreen
+ * mode.
+ *
+ * @return an array of all display modes the system reckons it can handle.
+ */
+ public static DisplayMode[] getAvailableDisplayModes() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ DisplayMode[] unfilteredModes = display_impl.getAvailableDisplayModes();
+
+ if ( unfilteredModes == null ) {
+ return new DisplayMode[0];
+ }
+
+ // We'll use a HashSet to filter out the duplicated modes
+ HashSet modes = new HashSet(unfilteredModes.length);
+
+ modes.addAll(Arrays.asList(unfilteredModes));
+ DisplayMode[] filteredModes = new DisplayMode[modes.size()];
+ modes.toArray(filteredModes);
+
+ LWJGLUtil.log("Removed " + (unfilteredModes.length - filteredModes.length) + " duplicate displaymodes");
+
+ return filteredModes;
+ }
+ }
+
+ /**
+ * Return the initial desktop display mode.
+ *
+ * @return The desktop display mode
+ */
+ public static DisplayMode getDesktopDisplayMode() {
+ return initial_mode;
+ }
+
+ /**
+ * Return the current display mode, as set by setDisplayMode().
+ *
+ * @return The current display mode
+ */
+ public static DisplayMode getDisplayMode() {
+ return current_mode;
+ }
+
+ /**
+ * Set the current display mode. If no OpenGL context has been created, the given mode will apply to
+ * the context when create() is called, and no immediate mode switching will happen. If there is a
+ * context already, it will be resized according to the given mode. If the context is also a
+ * fullscreen context, the mode will also be switched immediately. The native cursor position
+ * is also reset.
+ *
+ * @param mode The new display mode to set
+ *
+ * @throws LWJGLException if the display mode could not be set
+ */
+ public static void setDisplayMode(DisplayMode mode) throws LWJGLException {
+ synchronized (GlobalLock.lock) {
+ if (mode == null)
+ throw new NullPointerException("mode must be non-null");
+ boolean was_fullscreen = isFullscreen();
+ current_mode = mode;
+ if (isCreated()) {
+ destroyWindow();
+ // If mode is not fullscreen capable, make sure we are in windowed mode
+ try {
+ if (was_fullscreen && !isFullscreen())
+ display_impl.resetDisplayMode();
+ else if (isFullscreen())
+ switchDisplayMode();
+ createWindow();
+ makeCurrentAndSetSwapInterval();
+ } catch (LWJGLException e) {
+ destroyContext();
+ destroyPeerInfo();
+ display_impl.resetDisplayMode();
+ throw e;
+ }
+ }
+ }
+ }
+
+ private static DisplayMode getEffectiveMode() {
+ return !isFullscreen() && parent != null ? new DisplayMode(parent.getWidth(), parent.getHeight()) : current_mode;
+ }
+
+ private static int getWindowX() {
+ if (!isFullscreen() && parent == null) {
+ // if no display location set, center window
+ if (x == -1) {
+ return Math.max(0, (initial_mode.getWidth() - current_mode.getWidth()) / 2);
+ } else {
+ return x;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ private static int getWindowY() {
+ if (!isFullscreen() && parent == null) {
+ // if no display location set, center window
+ if ( y == -1 ) {
+ return Math.max(0, (initial_mode.getHeight() - current_mode.getHeight()) / 2);
+ } else {
+ return y;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Create the native window peer from the given mode and fullscreen flag.
+ * A native context must exist, and it will be attached to the window.
+ */
+ private static void createWindow() throws LWJGLException {
+ if ( window_created ) {
+ return;
+ }
+ Canvas tmp_parent = isFullscreen() ? null : parent;
+ if ( tmp_parent != null && !tmp_parent.isDisplayable() ) // Only a best effort check, since the parent can turn undisplayable hereafter
+ throw new LWJGLException("Parent.isDisplayable() must be true");
+ if ( tmp_parent != null ) {
+ tmp_parent.addComponentListener(component_listener);
+ }
+ DisplayMode mode = getEffectiveMode();
+ display_impl.createWindow(mode, tmp_parent, getWindowX(), getWindowY());
+ window_created = true;
+
+ setTitle(title);
+ initControls();
+
+ // set cached window icon if exists
+ if ( cached_icons != null ) {
+ setIcon(cached_icons);
+ } else {
+ setIcon(new ByteBuffer[] { LWJGLUtil.LWJGLIcon32x32, LWJGLUtil.LWJGLIcon16x16 });
+ }
+ }
+
+ private static void releaseDrawable() {
+ try {
+ if ( context != null && context.isCurrent() ) {
+ Context.releaseCurrentContext();
+ context.releaseDrawable();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while trying to release context: " + e);
+ }
+ }
+
+ private static void destroyWindow() {
+ if ( !window_created ) {
+ return;
+ }
+ if ( parent != null ) {
+ parent.removeComponentListener(component_listener);
+ }
+ releaseDrawable();
+
+ // Automatically destroy keyboard & mouse
+ if ( Mouse.isCreated() ) {
+ Mouse.destroy();
+ }
+ if ( Keyboard.isCreated() ) {
+ Keyboard.destroy();
+ }
+ display_impl.destroyWindow();
+ window_created = false;
+ }
+
+ private static void switchDisplayMode() throws LWJGLException {
+ if ( !current_mode.isFullscreenCapable() ) {
+ throw new IllegalStateException("Only modes acquired from getAvailableDisplayModes() can be used for fullscreen display");
+ }
+ display_impl.switchDisplayMode(current_mode);
+ }
+
+ /**
+ * Set the display configuration to the specified gamma, brightness and contrast.
+ * The configuration changes will be reset when destroy() is called.
+ *
+ * @param gamma The gamma value
+ * @param brightness The brightness value between -1.0 and 1.0, inclusive
+ * @param contrast The contrast, larger than 0.0.
+ */
+ public static void setDisplayConfiguration(float gamma, float brightness, float contrast) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() ) {
+ throw new LWJGLException("Display not yet created.");
+ }
+ if ( brightness < -1.0f || brightness > 1.0f )
+ throw new IllegalArgumentException("Invalid brightness value");
+ if ( contrast < 0.0f )
+ throw new IllegalArgumentException("Invalid contrast value");
+ int rampSize = display_impl.getGammaRampLength();
+ if ( rampSize == 0 ) {
+ throw new LWJGLException("Display configuration not supported");
+ }
+ FloatBuffer gammaRamp = BufferUtils.createFloatBuffer(rampSize);
+ for ( int i = 0; i < rampSize; i++ ) {
+ float intensity = (float)i / (rampSize - 1);
+ // apply gamma
+ float rampEntry = (float)java.lang.Math.pow(intensity, gamma);
+ // apply brightness
+ rampEntry += brightness;
+ // apply contrast
+ rampEntry = (rampEntry - 0.5f) * contrast + 0.5f;
+ // Clamp entry to [0, 1]
+ if ( rampEntry > 1.0f )
+ rampEntry = 1.0f;
+ else if ( rampEntry < 0.0f )
+ rampEntry = 0.0f;
+ gammaRamp.put(i, rampEntry);
+ }
+ display_impl.setGammaRamp(gammaRamp);
+ LWJGLUtil.log("Gamma set, gamma = " + gamma + ", brightness = " + brightness + ", contrast = " + contrast);
+ }
+ }
+
+ private static long timeLate;
+
+ /**
+ * Best sync method that works reliably.
+ *
+ * @param fps The desired frame rate, in frames per second
+ */
+ public static void sync(int fps) {
+ long timeNow;
+ long gapTo;
+ long savedTimeLate;
+ synchronized ( GlobalLock.lock ) {
+ gapTo = Sys.getTimerResolution() / fps + timeThen;
+ timeNow = Sys.getTime();
+ savedTimeLate = timeLate;
+ }
+
+ while ( gapTo > timeNow + savedTimeLate ) {
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ }
+ timeNow = Sys.getTime();
+ }
+
+ synchronized ( GlobalLock.lock ) {
+ if ( gapTo < timeNow )
+ timeLate = timeNow - gapTo;
+ else
+ timeLate = 0;
+
+ timeThen = timeNow;
+ }
+ }
+
+ /** @return the title of the window */
+ public static String getTitle() {
+ synchronized ( GlobalLock.lock ) {
+ return title;
+ }
+ }
+
+ /** Return the last parent set with setParent(). */
+ public static Canvas getParent() {
+ synchronized ( GlobalLock.lock ) {
+ return parent;
+ }
+ }
+
+ /**
+ * Set the parent of the Display. If parent is null, the Display will appear as a top level window.
+ * If parent is not null, the Display is made a child of the parent. A parent's isDisplayable() must be true when
+ * setParent() is called and remain true until setParent() is called again with
+ * null or a different parent. This generally means that the parent component must remain added to it's parent container.
+ * It is not advisable to call this method from an AWT thread, since the context will be made current on the thread
+ * and it is difficult to predict which AWT thread will process any given AWT event.
+ * While the Display is in fullscreen mode, the current parent will be ignored. Additionally, when a non null parent is specified,
+ * the Dispaly will inherit the size of the parent, disregarding the currently set display mode.
+ */
+ public static void setParent(Canvas parent) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if (Display.parent != parent) {
+ Display.parent = parent;
+ if ( !isCreated() )
+ return;
+ destroyWindow();
+ try {
+ if (isFullscreen()) {
+ switchDisplayMode();
+ } else {
+ display_impl.resetDisplayMode();
+ }
+ createWindow();
+ makeCurrentAndSetSwapInterval();
+ } catch (LWJGLException e) {
+ destroyContext();
+ destroyPeerInfo();
+ display_impl.resetDisplayMode();
+ throw e;
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the fullscreen mode of the context. If no context has been created through create(),
+ * the mode will apply when create() is called. If fullscreen is true, the context will become
+ * a fullscreen context and the display mode is switched to the mode given by getDisplayMode(). If
+ * fullscreen is false, the context will become a windowed context with the dimensions given in the
+ * mode returned by getDisplayMode(). The native cursor position is also reset.
+ *
+ * @param fullscreen Specify the fullscreen mode of the context.
+ *
+ * @throws LWJGLException If fullscreen is true, and the current DisplayMode instance is not
+ * from getAvailableDisplayModes() or if the mode switch fails.
+ */
+ public static void setFullscreen(boolean fullscreen) throws LWJGLException {
+ setDisplayModeAndFullscreenInternal(fullscreen, current_mode);
+ }
+
+ /**
+ * Set the mode of the context. If no context has been created through create(),
+ * the mode will apply when create() is called. If mode.isFullscreenCapable() is true, the context will become
+ * a fullscreen context and the display mode is switched to the mode given by getDisplayMode(). If
+ * mode.isFullscreenCapable() is false, the context will become a windowed context with the dimensions given in the
+ * mode returned by getDisplayMode(). The native cursor position is also reset.
+ *
+ * @param mode The new display mode to set. Must be non-null.
+ *
+ * @throws LWJGLException If the mode switch fails.
+ */
+ public static void setDisplayModeAndFullscreen(DisplayMode mode) throws LWJGLException {
+ setDisplayModeAndFullscreenInternal(mode.isFullscreenCapable(), mode);
+ }
+
+ private static void setDisplayModeAndFullscreenInternal(boolean fullscreen, DisplayMode mode) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if (mode == null)
+ throw new NullPointerException("mode must be non-null");
+ DisplayMode old_mode = current_mode;
+ current_mode = mode;
+ boolean was_fullscreen = isFullscreen();
+ Display.fullscreen = fullscreen;
+ if (was_fullscreen != isFullscreen() || !mode.equals(old_mode)) {
+ if (!isCreated())
+ return;
+ destroyWindow();
+ try {
+ if (isFullscreen()) {
+ switchDisplayMode();
+ } else {
+ display_impl.resetDisplayMode();
+ }
+ createWindow();
+ makeCurrentAndSetSwapInterval();
+ } catch (LWJGLException e) {
+ destroyContext();
+ destroyPeerInfo();
+ display_impl.resetDisplayMode();
+ throw e;
+ }
+ }
+ }
+ }
+
+ /** @return whether the Display is in fullscreen mode */
+ public static boolean isFullscreen() {
+ synchronized (GlobalLock.lock) {
+ return fullscreen && current_mode.isFullscreenCapable();
+ }
+ }
+
+ /**
+ * Set the title of the window. This may be ignored by the underlying OS.
+ *
+ * @param newTitle The new window title
+ */
+ public static void setTitle(String newTitle) {
+ synchronized ( GlobalLock.lock ) {
+ if ( newTitle == null ) {
+ newTitle = "";
+ }
+ title = newTitle;
+ if ( isCreated() )
+ display_impl.setTitle(title);
+ }
+ }
+
+ /** @return true if the user or operating system has asked the window to close */
+ public static boolean isCloseRequested() {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Cannot determine close requested state of uncreated window");
+ return display_impl.isCloseRequested();
+ }
+ }
+
+ /** @return true if the window is visible, false if not */
+ public static boolean isVisible() {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Cannot determine minimized state of uncreated window");
+ return display_impl.isVisible();
+ }
+ }
+
+ /** @return true if window is active, that is, the foreground display of the operating system. */
+ public static boolean isActive() {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Cannot determine focused state of uncreated window");
+ return display_impl.isActive();
+ }
+ }
+
+ /**
+ * Determine if the window's contents have been damaged by external events.
+ * If you are writing a straightforward game rendering loop and simply paint
+ * every frame regardless, you can ignore this flag altogether. If you are
+ * trying to be kind to other processes you can check this flag and only
+ * redraw when it returns true. The flag is cleared when update() or isDirty() is called.
+ *
+ * @return true if the window has been damaged by external changes
+ * and needs to repaint itself
+ */
+ public static boolean isDirty() {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Cannot determine dirty state of uncreated window");
+ return display_impl.isDirty();
+ }
+ }
+
+ /**
+ * Process operating system events. Call this to update the Display's state and to receive new
+ * input device events. This method is called from update(), so it is not necessary to call
+ * this method if update() is called periodically.
+ */
+ public static void processMessages() {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Display not created");
+
+ display_impl.update();
+ }
+ pollDevices();
+ }
+
+ /**
+ * Swap the display buffers. This method is called from update(), and should normally not be called by
+ * the application.
+ *
+ * @throws OpenGLException if an OpenGL error has occured since the last call to GL11.glGetError()
+ */
+ public static void swapBuffers() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Display not created");
+
+ if ( LWJGLUtil.DEBUG )
+ Util.checkGLError();
+ Context.swapBuffers();
+ }
+ }
+
+ /**
+ * Update the window. If the window is visible clears
+ * the dirty flag and calls swapBuffers() and finally
+ * polls the input devices.
+ *
+ */
+ public static void update() {
+ update(true);
+ }
+
+ /**
+ * Update the window. If the window is visible clears
+ * the dirty flag and calls swapBuffers() and finally
+ * polls the input devices if processMessages is true.
+ *
+ * @param processMessages Poll input devices if true
+ */
+ public static void update(boolean processMessages) {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Display not created");
+
+ // We paint only when the window is visible or dirty
+ if ( display_impl.isVisible() || display_impl.isDirty() ) {
+ try {
+ swapBuffers();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ if ( parent_resized ) {
+ reshape();
+ parent_resized = false;
+ }
+
+ if ( processMessages )
+ processMessages();
+ }
+ }
+
+ static void pollDevices() {
+ // Poll the input devices while we're here
+ if ( Mouse.isCreated() ) {
+ Mouse.poll();
+ Mouse.updateCursor();
+ }
+
+ if ( Keyboard.isCreated() ) {
+ Keyboard.poll();
+ }
+
+ if ( Controllers.isCreated() ) {
+ Controllers.poll();
+ }
+ }
+
+ /**
+ * Release the Display context.
+ *
+ * @throws LWJGLException If the context could not be released
+ */
+ public static void releaseContext() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Display is not created");
+ if ( context.isCurrent() )
+ Context.releaseCurrentContext();
+ }
+ }
+
+ /**
+ * Make the Display the current rendering context for GL calls.
+ *
+ * @throws LWJGLException If the context could not be made current
+ */
+ public static void makeCurrent() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ throw new IllegalStateException("Display is not created");
+ context.makeCurrent();
+ }
+ }
+
+ private static void removeShutdownHook() {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ Runtime.getRuntime().removeShutdownHook(shutdown_hook);
+ return null;
+ }
+ });
+ }
+
+ private static void registerShutdownHook() {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ Runtime.getRuntime().addShutdownHook(shutdown_hook);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Create the OpenGL context. 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.
+ *
+ * @throws LWJGLException
+ */
+ public static void create() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ create(new PixelFormat());
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @throws LWJGLException
+ */
+ public static void create(PixelFormat pixel_format) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ create(pixel_format, null, 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. (optional, may be null)
+ *
+ * @throws LWJGLException
+ */
+ public static void create(PixelFormat pixel_format, Drawable shared_drawable) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ create(pixel_format, shared_drawable, 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 attribs The ContextAttribs to use when creating the context. (optional, may be null)
+ *
+ * @throws LWJGLException
+ */
+ public static void create(PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ create(pixel_format, null, attribs);
+ }
+ }
+
+ /**
+ * 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. (optional, may be null)
+ * @param attribs The ContextAttribs to use when creating the context. (optional, may be null)
+ *
+ * @throws LWJGLException
+ */
+ public static void create(PixelFormat pixel_format, Drawable shared_drawable, ContextAttribs attribs) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if ( isCreated() )
+ throw new IllegalStateException("Only one LWJGL context may be instantiated at any one time.");
+ if ( pixel_format == null )
+ throw new NullPointerException("pixel_format cannot be null");
+ removeShutdownHook();
+ registerShutdownHook();
+ if (isFullscreen())
+ switchDisplayMode();
+ try {
+ peer_info = display_impl.createPeerInfo(pixel_format);
+ try {
+ createWindow();
+ try {
+ context = new Context(peer_info, attribs, shared_drawable != null ? shared_drawable.getContext() : null);
+ try {
+ makeCurrentAndSetSwapInterval();
+ initContext();
+ } catch (LWJGLException e) {
+ destroyContext();
+ throw e;
+ }
+ } catch (LWJGLException e) {
+ destroyWindow();
+ throw e;
+ }
+ } catch (LWJGLException e) {
+ destroyPeerInfo();
+ throw e;
+ }
+ } catch (LWJGLException e) {
+ display_impl.resetDisplayMode();
+ throw e;
+ }
+ }
+ }
+
+ /**
+ * Set the initial color of the Display. This method is called before the Display is created and will set the
+ * background color to the one specified in this method.
+ *
+ * @param red - color value between 0 - 1
+ * @param green - color value between 0 - 1
+ * @param blue - color value between 0 - 1
+ */
+ public static void setInitialBackground(float red, float green, float blue) {
+ r = red;
+ g = green;
+ b = blue;
+ }
+
+ private static void makeCurrentAndSetSwapInterval() throws LWJGLException {
+ makeCurrent();
+ try {
+ Util.checkGLError();
+ } catch (OpenGLException e) {
+ LWJGLUtil.log("OpenGL error during context creation: " + e.getMessage());
+ }
+ setSwapInterval(swap_interval);
+ }
+
+ private static void initContext() {
+ // set background clear color
+ GL11.glClearColor(r, g, b, 1.0f);
+ // Clear window to avoid the desktop "showing through"
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ update();
+ }
+
+ static DisplayImplementation getImplementation() {
+ return display_impl;
+ }
+
+ /** Gets a boolean property as a privileged action. */
+ static boolean getPrivilegedBoolean(final String property_name) {
+ Boolean value = (Boolean)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return new Boolean(Boolean.getBoolean(property_name));
+ }
+ });
+ return value.booleanValue();
+ }
+
+ private static void initControls() {
+ // Automatically create mouse, keyboard and controller
+ if ( !getPrivilegedBoolean("org.lwjgl.opengl.Display.noinput") ) {
+ if ( !Mouse.isCreated() && !getPrivilegedBoolean("org.lwjgl.opengl.Display.nomouse") ) {
+ try {
+ Mouse.create();
+ } catch (LWJGLException e) {
+ if ( LWJGLUtil.DEBUG ) {
+ e.printStackTrace(System.err);
+ } else {
+ LWJGLUtil.log("Failed to create Mouse: " + e);
+ }
+ }
+ }
+ if ( !Keyboard.isCreated() && !getPrivilegedBoolean("org.lwjgl.opengl.Display.nokeyboard") ) {
+ try {
+ Keyboard.create();
+ } catch (LWJGLException e) {
+ if ( LWJGLUtil.DEBUG ) {
+ e.printStackTrace(System.err);
+ } else {
+ LWJGLUtil.log("Failed to create Keyboard: " + e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Destroy the Display. After this call, there will be no current GL rendering context,
+ * regardless of whether the Display was the current rendering context.
+ */
+ public static void destroy() {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() ) {
+ return;
+ }
+
+ releaseDrawable();
+ destroyContext();
+ destroyWindow();
+ destroyPeerInfo();
+ x = y = -1;
+ cached_icons = null;
+ reset();
+ removeShutdownHook();
+ }
+ }
+
+ private static void destroyPeerInfo() {
+ peer_info.destroy();
+ peer_info = null;
+ }
+
+ private static void destroyContext() {
+ try {
+ context.forceDestroy();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ context = null;
+ }
+ }
+
+ /*
+ * Reset display mode if fullscreen. This method is also called from the shutdown hook added
+ * in the static constructor
+ */
+ private static void reset() {
+ display_impl.resetDisplayMode();
+ current_mode = initial_mode;
+ }
+
+ /** @return true if the window's native peer has been created */
+ public static boolean isCreated() {
+ synchronized ( GlobalLock.lock ) {
+ return window_created;
+ }
+ }
+
+ /**
+ * Set the buffer swap interval. This call is a best-attempt at changing
+ * the monitor swap interval, which is the minimum periodicity of color buffer swaps,
+ * measured in video frame periods, and is not guaranteed to be successful.
+ *
+ * A video frame period is the time required to display a full frame of video data.
+ *
+ * @param value The swap interval in frames, 0 to disable
+ */
+ public static void setSwapInterval(int value) {
+ synchronized ( GlobalLock.lock ) {
+ swap_interval = value;
+ if ( isCreated() )
+ Context.setSwapInterval(swap_interval);
+ }
+ }
+
+ /**
+ * Enable or disable vertical monitor synchronization. This call is a best-attempt at changing
+ * the vertical refresh synchronization of the monitor, and is not guaranteed to be successful.
+ *
+ * @param sync true to synchronize; false to ignore synchronization
+ */
+ public static void setVSyncEnabled(boolean sync) {
+ synchronized ( GlobalLock.lock ) {
+ setSwapInterval(sync ? 1 : 0);
+ }
+ }
+
+ /**
+ * Set the window's location. This is a no-op on fullscreen windows or when getParent() != null.
+ * The window is clamped to remain entirely on the screen. If you attempt
+ * to position the window such that it would extend off the screen, the window
+ * is simply placed as close to the edge as possible.
+ *
noteIf no location has been specified (or x == y == -1) the window will be centered
+ *
+ * @param new_x The new window location on the x axis
+ * @param new_y The new window location on the y axis
+ */
+ public static void setLocation(int new_x, int new_y) {
+ synchronized ( GlobalLock.lock ) {
+ // cache position
+ x = new_x;
+ y = new_y;
+
+ // offset if already created
+ if (isCreated() && !isFullscreen()) {
+ reshape();
+ }
+ }
+ }
+
+ private static void reshape() {
+ DisplayMode mode = getEffectiveMode();
+ display_impl.reshape(getWindowX(), getWindowY(), mode.getWidth(), mode.getHeight());
+ }
+
+ /**
+ * Get the driver adapter string. This is a unique string describing the actual card's hardware, eg. "Geforce2", "PS2",
+ * "Radeon9700". If the adapter cannot be determined, this function returns null.
+ *
+ * @return a String
+ */
+ public static String getAdapter() {
+ synchronized ( GlobalLock.lock ) {
+ return display_impl.getAdapter();
+ }
+ }
+
+ /**
+ * Get the driver version. This is a vendor/adapter specific version string. If the version cannot be determined,
+ * this function returns null.
+ *
+ * @return a String
+ */
+ public static String getVersion() {
+ synchronized ( GlobalLock.lock ) {
+ return display_impl.getVersion();
+ }
+ }
+
+ /**
+ * Sets one or more icons for the Display.
+ *
+ * - On Windows you should supply at least one 16x16 icon and one 32x32.
+ * - Linux (and similar platforms) expect one 32x32 icon.
+ * - Mac OS X should be supplied one 128x128 icon
+ *
+ * The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions nescesarry for the specific platform.
+ *
+ * NOTE: The display will make a deep copy of the supplied byte buffer array, for the purpose
+ * of recreating the icons when you go back and forth fullscreen mode. You therefore only need to
+ * set the icon once per instance.
+ *
+ * @param icons Array of icons in RGBA mode. Pass the icons in order of preference.
+ *
+ * @return number of icons used, or 0 if display hasn't been created
+ */
+ public static int setIcon(ByteBuffer[] icons) {
+ synchronized ( GlobalLock.lock ) {
+ // make deep copy so we dont rely on the supplied buffers later on
+ // don't recache!
+ if ( cached_icons != icons ) {
+ cached_icons = new ByteBuffer[icons.length];
+ for ( int i = 0; i < icons.length; i++ ) {
+ cached_icons[i] = BufferUtils.createByteBuffer(icons[i].capacity());
+ int old_position = icons[i].position();
+ cached_icons[i].put(icons[i]);
+ icons[i].position(old_position);
+ cached_icons[i].flip();
+ }
+ }
+
+ if ( Display.isCreated() && parent == null ) {
+ return display_impl.setIcon(cached_icons);
+ } else {
+ return 0;
+ }
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/DisplayImplementation.java b/src/java/org/lwjgl/opengl/DisplayImplementation.java
new file mode 100644
index 0000000..2c1c6f0
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/DisplayImplementation.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is the Display implementation interface. Display delegates
+ * to implementors of this interface. There is one DisplayImplementation
+ * for each supported platform.
+ * @author elias_naur
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.awt.Canvas;
+
+import org.lwjgl.LWJGLException;
+
+interface DisplayImplementation extends InputImplementation {
+
+ void createWindow(DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException;
+
+ void destroyWindow();
+
+ void switchDisplayMode(DisplayMode mode) throws LWJGLException;
+
+ /**
+ * Reset the display mode to whatever it was when LWJGL was initialized.
+ * Fails silently.
+ */
+ void resetDisplayMode();
+
+ /**
+ * Return the length of the gamma ramp arrays. Returns 0 if gamma settings are
+ * unsupported.
+ *
+ * @return the length of each gamma ramp array, or 0 if gamma settings are unsupported.
+ */
+ int getGammaRampLength();
+
+ /**
+ * Method to set the gamma ramp.
+ */
+ void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException;
+
+ /**
+ * Get the driver adapter string. This is a unique string describing the actual card's hardware, eg. "Geforce2", "PS2",
+ * "Radeon9700". If the adapter cannot be determined, this function returns null.
+ * @return a String
+ */
+ String getAdapter();
+
+ /**
+ * Get the driver version. This is a vendor/adapter specific version string. If the version cannot be determined,
+ * this function returns null.
+ * @return a String
+ */
+ String getVersion();
+
+ /**
+ * Initialize and return the current display mode.
+ */
+ DisplayMode init() throws LWJGLException;
+
+ /**
+ * Implementation of setTitle(). This will read the window's title member
+ * and stash it in the native title of the window.
+ */
+ void setTitle(String title);
+
+ boolean isCloseRequested();
+
+ boolean isVisible();
+ boolean isActive();
+
+ boolean isDirty();
+
+ /**
+ * Create the native PeerInfo.
+ * @throws LWJGLException
+ */
+ PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException;
+
+// void destroyPeerInfo();
+
+ /**
+ * Updates the windows internal state. This must be called at least once per video frame
+ * to handle window close requests, moves, paints, etc.
+ */
+ void update();
+
+ void reshape(int x, int y, int width, int height);
+
+ /**
+ * Method for getting displaymodes
+ */
+ DisplayMode[] getAvailableDisplayModes() throws LWJGLException;
+
+ /* Pbuffer */
+ int getPbufferCapabilities();
+
+ /**
+ * Method to test for buffer integrity
+ */
+ boolean isBufferLost(PeerInfo handle);
+
+ /**
+ * Method to create a Pbuffer
+ */
+ PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format,
+ IntBuffer pixelFormatCaps,
+ IntBuffer pBufferAttribs) throws LWJGLException;
+
+ void setPbufferAttrib(PeerInfo handle, int attrib, int value);
+
+ void bindTexImageToPbuffer(PeerInfo handle, int buffer);
+
+ void releaseTexImageFromPbuffer(PeerInfo handle, int buffer);
+
+ /**
+ * Sets one or more icons for the Display.
+ *
+ * - On Windows you should supply at least one 16x16 icon and one 32x32.
+ * - Linux (and similar platforms) expect one 32x32 icon.
+ * - Mac OS X should be supplied one 128x128 icon
+ *
+ * The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions nescesarry for the specific platform.
+ *
+ * @param icons Array of icons in RGBA mode
+ * @return number of icons used.
+ */
+ int setIcon(ByteBuffer[] icons);
+}
diff --git a/src/java/org/lwjgl/opengl/DisplayMode.java b/src/java/org/lwjgl/opengl/DisplayMode.java
new file mode 100644
index 0000000..ca59acc
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/DisplayMode.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ *
+ * This class encapsulates the properties for a given display mode.
+ * This class is not instantiable, and is aquired from the Display.
+ * getAvailableDisplayModes()
method.
+ *
+ * @author cix_foo
+ * @version $Revision: 3171 $
+ * $Id: DisplayMode.java 3171 2008-12-28 17:50:08Z elias_naur $
+ */
+
+public final class DisplayMode {
+
+ /** properties of the display mode */
+ private final int width, height, bpp, freq;
+ /** If true, this instance can be used for fullscreen modes */
+ private final boolean fullscreen;
+
+ /**
+ * Construct a display mode. DisplayModes constructed through the
+ * public constructor can only be used to specify the dimensions of
+ * the Display in windowed mode. To get the available DisplayModes for
+ * fullscreen modes, use Display.getAvailableDisplayModes().
+ *
+ * @param width The Display width.
+ * @param height The Display height.
+ * @see Display
+ */
+ public DisplayMode(int width, int height) {
+ this(width, height, 0, 0, false);
+ }
+
+ DisplayMode(int width, int height, int bpp, int freq) {
+ this(width, height, bpp, freq, true);
+ }
+
+ private DisplayMode(int width, int height, int bpp, int freq, boolean fullscreen) {
+ this.width = width;
+ this.height = height;
+ this.bpp = bpp;
+ this.freq = freq;
+ this.fullscreen = fullscreen;
+ }
+
+ /** True iff this instance can be used for fullscreen modes */
+ public boolean isFullscreenCapable() {
+ return fullscreen;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public int getBitsPerPixel() {
+ return bpp;
+ }
+
+ public int getFrequency() {
+ return freq;
+ }
+
+ /**
+ * Tests for DisplayMode
equality
+ *
+ * @see java.lang.Object#equals(Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof DisplayMode)) {
+ return false;
+ }
+
+ DisplayMode dm = (DisplayMode) obj;
+ return dm.width == width
+ && dm.height == height
+ && dm.bpp == bpp
+ && dm.freq == freq;
+ }
+
+ /**
+ * Retrieves the hashcode for this object
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return width ^ height ^ freq ^ bpp;
+ }
+
+ /**
+ * Retrieves a String representation of this DisplayMode
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer(32);
+ sb.append(width);
+ sb.append(" x ");
+ sb.append(height);
+ sb.append(" x ");
+ sb.append(bpp);
+ sb.append(" @");
+ sb.append(freq);
+ sb.append("Hz");
+ return sb.toString();
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/Drawable.java b/src/java/org/lwjgl/opengl/Drawable.java
new file mode 100644
index 0000000..a4681bb
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/Drawable.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2008 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/EventQueue.java b/src/java/org/lwjgl/opengl/EventQueue.java
new file mode 100644
index 0000000..60ec1f2
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/EventQueue.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * A java implementation of a LWJGL compatible event queue.
+ * @author elias_naur
+ */
+
+import java.nio.ByteBuffer;
+
+class EventQueue {
+ private static final int QUEUE_SIZE = 200;
+
+ private final int event_size;
+
+ private final ByteBuffer queue;
+
+ protected EventQueue(int event_size) {
+ this.event_size = event_size;
+ this.queue = ByteBuffer.allocate(QUEUE_SIZE*event_size);
+ }
+
+ protected synchronized void clearEvents() {
+ queue.clear();
+ }
+
+ /**
+ * Copy available events into the specified buffer.
+ */
+ public synchronized void copyEvents(ByteBuffer dest) {
+ queue.flip();
+ int old_limit = queue.limit();
+ if (dest.remaining() < queue.remaining())
+ queue.limit(dest.remaining() + queue.position());
+ dest.put(queue);
+ queue.limit(old_limit);
+ queue.compact();
+ }
+
+ /**
+ * Put an event into the queue.
+ * @return true if the event fitted into the queue, false otherwise
+ */
+ public synchronized boolean putEvent(ByteBuffer event) {
+ if (event.remaining() != event_size)
+ throw new IllegalArgumentException("Internal error: event size " + event_size + " does not equal the given event size " + event.remaining());
+ if (queue.remaining() >= event.remaining()) {
+ queue.put(event);
+ return true;
+ } else
+ return false;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/GLChecks.java b/src/java/org/lwjgl/opengl/GLChecks.java
new file mode 100644
index 0000000..df51ee5
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/GLChecks.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2002-2008 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.Buffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+
+/**
+ * A class to check buffer boundaries in GL methods. Many GL
+ * methods read data from the GL into a native Buffer at its current position. If there is unsufficient space in the buffer when
+ * the call is made then a buffer overflow would otherwise occur and cause unexpected behaviour, a crash, or worse, a security
+ * risk. Therefore in those methods where GL reads data back into a buffer, we will call a bounds check method from this class
+ * to ensure that there is sufficient space in the buffer.
+ *
+ * Thrown by the debug build library of the LWJGL if any OpenGL operation causes an error.
+ *
+ * @author cix_foo
+ * @version $Revision: 3279 $
+ * $Id: GLChecks.java 3279 2010-03-11 21:06:49Z spasi $
+ */
+class GLChecks {
+
+ /** Static methods only! */
+ private GLChecks() {
+ }
+
+ static References getReferences(ContextCapabilities caps) {
+ return StateTracker.getReferencesStack(caps).getReferences();
+ }
+
+ static int getBufferObjectSize(ContextCapabilities caps, int buffer_enum) {
+ IntBuffer scratch_buffer = caps.scratch_int_buffer;
+ GL15.glGetBufferParameter(buffer_enum, GL15.GL_BUFFER_SIZE, scratch_buffer);
+ return scratch_buffer.get(0);
+ }
+
+ static int getBufferObjectSizeARB(ContextCapabilities caps, int buffer_enum) {
+ IntBuffer scratch_buffer = caps.scratch_int_buffer;
+ ARBBufferObject.glGetBufferParameterARB(buffer_enum, ARBBufferObject.GL_BUFFER_SIZE_ARB, scratch_buffer);
+ return scratch_buffer.get(0);
+ }
+
+ static int getBufferObjectSizeATI(ContextCapabilities caps, int buffer) {
+ IntBuffer scratch_buffer = caps.scratch_int_buffer;
+ ATIVertexArrayObject.glGetObjectBufferATI(buffer, ATIVertexArrayObject.GL_OBJECT_BUFFER_SIZE_ATI, scratch_buffer);
+ return scratch_buffer.get(0);
+ }
+
+ static int getNamedBufferObjectSize(ContextCapabilities caps, int buffer) {
+ IntBuffer scratch_buffer = caps.scratch_int_buffer;
+ EXTDirectStateAccess.glGetNamedBufferParameterEXT(buffer, GL15.GL_BUFFER_SIZE, scratch_buffer);
+ return scratch_buffer.get(0);
+ }
+
+ private static boolean checkBufferObject(ContextCapabilities caps, int buffer_enum, boolean state) {
+ IntBuffer scratch_buffer = caps.scratch_int_buffer;
+ GL11.glGetInteger(buffer_enum, scratch_buffer);
+ boolean is_enabled = scratch_buffer.get(0) != 0;
+ return state == is_enabled;
+ }
+
+ /** Helper method to ensure that array buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensureArrayVBOdisabled(ContextCapabilities caps) {
+ if(StateTracker.getReferencesStack(caps).getReferences().arrayBuffer != 0)
+ throw new OpenGLException("Cannot use Buffers when Array Buffer Object is enabled");
+ }
+
+ /** Helper method to ensure that array buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensureArrayVBOenabled(ContextCapabilities caps) {
+ if(StateTracker.getReferencesStack(caps).getReferences().arrayBuffer == 0)
+ throw new OpenGLException("Cannot use offsets when Array Buffer Object is disabled");
+ }
+
+ /** Helper method to ensure that element array buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensureElementVBOdisabled(ContextCapabilities caps) {
+ if(StateTracker.getReferencesStack(caps).getReferences().elementArrayBuffer != 0)
+ throw new OpenGLException("Cannot use Buffers when Element Array Buffer Object is enabled");
+ }
+
+ /** Helper method to ensure that element array buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensureElementVBOenabled(ContextCapabilities caps) {
+ if(StateTracker.getReferencesStack(caps).getReferences().elementArrayBuffer == 0)
+ throw new OpenGLException("Cannot use offsets when Element Array Buffer Object is disabled");
+ }
+
+ /** Helper method to ensure that array buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensureIndirectBOdisabled(ContextCapabilities caps) {
+ if ( StateTracker.getReferencesStack(caps).getReferences().indirectBuffer != 0 )
+ throw new OpenGLException("Cannot use Buffers when Draw Indirect Object is enabled");
+ }
+
+ /** Helper method to ensure that array buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensureIndirectBOenabled(ContextCapabilities caps) {
+ if ( StateTracker.getReferencesStack(caps).getReferences().indirectBuffer == 0 )
+ throw new OpenGLException("Cannot use offsets when Draw Indirect Object is disabled");
+ }
+
+ /** Helper method to ensure that pixel pack buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensurePackPBOdisabled(ContextCapabilities caps) {
+ if ( StateTracker.getReferencesStack(caps).getReferences().pixelPackBuffer != 0 )
+ throw new OpenGLException("Cannot use Buffers when Pixel Pack Buffer Object is enabled");
+ }
+
+ /** Helper method to ensure that pixel pack buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensurePackPBOenabled(ContextCapabilities caps) {
+ if ( StateTracker.getReferencesStack(caps).getReferences().pixelPackBuffer == 0 )
+ throw new OpenGLException("Cannot use offsets when Pixel Pack Buffer Object is disabled");
+ }
+
+ /** Helper method to ensure that pixel unpack buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensureUnpackPBOdisabled(ContextCapabilities caps) {
+ if ( StateTracker.getReferencesStack(caps).getReferences().pixelUnpackBuffer != 0 )
+ throw new OpenGLException("Cannot use Buffers when Pixel Unpack Buffer Object is enabled");
+ }
+
+ /** Helper method to ensure that pixel unpack buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensureUnpackPBOenabled(ContextCapabilities caps) {
+ if ( StateTracker.getReferencesStack(caps).getReferences().pixelUnpackBuffer == 0 )
+ throw new OpenGLException("Cannot use offsets when Pixel Unpack Buffer Object is disabled");
+ }
+
+ /**
+ * Calculate the storage required for an image in elements
+ *
+ * @param format The format of the image (example: GL_RGBA)
+ * @param type The type of the image elements (example: GL_UNSIGNED_BYTE)
+ * @param width The width of the image
+ * @param height The height of the image (1 for 1D images)
+ * @param depth The depth of the image (1 for 2D images)
+ *
+ * @return the size, in elements, of the image
+ */
+ static int calculateImageStorage(Buffer buffer, int format, int type, int width, int height, int depth) {
+ return calculateImageStorage(format, type, width, height, depth) >> BufferUtils.getElementSizeExponent(buffer);
+ }
+
+ static int calculateTexImage1DStorage(Buffer buffer, int format, int type, int width) {
+ return calculateTexImage1DStorage(format, type, width) >> BufferUtils.getElementSizeExponent(buffer);
+ }
+
+ static int calculateTexImage2DStorage(Buffer buffer, int format, int type, int width, int height) {
+ return calculateTexImage2DStorage(format, type, width, height) >> BufferUtils.getElementSizeExponent(buffer);
+ }
+
+ static int calculateTexImage3DStorage(Buffer buffer, int format, int type, int width, int height, int depth) {
+ return calculateTexImage3DStorage(format, type, width, height, depth) >> BufferUtils.getElementSizeExponent(buffer);
+ }
+
+ /**
+ * Calculate the storage required for an image in bytes.
+ *
+ * @param format The format of the image (example: GL_RGBA)
+ * @param type The type of the image elements (example: GL_UNSIGNED_BYTE)
+ * @param width The width of the image
+ * @param height The height of the image (1 for 1D images)
+ * @param depth The depth of the image (1 for 2D images)
+ *
+ * @return the size, in bytes, of the image
+ */
+ private static int calculateImageStorage(int format, int type, int width, int height, int depth) {
+ return calculateBytesPerPixel(format, type) * width * height * depth;
+ }
+
+ private static int calculateTexImage1DStorage(int format, int type, int width) {
+ return calculateBytesPerPixel(format, type) * width;
+ }
+
+ private static int calculateTexImage2DStorage(int format, int type, int width, int height) {
+ return calculateTexImage1DStorage(format, type, width) * height;
+ }
+
+ private static int calculateTexImage3DStorage(int format, int type, int width, int height, int depth) {
+ return calculateTexImage2DStorage(format, type, width, height) * depth;
+ }
+
+ private static int calculateBytesPerPixel(int format, int type) {
+ int bpe;
+ switch ( type ) {
+ case GL11.GL_UNSIGNED_BYTE:
+ case GL11.GL_BYTE:
+ bpe = 1;
+ break;
+ case GL11.GL_UNSIGNED_SHORT:
+ case GL11.GL_SHORT:
+ bpe = 2;
+ break;
+ case GL11.GL_UNSIGNED_INT:
+ case GL11.GL_INT:
+ case GL11.GL_FLOAT:
+ bpe = 4;
+ break;
+ default :
+ // TODO: Add more types (like the GL12 types GL_UNSIGNED_INT_8_8_8_8
+ return 0;
+ // throw new IllegalArgumentException("Unknown type " + type);
+ }
+ int epp;
+ switch ( format ) {
+ case GL11.GL_LUMINANCE:
+ case GL11.GL_ALPHA:
+ epp = 1;
+ break;
+
+ case GL11.GL_LUMINANCE_ALPHA:
+ epp = 2;
+ break;
+ case GL11.GL_RGB:
+ case EXTBgra.GL_BGR_EXT:
+ epp = 3;
+ break;
+ case GL11.GL_RGBA:
+ case EXTAbgr.GL_ABGR_EXT:
+ case EXTBgra.GL_BGRA_EXT:
+ epp = 4;
+ break;
+ default :
+ // TODO: Add more formats. Assuming 4 is too wasteful on buffer sizes where e.g. 1 is enough (like GL_DEPTH_COMPONENT)
+ return 0;
+/* // Assume 4 elements per pixel
+ epp = 4;*/
+ }
+
+ return bpe * epp;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/GLContext.java b/src/java/org/lwjgl/opengl/GLContext.java
new file mode 100644
index 0000000..35158f5
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/GLContext.java
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+
+import java.lang.reflect.Method;
+import java.nio.IntBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.util.*;
+
+/**
+ *
+ * Manages GL contexts. Before any rendering is done by a LWJGL system, a call should be made to GLContext.useContext() with a
+ * context. This will ensure that GLContext has an accurate reflection of the current context's capabilities and function
+ * pointers.
+ *
+ * This class is thread-safe in the sense that multiple threads can safely call all public methods. The class is also
+ * thread-aware in the sense that it tracks a per-thread current context (including capabilities and function pointers).
+ * That way, multiple threads can have multiple contexts current and render to them concurrently.
+ *
+ * @author elias_naur
+ * @version $Revision: 3279 $
+ * $Id: GLContext.java 3279 2010-03-11 21:06:49Z spasi $
+ */
+public final class GLContext {
+
+ /** Maps threads to their current context's ContextCapabilities, if any */
+ private final static ThreadLocal current_capabilities = new ThreadLocal();
+
+ /**
+ * The getCapabilities() method is a potential hot spot in any LWJGL application, since
+ * it is needed for context capability discovery (e.g. is OpenGL 2.0 supported?), and
+ * for the function pointers of gl functions. However, the 'current_capabilities' ThreadLocal
+ * is (relatively) expensive to look up, and since most OpenGL applications use are single threaded
+ * rendering, the following two is an optimization for this case.
+ *
+ * ThreadLocals can be thought of as a mapping between threads and values, so the idea
+ * is to use a lock-less cache of mappings between threads and the current ContextCapabilities. The cache
+ * could be any size, but in our case, we want a single sized cache for optimal performance
+ * in the single threaded case.
+ *
+ * 'fast_path_cache' is the most recent ContextCapabilities (potentially null) and its owner. By
+ * recent I mean the last thread setting the value in setCapabilities(). When getCapabilities()
+ * is called, a check to see if the current is the owner of the ContextCapabilities instance in
+ * fast_path_cache. If so, the instance is returned, if not, some thread has since taken ownership
+ * of the cache entry and the slower current_capabilities ThreadLocal is queried instead.
+ *
+ * No locks are needed in get/setCapabilities, because even though fast_path_cache can be accessed
+ * from multiple threads at once, we are guaranteed by the JVM spec that its value is always valid.
+ * Furthermore, if the ownership test in getCapabilities() succeeds, the cache entry can only contain
+ * the correct ContextCapabilites (that is, the one from getThreadLocalCapabilites()),
+ * since no other thread can set the owner to anyone else than itself.
+ */
+ private static CapabilitiesCacheEntry fast_path_cache = new CapabilitiesCacheEntry();
+
+ /**
+ * Simple lock-free cache of CapabilitesEntryCache to avoid allocating more than one
+ * cache entry per thread
+ */
+ private final static ThreadLocal thread_cache_entries = new ThreadLocal();
+
+ /**
+ * The weak mapping from context Object instances to ContextCapabilities. Used
+ * to avoid recreating a ContextCapabilities every time a context is made current.
+ */
+ private final static Map capability_cache = new WeakHashMap();
+
+ /** Reference count of the native opengl implementation library */
+ private static int gl_ref_count;
+ private static boolean did_auto_load;
+
+ static {
+ Sys.initialize();
+ }
+
+ /**
+ * Get the current capabilities instance. It contains the flags used
+ * to test for support of a particular extension.
+ *
+ * @return The current capabilities instance.
+ */
+ public static ContextCapabilities getCapabilities() {
+ CapabilitiesCacheEntry recent_cache_entry = fast_path_cache;
+ // Check owner of cache entry
+ if ( recent_cache_entry.owner == Thread.currentThread() ) {
+ /* The owner ship test succeeded, so the cache must contain the current ContextCapabilities instance
+ * assert recent_cache_entry.capabilities == getThreadLocalCapabilities();
+ */
+ return recent_cache_entry.capabilities;
+ } else // Some other thread has written to the cache since, and we fall back to the slower path
+ return getThreadLocalCapabilities();
+ }
+
+ private static ContextCapabilities getThreadLocalCapabilities() {
+ return ((ContextCapabilities)current_capabilities.get());
+ }
+
+ /**
+ * Set the current capabilities instance. It contains the flags used
+ * to test for support of a particular extension.
+ *
+ * @return The current capabilities instance.
+ */
+ static void setCapabilities(ContextCapabilities capabilities) {
+ current_capabilities.set(capabilities);
+
+ CapabilitiesCacheEntry thread_cache_entry = (CapabilitiesCacheEntry)thread_cache_entries.get();
+ if ( thread_cache_entry == null ) {
+ thread_cache_entry = new CapabilitiesCacheEntry();
+ thread_cache_entries.set(thread_cache_entry);
+ }
+ thread_cache_entry.owner = Thread.currentThread();
+ thread_cache_entry.capabilities = capabilities;
+
+ fast_path_cache = thread_cache_entry;
+ }
+
+ /**
+ * Helper method to get a pointer to a named function in the OpenGL library
+ * with a name dependent on the current platform
+ */
+ static long getPlatformSpecificFunctionAddress(String function_prefix, String[] os_prefixes, String[] os_function_prefixes, String function) {
+ String os_name = (String)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty("os.name");
+ }
+ });
+ for ( int i = 0; i < os_prefixes.length; i++ )
+ if ( os_name.startsWith(os_prefixes[i]) ) {
+ String platform_function_name = function.replaceFirst(function_prefix, os_function_prefixes[i]);
+ long address = getFunctionAddress(platform_function_name);
+ return address;
+ }
+ return 0;
+ }
+
+ /** Helper method to get a pointer to a named function in the OpenGL library */
+ static native long getFunctionAddress(String name);
+
+ /**
+ * Determine which extensions are available and returns the context profile mask. Helper method to ContextCapabilities.
+ *
+ * @param supported_extensions the Set to fill with the available extension names
+ *
+ * @return the context profile mask, will be 0 for any version < 3.2
+ */
+ static int getSupportedExtensions(final Set supported_extensions) {
+ // Detect OpenGL version first
+
+ final String version = GL11.glGetString(GL11.GL_VERSION);
+ if ( version == null )
+ throw new IllegalStateException("glGetString(GL_VERSION) returned null - possibly caused by missing current context.");
+
+ final StringTokenizer version_tokenizer = new StringTokenizer(version, ". ");
+ final String major_string = version_tokenizer.nextToken();
+ final String minor_string = version_tokenizer.nextToken();
+
+ int majorVersion = 0;
+ int minorVersion = 0;
+ try {
+ majorVersion = Integer.parseInt(major_string);
+ minorVersion = Integer.parseInt(minor_string);
+ } catch (NumberFormatException e) {
+ LWJGLUtil.log("The major and/or minor OpenGL version is malformed: " + e.getMessage());
+ }
+
+ // ----------------------[ 4.X ]----------------------
+ if ( 4 <= majorVersion )
+ supported_extensions.add("OpenGL40");
+
+ // ----------------------[ 3.X ]----------------------
+ if ( 3 < majorVersion || (3 == majorVersion && 3 <= minorVersion) )
+ supported_extensions.add("OpenGL33");
+ if ( 3 < majorVersion || (3 == majorVersion && 2 <= minorVersion) )
+ supported_extensions.add("OpenGL32");
+ if ( 3 < majorVersion || (3 == majorVersion && 1 <= minorVersion) )
+ supported_extensions.add("OpenGL31");
+ if ( 3 <= majorVersion )
+ supported_extensions.add("OpenGL30");
+
+ // ----------------------[ 2.X ]----------------------
+ if ( 2 < majorVersion || (2 == majorVersion && 1 <= minorVersion) )
+ supported_extensions.add("OpenGL21");
+ if ( 2 <= majorVersion )
+ supported_extensions.add("OpenGL20");
+
+ // ----------------------[ 1.X ]----------------------
+ if ( 1 < majorVersion || 5 <= minorVersion )
+ supported_extensions.add("OpenGL15");
+ if ( 1 < majorVersion || 4 <= minorVersion )
+ supported_extensions.add("OpenGL14");
+ if ( 1 < majorVersion || 3 <= minorVersion )
+ supported_extensions.add("OpenGL13");
+ if ( 1 < majorVersion || 2 <= minorVersion )
+ supported_extensions.add("OpenGL12");
+ if ( 1 < majorVersion || 1 <= minorVersion )
+ supported_extensions.add("OpenGL11");
+
+ int profileMask = 0;
+
+ if ( majorVersion < 3 ) {
+ // Parse EXTENSIONS string
+ final String extensions_string = GL11.glGetString(GL11.GL_EXTENSIONS);
+ if ( extensions_string == null )
+ throw new IllegalStateException("glGetString(GL_EXTENSIONS) returned null - is there a context current?");
+
+ final StringTokenizer tokenizer = new StringTokenizer(extensions_string);
+ while ( tokenizer.hasMoreTokens() )
+ supported_extensions.add(tokenizer.nextToken());
+ } else {
+ // Use forward compatible indexed EXTENSIONS
+ final IntBuffer buffer = BufferUtils.createIntBuffer(16);
+ GL11.glGetInteger(GL30.GL_NUM_EXTENSIONS, buffer);
+ final int extensionCount = buffer.get(0);
+
+ for ( int i = 0; i < extensionCount; i++ )
+ supported_extensions.add(GL30.glGetStringi(GL11.GL_EXTENSIONS, i));
+
+ // Get the context profile mask for versions >= 3.2
+ if ( 3 < majorVersion || 2 <= minorVersion ) {
+ Util.checkGLError(); // Make sure we have no errors up to this point
+
+ GL11.glGetInteger(GL32.GL_CONTEXT_PROFILE_MASK, buffer);
+
+ try {
+ // Retrieving GL_CONTEXT_PROFILE_MASK may generate an INVALID_OPERATION error on certain implementations, ignore.
+ // Happens on pre10.1 ATI drivers, when ContextAttribs.withProfileCompatibility is not used
+ Util.checkGLError();
+ profileMask = buffer.get(0);
+ } catch (OpenGLException e) {
+ LWJGLUtil.log("Failed to retrieve CONTEXT_PROFILE_MASK");
+ }
+ }
+ }
+
+ return profileMask;
+ }
+
+ /**
+ * Helper method to ContextCapabilities. It will try to initialize the native stubs,
+ * and remove the given extension name from the extension set if the initialization fails.
+ */
+ static void initNativeStubs(final Class extension_class, Set supported_extensions, String ext_name) {
+ resetNativeStubs(extension_class);
+ if ( supported_extensions.contains(ext_name) ) {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ Method init_stubs_method = extension_class.getDeclaredMethod("initNativeStubs", null);
+ init_stubs_method.invoke(null, null);
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ LWJGLUtil.log("Failed to initialize extension " + extension_class + " - exception: " + e);
+ supported_extensions.remove(ext_name);
+ }
+ }
+ }
+
+ /**
+ * Makes a GL context the current LWJGL context by loading GL function pointers. The context must be current before a call to
+ * this method! Instead it simply ensures that the current context is reflected accurately by GLContext's extension caps and
+ * function pointers. Use useContext(null) when no context is active. If the context is the same as last time, then this is
+ * a no-op.
If the context has not been encountered before it will be fully initialized from scratch. Otherwise a cached set
+ * of caps and function pointers will be used.
The reference to the context is held in a weak reference; therefore if no
+ * strong reference exists to the GL context it will automatically be forgotten by the VM at an indeterminate point in the
+ * future, freeing up a little RAM.
+ *
+ * @param context The context object, which uniquely identifies a GL context. If context is null, the native stubs are
+ * unloaded.
+ *
+ * @throws LWJGLException if context non-null, and the gl library can't be loaded or the basic GL11 functions can't be loaded
+ */
+ public static synchronized void useContext(Object context) throws LWJGLException {
+ useContext(context, false);
+ }
+
+ /**
+ * Makes a GL context the current LWJGL context by loading GL function pointers. The context must be current before a call to
+ * this method! Instead it simply ensures that the current context is reflected accurately by GLContext's extension caps and
+ * function pointers. Use useContext(null) when no context is active.
If the context is the same as last time, then this is
+ * a no-op.
If the context has not been encountered before it will be fully initialized from scratch. Otherwise a cached set
+ * of caps and function pointers will be used.
The reference to the context is held in a weak reference; therefore if no
+ * strong reference exists to the GL context it will automatically be forgotten by the VM at an indeterminate point in the
+ * future, freeing up a little RAM.
+ *
If forwardCompatible is true, function pointers of deprecated GL11-GL21 functionality will not be loaded. Calling a deprecated
+ * function using the specified context will result in an IllegalStateException
.
+ *
+ * @param context The context object, which uniquely identifies a GL context. If context is null, the native stubs are
+ * unloaded.
+ * @param forwardCompatible If the context is a forward compatible context (does not expose deprecated functionality, see XGL_ARB_create_context)
+ *
+ * @throws LWJGLException if context non-null, and the gl library can't be loaded or the basic GL11 functions can't be loaded
+ */
+ public static synchronized void useContext(Object context, boolean forwardCompatible) throws LWJGLException {
+ if ( context == null ) {
+ ContextCapabilities.unloadAllStubs();
+ setCapabilities(null);
+ if ( did_auto_load )
+ unloadOpenGLLibrary();
+ return;
+ }
+ if ( gl_ref_count == 0 ) {
+ loadOpenGLLibrary();
+ did_auto_load = true;
+ }
+ try {
+ ContextCapabilities capabilities = (ContextCapabilities)capability_cache.get(context);
+ if ( capabilities == null ) {
+ /*
+ * The capabilities object registers itself as current. This behaviour is caused
+ * by a chicken-and-egg situation where the constructor needs to call GL functions
+ * as part of its capability discovery, but GL functions cannot be called before
+ * a capabilities object has been set.
+ */
+ new ContextCapabilities(forwardCompatible);
+ capability_cache.put(context, getCapabilities());
+ } else
+ setCapabilities(capabilities);
+ } catch (LWJGLException e) {
+ if ( did_auto_load )
+ unloadOpenGLLibrary();
+ throw e;
+ }
+ }
+
+ /** If the OpenGL reference count is 0, the library is loaded. The reference count is then incremented. */
+ public static synchronized void loadOpenGLLibrary() throws LWJGLException {
+ if ( gl_ref_count == 0 )
+ nLoadOpenGLLibrary();
+ gl_ref_count++;
+ }
+
+ private static native void nLoadOpenGLLibrary() throws LWJGLException;
+
+ /** The OpenGL library reference count is decremented, and if it reaches 0, the library is unloaded. */
+ public static synchronized void unloadOpenGLLibrary() {
+ gl_ref_count--;
+ /*
+ * Unload the native OpenGL library unless we're on linux, since
+ * some drivers (NVIDIA proprietary) crash on exit when unloading the library.
+ */
+ if ( gl_ref_count == 0 && LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_LINUX )
+ nUnloadOpenGLLibrary();
+ }
+
+ private static native void nUnloadOpenGLLibrary();
+
+ /** Native method to clear native stub bindings */
+ static native void resetNativeStubs(Class clazz);
+
+ private final static class CapabilitiesCacheEntry {
+
+ Thread owner;
+ ContextCapabilities capabilities;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/GLSync.java b/src/java/org/lwjgl/opengl/GLSync.java
new file mode 100644
index 0000000..721990e
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/GLSync.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * @author spasi
+ */
+public final class GLSync implements PointerWrapper {
+
+ private final long sync;
+
+ GLSync(final long sync) {
+ this.sync = sync;
+ }
+
+ public long getPointer() {
+ return sync;
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/GLUConstants.java b/src/java/org/lwjgl/opengl/GLUConstants.java
new file mode 100644
index 0000000..c2a8bcf
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/GLUConstants.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ *
+ * GLU constants.
+ *
+ * @author cix_foo
+ * @version $Revision: 2983 $
+ * $Id: GLUConstants.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface GLUConstants {
+
+ /* Errors: (return value 0 = no error) */
+ int GLU_INVALID_ENUM = 100900;
+ int GLU_INVALID_VALUE = 100901;
+ int GLU_OUT_OF_MEMORY = 100902;
+ int GLU_INCOMPATIBLE_GL_VERSION = 100903;
+
+ /* StringName */
+ int GLU_VERSION = 100800;
+ int GLU_EXTENSIONS = 100801;
+
+ /* Boolean */
+ int GLU_TRUE = GL11.GL_TRUE;
+ int GLU_FALSE = GL11.GL_FALSE;
+
+}
diff --git a/src/java/org/lwjgl/opengl/GlobalLock.java b/src/java/org/lwjgl/opengl/GlobalLock.java
new file mode 100644
index 0000000..a834f01
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/GlobalLock.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This class contains the global lock that LWJGL will use to
+ * synchronize access to Display.
+ */
+final class GlobalLock {
+ final static Object lock = new Object();
+}
diff --git a/src/java/org/lwjgl/opengl/InputImplementation.java b/src/java/org/lwjgl/opengl/InputImplementation.java
new file mode 100644
index 0000000..3f7de2c
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/InputImplementation.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is the input implementation interface. Mouse and Keyboard delegates
+ * to implementors of this interface. There is one InputImplementation
+ * for each supported platform.
+ * @author elias_naur
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.LWJGLException;
+
+public interface InputImplementation {
+ /*
+ * Mouse methods
+ */
+ /** Query of wheel support */
+ boolean hasWheel();
+
+ /** Query of button count */
+ int getButtonCount();
+
+ /**
+ * Method to create the mouse.
+ */
+ void createMouse() throws LWJGLException;
+
+ /**
+ * Method the destroy the mouse
+ */
+ void destroyMouse();
+
+ /**
+ * Method to poll the mouse
+ */
+ void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons);
+
+ /**
+ * Method to read the keyboard buffer
+ */
+ void readMouse(ByteBuffer buffer);
+
+ void grabMouse(boolean grab);
+
+ /**
+ * Function to determine native cursor support
+ */
+ int getNativeCursorCapabilities();
+
+ /** Method to set the native cursor position */
+ void setCursorPosition(int x, int y);
+
+ /** Method to set the native cursor */
+ void setNativeCursor(Object handle) throws LWJGLException;
+
+ /** Method returning the minimum cursor size */
+ int getMinCursorSize();
+
+ /** Method returning the maximum cursor size */
+ int getMaxCursorSize();
+
+ /*
+ * Keyboard methods
+ */
+
+ /**
+ * Method to create the keyboard
+ */
+ void createKeyboard() throws LWJGLException;
+
+ /**
+ * Method to destroy the keyboard
+ */
+ void destroyKeyboard();
+
+ /**
+ * Method to poll the keyboard.
+ *
+ * @param keyDownBuffer the address of a 256-byte buffer to place
+ * key states in.
+ */
+ void pollKeyboard(ByteBuffer keyDownBuffer);
+
+ /**
+ * Method to read the keyboard buffer
+ */
+ void readKeyboard(ByteBuffer buffer);
+
+// int isStateKeySet(int key);
+
+ /** Native cursor handles */
+ Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException;
+
+ void destroyCursor(Object cursor_handle);
+
+ int getWidth();
+
+ int getHeight();
+
+ boolean isInsideWindow();
+}
diff --git a/src/java/org/lwjgl/opengl/KeyboardEventQueue.java b/src/java/org/lwjgl/opengl/KeyboardEventQueue.java
new file mode 100644
index 0000000..12a2a5c
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/KeyboardEventQueue.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * An AWT implementation of a LWJGL compatible Keyboard event queue.
+ * @author elias_naur
+ */
+
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.Component;
+import java.nio.ByteBuffer;
+
+import org.lwjgl.input.Keyboard;
+
+final class KeyboardEventQueue extends EventQueue implements KeyListener {
+ private static final int[] KEY_MAP = new int[0xffff];
+
+ private final byte[] key_states = new byte[Keyboard.KEYBOARD_SIZE];
+
+ /** Event scratch array */
+ private final ByteBuffer event = ByteBuffer.allocate(Keyboard.EVENT_SIZE);
+
+ private final Component component;
+
+ private boolean has_deferred_event;
+ private long deferred_nanos;
+ private int deferred_key_code;
+ private int deferred_key_location;
+ private byte deferred_key_state;
+ private int deferred_character;
+
+ static {
+ KEY_MAP[KeyEvent.VK_0] = Keyboard.KEY_0;
+ KEY_MAP[KeyEvent.VK_1] = Keyboard.KEY_1;
+ KEY_MAP[KeyEvent.VK_2] = Keyboard.KEY_2;
+ KEY_MAP[KeyEvent.VK_3] = Keyboard.KEY_3;
+ KEY_MAP[KeyEvent.VK_4] = Keyboard.KEY_4;
+ KEY_MAP[KeyEvent.VK_5] = Keyboard.KEY_5;
+ KEY_MAP[KeyEvent.VK_6] = Keyboard.KEY_6;
+ KEY_MAP[KeyEvent.VK_7] = Keyboard.KEY_7;
+ KEY_MAP[KeyEvent.VK_8] = Keyboard.KEY_8;
+ KEY_MAP[KeyEvent.VK_9] = Keyboard.KEY_9;
+ KEY_MAP[KeyEvent.VK_A] = Keyboard.KEY_A;
+// KEY_MAP[KeyEvent.VK_ACCEPT] = Keyboard.KEY_ACCEPT;
+ KEY_MAP[KeyEvent.VK_ADD] = Keyboard.KEY_ADD;
+// KEY_MAP[KeyEvent.VK_AGAIN] = Keyboard.KEY_AGAIN;
+// KEY_MAP[KeyEvent.VK_ALL_CANDIDATES] = Keyboard.KEY_ALL_CANDIDATES;
+// KEY_MAP[KeyEvent.VK_ALPHANUMERIC] = Keyboard.KEY_ALPHANUMERIC;
+// KEY_MAP[KeyEvent.VK_ALT] = Keyboard.KEY_LMENU; manually mapped
+ KEY_MAP[KeyEvent.VK_ALT_GRAPH] = Keyboard.KEY_RMENU;
+// KEY_MAP[KeyEvent.VK_AMPERSAND] = Keyboard.KEY_AMPERSAND;
+// KEY_MAP[KeyEvent.VK_ASTERISK] = Keyboard.KEY_ASTERISK;
+ KEY_MAP[KeyEvent.VK_AT] = Keyboard.KEY_AT;
+ KEY_MAP[KeyEvent.VK_B] = Keyboard.KEY_B;
+// KEY_MAP[KeyEvent.VK_BACK_QUOTE] = Keyboard.KEY_BACK_QUOTE;
+ KEY_MAP[KeyEvent.VK_BACK_SLASH] = Keyboard.KEY_BACKSLASH;
+ KEY_MAP[KeyEvent.VK_BACK_SPACE] = Keyboard.KEY_BACK;
+// KEY_MAP[KeyEvent.VK_BRACELEFT] = Keyboard.KEY_BRACELEFT;
+// KEY_MAP[KeyEvent.VK_BRACERIGHT] = Keyboard.KEY_BRACERIGHT;
+ KEY_MAP[KeyEvent.VK_C] = Keyboard.KEY_C;
+// KEY_MAP[KeyEvent.VK_CANCEL] = Keyboard.KEY_CANCEL;
+ KEY_MAP[KeyEvent.VK_CAPS_LOCK] = Keyboard.KEY_CAPITAL;
+ KEY_MAP[KeyEvent.VK_CIRCUMFLEX] = Keyboard.KEY_CIRCUMFLEX;
+// KEY_MAP[KeyEvent.VK_CLEAR] = Keyboard.KEY_CLEAR;
+ KEY_MAP[KeyEvent.VK_CLOSE_BRACKET] = Keyboard.KEY_RBRACKET;
+// KEY_MAP[KeyEvent.VK_CODE_INPUT] = Keyboard.KEY_CODE_INPUT;
+ KEY_MAP[KeyEvent.VK_COLON] = Keyboard.KEY_COLON;
+ KEY_MAP[KeyEvent.VK_COMMA] = Keyboard.KEY_COMMA;
+// KEY_MAP[KeyEvent.VK_COMPOSE] = Keyboard.KEY_COMPOSE;
+// KEY_MAP[KeyEvent.VK_CONTROL] = Keyboard.KEY_LCONTROL; manually mapped
+ KEY_MAP[KeyEvent.VK_CONVERT] = Keyboard.KEY_CONVERT;
+// KEY_MAP[KeyEvent.VK_COPY] = Keyboard.KEY_COPY;
+// KEY_MAP[KeyEvent.VK_CUT] = Keyboard.KEY_CUT;
+ KEY_MAP[KeyEvent.VK_D] = Keyboard.KEY_D;
+// KEY_MAP[KeyEvent.VK_DEAD_ABOVEDOT] = Keyboard.KEY_DEAD_ABOVEDOT;
+// KEY_MAP[KeyEvent.VK_DEAD_ABOVERING] = Keyboard.KEY_DEAD_ABOVERING;
+// KEY_MAP[KeyEvent.VK_DEAD_ACUTE] = Keyboard.KEY_DEAD_ACUTE;
+// KEY_MAP[KeyEvent.VK_DEAD_BREVE] = Keyboard.KEY_DEAD_BREVE;
+// KEY_MAP[KeyEvent.VK_DEAD_CARON] = Keyboard.KEY_DEAD_CARON;
+// KEY_MAP[KeyEvent.VK_DEAD_CEDILLA] = Keyboard.KEY_DEAD_CEDILLA;
+// KEY_MAP[KeyEvent.VK_DEAD_CIRCUMFLEX] = Keyboard.KEY_DEAD_CIRCUMFLEX;
+// KEY_MAP[KeyEvent.VK_DEAD_DIAERESIS] = Keyboard.KEY_DEAD_DIAERESIS;
+// KEY_MAP[KeyEvent.VK_DEAD_DOUBLEACUTE] = Keyboard.KEY_DEAD_DOUBLEACUTE;
+// KEY_MAP[KeyEvent.VK_DEAD_GRAVE] = Keyboard.KEY_DEAD_GRAVE;
+// KEY_MAP[KeyEvent.VK_DEAD_IOTA] = Keyboard.KEY_DEAD_IOTA;
+// KEY_MAP[KeyEvent.VK_DEAD_MACRON] = Keyboard.KEY_DEAD_MACRON;
+// KEY_MAP[KeyEvent.VK_DEAD_OGONEK] = Keyboard.KEY_DEAD_OGONEK;
+// KEY_MAP[KeyEvent.VK_DEAD_SEMIVOICED_SOUND] = Keyboard.KEY_DEAD_SEMIVOICED_SOUND;
+// KEY_MAP[KeyEvent.VK_DEAD_TILDE] = Keyboard.KEY_DEAD_TILDE;
+// KEY_MAP[KeyEvent.VK_DEAD_VOICED_SOUND] = Keyboard.KEY_DEAD_VOICED_SOUND;
+ KEY_MAP[KeyEvent.VK_DECIMAL] = Keyboard.KEY_DECIMAL;
+ KEY_MAP[KeyEvent.VK_DELETE] = Keyboard.KEY_DELETE;
+ KEY_MAP[KeyEvent.VK_DIVIDE] = Keyboard.KEY_DIVIDE;
+// KEY_MAP[KeyEvent.VK_DOLLAR] = Keyboard.KEY_DOLLAR;
+ KEY_MAP[KeyEvent.VK_DOWN] = Keyboard.KEY_DOWN;
+ KEY_MAP[KeyEvent.VK_E] = Keyboard.KEY_E;
+ KEY_MAP[KeyEvent.VK_END] = Keyboard.KEY_END;
+ KEY_MAP[KeyEvent.VK_ENTER] = Keyboard.KEY_RETURN;
+ KEY_MAP[KeyEvent.VK_EQUALS] = Keyboard.KEY_EQUALS;
+ KEY_MAP[KeyEvent.VK_ESCAPE] = Keyboard.KEY_ESCAPE;
+// KEY_MAP[KeyEvent.VK_EURO_SIGN] = Keyboard.KEY_EURO_SIGN;
+// KEY_MAP[KeyEvent.VK_EXCLAMATION_MARK] = Keyboard.KEY_EXCLAMATION_MARK;
+ KEY_MAP[KeyEvent.VK_F] = Keyboard.KEY_F;
+ KEY_MAP[KeyEvent.VK_F1] = Keyboard.KEY_F1;
+ KEY_MAP[KeyEvent.VK_F10] = Keyboard.KEY_F10;
+ KEY_MAP[KeyEvent.VK_F11] = Keyboard.KEY_F11;
+ KEY_MAP[KeyEvent.VK_F12] = Keyboard.KEY_F12;
+ KEY_MAP[KeyEvent.VK_F13] = Keyboard.KEY_F13;
+ KEY_MAP[KeyEvent.VK_F14] = Keyboard.KEY_F14;
+ KEY_MAP[KeyEvent.VK_F15] = Keyboard.KEY_F15;
+// KEY_MAP[KeyEvent.VK_F16] = Keyboard.KEY_F16;
+// KEY_MAP[KeyEvent.VK_F17] = Keyboard.KEY_F17;
+// KEY_MAP[KeyEvent.VK_F18] = Keyboard.KEY_F18;
+// KEY_MAP[KeyEvent.VK_F19] = Keyboard.KEY_F19;
+ KEY_MAP[KeyEvent.VK_F2] = Keyboard.KEY_F2;
+// KEY_MAP[KeyEvent.VK_F20] = Keyboard.KEY_F20;
+// KEY_MAP[KeyEvent.VK_F21] = Keyboard.KEY_F21;
+// KEY_MAP[KeyEvent.VK_F22] = Keyboard.KEY_F22;
+// KEY_MAP[KeyEvent.VK_F23] = Keyboard.KEY_F23;
+// KEY_MAP[KeyEvent.VK_F24] = Keyboard.KEY_F24;
+ KEY_MAP[KeyEvent.VK_F3] = Keyboard.KEY_F3;
+ KEY_MAP[KeyEvent.VK_F4] = Keyboard.KEY_F4;
+ KEY_MAP[KeyEvent.VK_F5] = Keyboard.KEY_F5;
+ KEY_MAP[KeyEvent.VK_F6] = Keyboard.KEY_F6;
+ KEY_MAP[KeyEvent.VK_F7] = Keyboard.KEY_F7;
+ KEY_MAP[KeyEvent.VK_F8] = Keyboard.KEY_F8;
+ KEY_MAP[KeyEvent.VK_F9] = Keyboard.KEY_F9;
+// KEY_MAP[KeyEvent.VK_FINAL] = Keyboard.KEY_FINAL;
+// KEY_MAP[KeyEvent.VK_FIND] = Keyboard.KEY_FIND;
+// KEY_MAP[KeyEvent.VK_FULL_WIDTH] = Keyboard.KEY_FULL_WIDTH;
+ KEY_MAP[KeyEvent.VK_G] = Keyboard.KEY_G;
+// KEY_MAP[KeyEvent.VK_GREATER] = Keyboard.KEY_GREATER;
+ KEY_MAP[KeyEvent.VK_H] = Keyboard.KEY_H;
+// KEY_MAP[KeyEvent.VK_HALF_WIDTH] = Keyboard.KEY_HALF_WIDTH;
+// KEY_MAP[KeyEvent.VK_HELP] = Keyboard.KEY_HELP;
+// KEY_MAP[KeyEvent.VK_HIRAGANA] = Keyboard.KEY_HIRAGANA;
+ KEY_MAP[KeyEvent.VK_HOME] = Keyboard.KEY_HOME;
+ KEY_MAP[KeyEvent.VK_I] = Keyboard.KEY_I;
+// KEY_MAP[KeyEvent.VK_INPUT_METHOD_ON_OFF] = Keyboard.KEY_INPUT_METHOD_ON_OFF;
+ KEY_MAP[KeyEvent.VK_INSERT] = Keyboard.KEY_INSERT;
+// KEY_MAP[KeyEvent.VK_INVERTED_EXCLAMATION_MARK] = Keyboard.KEY_INVERTED_EXCLAMATION_MARK;
+ KEY_MAP[KeyEvent.VK_J] = Keyboard.KEY_J;
+// KEY_MAP[KeyEvent.VK_JAPANESE_HIRAGANA] = Keyboard.KEY_JAPANESE_HIRAGANA;
+// KEY_MAP[KeyEvent.VK_JAPANESE_KATAKANA] = Keyboard.KEY_JAPANESE_KATAKANA;
+// KEY_MAP[KeyEvent.VK_JAPANESE_ROMAN] = Keyboard.KEY_JAPANESE_ROMAN;
+ KEY_MAP[KeyEvent.VK_K] = Keyboard.KEY_K;
+ KEY_MAP[KeyEvent.VK_KANA] = Keyboard.KEY_KANA;
+// KEY_MAP[KeyEvent.VK_KANA_LOCK] = Keyboard.KEY_KANA_LOCK;
+ KEY_MAP[KeyEvent.VK_KANJI] = Keyboard.KEY_KANJI;
+// KEY_MAP[KeyEvent.VK_KATAKANA] = Keyboard.KEY_KATAKANA;
+// KEY_MAP[KeyEvent.VK_KP_DOWN] = Keyboard.KEY_KP_DOWN;
+// KEY_MAP[KeyEvent.VK_KP_LEFT] = Keyboard.KEY_KP_LEFT;
+// KEY_MAP[KeyEvent.VK_KP_RIGHT] = Keyboard.KEY_KP_RIGHT;
+// KEY_MAP[KeyEvent.VK_KP_UP] = Keyboard.KEY_KP_UP;
+ KEY_MAP[KeyEvent.VK_L] = Keyboard.KEY_L;
+ KEY_MAP[KeyEvent.VK_LEFT] = Keyboard.KEY_LEFT;
+// KEY_MAP[KeyEvent.VK_LEFT_PARENTHESIS] = Keyboard.KEY_LEFT_PARENTHESIS;
+// KEY_MAP[KeyEvent.VK_LESS] = Keyboard.KEY_LESS;
+ KEY_MAP[KeyEvent.VK_M] = Keyboard.KEY_M;
+// KEY_MAP[KeyEvent.VK_META] = Keyboard.KEY_LMENU; manually mapped
+ KEY_MAP[KeyEvent.VK_MINUS] = Keyboard.KEY_MINUS;
+// KEY_MAP[KeyEvent.VK_MODECHANGE] = Keyboard.KEY_MODECHANGE;
+ KEY_MAP[KeyEvent.VK_MULTIPLY] = Keyboard.KEY_MULTIPLY;
+ KEY_MAP[KeyEvent.VK_N] = Keyboard.KEY_N;
+// KEY_MAP[KeyEvent.VK_NONCONVERT] = Keyboard.KEY_NONCONVERT;
+ KEY_MAP[KeyEvent.VK_NUM_LOCK] = Keyboard.KEY_NUMLOCK;
+// KEY_MAP[KeyEvent.VK_NUMBER_SIGN] = Keyboard.KEY_NUMBER_SIGN;
+ KEY_MAP[KeyEvent.VK_NUMPAD0] = Keyboard.KEY_NUMPAD0;
+ KEY_MAP[KeyEvent.VK_NUMPAD1] = Keyboard.KEY_NUMPAD1;
+ KEY_MAP[KeyEvent.VK_NUMPAD2] = Keyboard.KEY_NUMPAD2;
+ KEY_MAP[KeyEvent.VK_NUMPAD3] = Keyboard.KEY_NUMPAD3;
+ KEY_MAP[KeyEvent.VK_NUMPAD4] = Keyboard.KEY_NUMPAD4;
+ KEY_MAP[KeyEvent.VK_NUMPAD5] = Keyboard.KEY_NUMPAD5;
+ KEY_MAP[KeyEvent.VK_NUMPAD6] = Keyboard.KEY_NUMPAD6;
+ KEY_MAP[KeyEvent.VK_NUMPAD7] = Keyboard.KEY_NUMPAD7;
+ KEY_MAP[KeyEvent.VK_NUMPAD8] = Keyboard.KEY_NUMPAD8;
+ KEY_MAP[KeyEvent.VK_NUMPAD9] = Keyboard.KEY_NUMPAD9;
+ KEY_MAP[KeyEvent.VK_O] = Keyboard.KEY_O;
+ KEY_MAP[KeyEvent.VK_OPEN_BRACKET] = Keyboard.KEY_LBRACKET;
+ KEY_MAP[KeyEvent.VK_P] = Keyboard.KEY_P;
+ KEY_MAP[KeyEvent.VK_PAGE_DOWN] = Keyboard.KEY_NEXT;
+ KEY_MAP[KeyEvent.VK_PAGE_UP] = Keyboard.KEY_PRIOR;
+// KEY_MAP[KeyEvent.VK_PASTE] = Keyboard.KEY_PASTE;
+ KEY_MAP[KeyEvent.VK_PAUSE] = Keyboard.KEY_PAUSE;
+ KEY_MAP[KeyEvent.VK_PERIOD] = Keyboard.KEY_PERIOD;
+// KEY_MAP[KeyEvent.VK_PLUS] = Keyboard.KEY_PLUS;
+// KEY_MAP[KeyEvent.VK_PREVIOUS_CANDIDATE] = Keyboard.KEY_PREVIOUS_CANDIDATE;
+// KEY_MAP[KeyEvent.VK_PRINTSCREEN] = Keyboard.KEY_PRINTSCREEN;
+// KEY_MAP[KeyEvent.VK_PROPS] = Keyboard.KEY_PROPS;
+ KEY_MAP[KeyEvent.VK_Q] = Keyboard.KEY_Q;
+// KEY_MAP[KeyEvent.VK_QUOTE] = Keyboard.KEY_QUOTE;
+// KEY_MAP[KeyEvent.VK_QUOTEDBL] = Keyboard.KEY_QUOTEDBL;
+ KEY_MAP[KeyEvent.VK_R] = Keyboard.KEY_R;
+ KEY_MAP[KeyEvent.VK_RIGHT] = Keyboard.KEY_RIGHT;
+// KEY_MAP[KeyEvent.VK_RIGHT_PARENTHESIS] = Keyboard.KEY_RIGHT_PARENTHESIS;
+// KEY_MAP[KeyEvent.VK_ROMAN_CHARACTERS] = Keyboard.KEY_ROMAN_CHARACTERS;
+ KEY_MAP[KeyEvent.VK_S] = Keyboard.KEY_S;
+ KEY_MAP[KeyEvent.VK_SCROLL_LOCK] = Keyboard.KEY_SCROLL;
+ KEY_MAP[KeyEvent.VK_SEMICOLON] = Keyboard.KEY_SEMICOLON;
+ KEY_MAP[KeyEvent.VK_SEPARATOR] = Keyboard.KEY_DECIMAL;
+// KEY_MAP[KeyEvent.VK_SHIFT] = Keyboard.KEY_LSHIFT; manually mapped
+ KEY_MAP[KeyEvent.VK_SLASH] = Keyboard.KEY_SLASH;
+ KEY_MAP[KeyEvent.VK_SPACE] = Keyboard.KEY_SPACE;
+ KEY_MAP[KeyEvent.VK_STOP] = Keyboard.KEY_STOP;
+ KEY_MAP[KeyEvent.VK_SUBTRACT] = Keyboard.KEY_SUBTRACT;
+ KEY_MAP[KeyEvent.VK_T] = Keyboard.KEY_T;
+ KEY_MAP[KeyEvent.VK_TAB] = Keyboard.KEY_TAB;
+ KEY_MAP[KeyEvent.VK_U] = Keyboard.KEY_U;
+// KEY_MAP[KeyEvent.VK_UNDERSCORE] = Keyboard.KEY_UNDERSCORE;
+// KEY_MAP[KeyEvent.VK_UNDO] = Keyboard.KEY_UNDO;
+ KEY_MAP[KeyEvent.VK_UP] = Keyboard.KEY_UP;
+ KEY_MAP[KeyEvent.VK_V] = Keyboard.KEY_V;
+ KEY_MAP[KeyEvent.VK_W] = Keyboard.KEY_W;
+ KEY_MAP[KeyEvent.VK_X] = Keyboard.KEY_X;
+ KEY_MAP[KeyEvent.VK_Y] = Keyboard.KEY_Y;
+ KEY_MAP[KeyEvent.VK_Z] = Keyboard.KEY_Z;
+ }
+
+ KeyboardEventQueue(Component component) {
+ super(Keyboard.EVENT_SIZE);
+ this.component = component;
+ }
+
+ public void register() {
+ component.addKeyListener(this);
+ }
+
+ public void unregister() {
+ /*
+ * This line is commented out to work around AWT bug 4867453:
+ * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4867453
+ */
+ //component.removeKeyListener(this);
+ }
+
+ private void putKeyboardEvent(int key_code, byte state, int character, long nanos, boolean repeat) {
+ event.clear();
+ event.putInt(key_code).put(state).putInt(character).putLong(nanos).put(repeat ? (byte)1 : (byte)0);
+ event.flip();
+ putEvent(event);
+ }
+
+ public synchronized void poll(ByteBuffer key_down_buffer) {
+ flushDeferredEvent();
+ int old_position = key_down_buffer.position();
+ key_down_buffer.put(key_states);
+ key_down_buffer.position(old_position);
+ }
+
+ public synchronized void copyEvents(ByteBuffer dest) {
+ flushDeferredEvent();
+ super.copyEvents(dest);
+ }
+
+ private synchronized void handleKey(int key_code, int key_location, byte state, int character, long nanos) {
+ if (character == KeyEvent.CHAR_UNDEFINED)
+ character = Keyboard.CHAR_NONE;
+ if (state == 1) {
+ boolean repeat = false;
+ if (has_deferred_event) {
+ if ((nanos == deferred_nanos && deferred_key_code == key_code &&
+ deferred_key_location == key_location)) {
+ has_deferred_event = false;
+ repeat = true; // Repeat event
+ } else
+ flushDeferredEvent();
+ }
+ putKeyEvent(key_code, key_location, state, character, nanos, repeat);
+ } else {
+ flushDeferredEvent();
+ has_deferred_event = true;
+ deferred_nanos = nanos;
+ deferred_key_code = key_code;
+ deferred_key_location = key_location;
+ deferred_key_state = state;
+ deferred_character = character;
+ }
+ }
+
+ private void flushDeferredEvent() {
+ if (has_deferred_event) {
+ putKeyEvent(deferred_key_code, deferred_key_location, deferred_key_state, deferred_character, deferred_nanos, false);
+ has_deferred_event = false;
+ }
+ }
+
+ private void putKeyEvent(int key_code, int key_location, byte state, int character, long nanos, boolean repeat) {
+ int key_code_mapped = getMappedKeyCode(key_code, key_location);
+ /* Ignore repeating presses */
+ if ( key_states[key_code_mapped] == state )
+ repeat = true;
+ key_states[key_code_mapped] = state;
+ int key_int_char = character & 0xffff;
+ putKeyboardEvent(key_code_mapped, state, key_int_char, nanos, repeat);
+ }
+
+ private int getMappedKeyCode(int key_code, int position) {
+ // manually map positioned keys
+ switch (key_code) {
+ case KeyEvent.VK_ALT: // fall through
+ if (position == KeyEvent.KEY_LOCATION_RIGHT)
+ return Keyboard.KEY_RMENU;
+ else
+ return Keyboard.KEY_LMENU;
+ case KeyEvent.VK_META:
+ if (position == KeyEvent.KEY_LOCATION_RIGHT)
+ return Keyboard.KEY_RMETA;
+ else
+ return Keyboard.KEY_LMETA;
+ case KeyEvent.VK_SHIFT:
+ if (position == KeyEvent.KEY_LOCATION_RIGHT)
+ return Keyboard.KEY_RSHIFT;
+ else
+ return Keyboard.KEY_LSHIFT;
+ case KeyEvent.VK_CONTROL:
+ if (position == KeyEvent.KEY_LOCATION_RIGHT)
+ return Keyboard.KEY_RCONTROL;
+ else
+ return Keyboard.KEY_LCONTROL;
+ default:
+ return KEY_MAP[key_code];
+ }
+ }
+
+ public void keyPressed(KeyEvent e) {
+ handleKey(e.getKeyCode(), e.getKeyLocation(), (byte)1, e.getKeyChar(), e.getWhen()*1000000);
+ }
+
+ public void keyReleased(KeyEvent e) {
+ handleKey(e.getKeyCode(), e.getKeyLocation(), (byte)0, Keyboard.CHAR_NONE, e.getWhen()*1000000);
+ }
+
+ public void keyTyped(KeyEvent e) {
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java
new file mode 100644
index 0000000..8258c77
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2002-2008 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.LWJGLUtil;
+import java.awt.Canvas;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: LinuxAWTGLCanvasPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class LinuxAWTGLCanvasPeerInfo extends LinuxPeerInfo {
+ private final Canvas component;
+ private final AWTSurfaceLock awt_surface = new AWTSurfaceLock();
+ private int screen = -1;
+
+ LinuxAWTGLCanvasPeerInfo(Canvas component) {
+ this.component = component;
+ }
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ ByteBuffer surface_handle = awt_surface.lockAndGetHandle(component);
+ if (screen == -1) {
+ try {
+ screen = getScreenFromSurfaceInfo(surface_handle);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Got exception while trying to determine screen: " + e);
+ screen = 0;
+ }
+ }
+ nInitHandle(screen, surface_handle, getHandle());
+ }
+ private static native int getScreenFromSurfaceInfo(ByteBuffer surface_handle) throws LWJGLException;
+ 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 0000000..42b610d
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2002-2008 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.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Canvas;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3002 $
+ * $Id: LinuxCanvasImplementation.java 3002 2008-04-10 20:25:54Z elias_naur $
+ */
+final class LinuxCanvasImplementation implements AWTCanvasImplementation {
+ static int getScreenFromDevice(final GraphicsDevice device) throws LWJGLException {
+ try {
+ Method getScreen_method = (Method)AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return device.getClass().getMethod("getScreen", null);
+ }
+ });
+ Integer screen = (Integer)getScreen_method.invoke(device, null);
+ return screen.intValue();
+ } catch (Exception e) {
+ throw new LWJGLException(e);
+ }
+ }
+
+ private static int getVisualIDFromConfiguration(final GraphicsConfiguration configuration) throws LWJGLException {
+ try {
+ Method getVisual_method = (Method)AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return configuration.getClass().getMethod("getVisual", null);
+ }
+ });
+ Integer visual = (Integer)getVisual_method.invoke(configuration, null);
+ return visual.intValue();
+ } catch (Exception e) {
+ throw new LWJGLException(e);
+ }
+ }
+
+ public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
+ return new LinuxAWTGLCanvasPeerInfo(component);
+ }
+
+ /**
+ * 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 {
+ try {
+ 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];
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Got exception while trying to determine configuration: " + e);
+ }
+ return null; // In case we failed to locate the visual, or if we're not on a SUN JDK
+ }
+
+ private static int findVisualIDFromFormat(int screen, PixelFormat pixel_format) throws LWJGLException {
+ try {
+ LinuxDisplay.lockAWT();
+ try {
+ GLContext.loadOpenGLLibrary();
+ try {
+ LinuxDisplay.incDisplay();
+ return nFindVisualIDFromFormat(LinuxDisplay.getDisplay(), screen, pixel_format);
+ } finally {
+ LinuxDisplay.decDisplay();
+ }
+ } finally {
+ GLContext.unloadOpenGLLibrary();
+ }
+ } finally {
+ LinuxDisplay.unlockAWT();
+ }
+ }
+ private static native int nFindVisualIDFromFormat(long display, int screen, PixelFormat pixel_format) throws LWJGLException;
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxContextAttribs.java b/src/java/org/lwjgl/opengl/LinuxContextAttribs.java
new file mode 100644
index 0000000..d8fa015
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxContextAttribs.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * An implementation of ContextAttribs using GLX_create_context.
+ *
+ * ---- WIP - GLX_create_context has not been defined yet ----
+ *
+ * @author spasi
+ */
+final class LinuxContextAttribs implements ContextAttribsImplementation {
+
+ private static final int GLX_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
+ private static final int GLX_CONTEXT_MINOR_VERSION_ARB = 0x2092;
+ private static final int GLX_CONTEXT_LAYER_PLANE_ARB = 0x2093;
+ private static final int GLX_CONTEXT_FLAGS_ARB = 0x2094;
+ private static final int GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126;
+
+ private static final int GLX_CONTEXT_DEBUG_BIT_ARB = 0x0001;
+ private static final int GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002;
+
+ private static final int GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
+ private static final int GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
+
+ LinuxContextAttribs() {
+ }
+
+ public int getMajorVersionAttrib() {
+ return GLX_CONTEXT_MAJOR_VERSION_ARB;
+ }
+
+ public int getMinorVersionAttrib() {
+ return GLX_CONTEXT_MINOR_VERSION_ARB;
+ }
+
+ public int getLayerPlaneAttrib() {
+ return GLX_CONTEXT_LAYER_PLANE_ARB;
+ }
+
+ public int getFlagsAttrib() {
+ return GLX_CONTEXT_FLAGS_ARB;
+ }
+
+ public int getDebugBit() {
+ return GLX_CONTEXT_DEBUG_BIT_ARB;
+ }
+
+ public int getForwardCompatibleBit() {
+ return GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+ }
+
+ public int getProfileMaskAttrib() {
+ return GLX_CONTEXT_PROFILE_MASK_ARB;
+ }
+
+ public int getProfileCoreBit() {
+ return GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+
+ public int getProfileCompatibilityBit() {
+ return GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/LinuxContextImplementation.java b/src/java/org/lwjgl/opengl/LinuxContextImplementation.java
new file mode 100644
index 0000000..1704dce
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxContextImplementation.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.LWJGLException;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+/**
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: LinuxContextImplementation.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class LinuxContextImplementation implements ContextImplementation {
+
+ public ByteBuffer create(PeerInfo peer_info, IntBuffer attribs, ByteBuffer shared_context_handle) throws LWJGLException {
+ LinuxDisplay.lockAWT();
+ try {
+ ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ try {
+ return nCreate(peer_handle, attribs, shared_context_handle);
+ } finally {
+ peer_info.unlock();
+ }
+ } finally {
+ LinuxDisplay.unlockAWT();
+ }
+ }
+
+ private static native ByteBuffer nCreate(ByteBuffer peer_handle, IntBuffer attribs, ByteBuffer shared_context_handle) throws LWJGLException;
+
+ public void releaseDrawable(ByteBuffer context_handle) throws LWJGLException {
+ }
+
+ public void swapBuffers() throws LWJGLException {
+ Context current_context = Context.getCurrentContext();
+ if ( current_context == null )
+ throw new IllegalStateException("No context is current");
+ synchronized ( current_context ) {
+ PeerInfo current_peer_info = current_context.getPeerInfo();
+ 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 {
+ Context current_context = Context.getCurrentContext();
+ if ( current_context == null )
+ throw new IllegalStateException("No context is current");
+ synchronized ( current_context ) {
+ PeerInfo current_peer_info = current_context.getPeerInfo();
+ 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 update(ByteBuffer context_handle) {
+ }
+
+ 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 setSwapInterval(int value) {
+ Context current_context = Context.getCurrentContext();
+ if ( current_context == null )
+ throw new IllegalStateException("No context is current");
+ synchronized ( current_context ) {
+ LinuxDisplay.lockAWT();
+ nSetSwapInterval(current_context.getHandle(), value);
+ LinuxDisplay.unlockAWT();
+ }
+ }
+
+ private static native void nSetSwapInterval(ByteBuffer context_handle, int value);
+
+ 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
new file mode 100644
index 0000000..609d86f
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java
@@ -0,0 +1,1215 @@
+/*
+ * Copyright (c) 2002-2010 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;
+
+/**
+ * This is the Display implementation interface. Display delegates
+ * to implementors of this interface. There is one DisplayImplementation
+ * for each supported platform.
+ * @author elias_naur
+ */
+
+import java.awt.Canvas;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.opengl.XRandR.Screen;
+
+final class LinuxDisplay implements DisplayImplementation {
+ /* X11 constants */
+ public final static int CurrentTime = 0;
+ public final static int GrabSuccess = 0;
+ public final static int AutoRepeatModeOff = 0;
+ public final static int AutoRepeatModeOn = 1;
+ public final static int AutoRepeatModeDefault = 2;
+ public final static int None = 0;
+
+ private final static int KeyPressMask = 1 << 0;
+ private final static int KeyReleaseMask = 1 << 1;
+ private final static int ButtonPressMask = 1 << 2;
+ private final static int ButtonReleaseMask = 1 << 3;
+
+ private final static int NotifyAncestor = 0;
+ private final static int NotifyNonlinear = 3;
+ private final static int NotifyPointer = 5;
+ private final static int NotifyPointerRoot = 6;
+ private final static int NotifyDetailNone = 7;
+
+ private final static int SetModeInsert = 0;
+ private final static int SaveSetRoot = 1;
+ private final static int SaveSetUnmap = 1;
+
+ /** Window mode enum */
+ private static final int FULLSCREEN_LEGACY = 1;
+ private static final int FULLSCREEN_NETWM = 2;
+ private static final int WINDOWED = 3;
+
+ /** Current window mode */
+ private static int current_window_mode = WINDOWED;
+
+ /** Display mode switching API */
+ private static final int XRANDR = 10;
+ private static final int XF86VIDMODE = 11;
+ private static final int NONE = 12;
+
+ /** Current X11 Display pointer */
+ private static long display;
+ private static long current_window;
+ private static long saved_error_handler;
+
+ private static int display_connection_usage_count = 0;
+
+ /** Event buffer */
+ private final LinuxEvent event_buffer = new LinuxEvent();
+ private final LinuxEvent tmp_event_buffer = new LinuxEvent();
+
+ /** Current mode swithcing API */
+ private int current_displaymode_extension = NONE;
+
+ /** Atom used for the pointer warp messages */
+ private long delete_atom;
+
+ private PeerInfo peer_info;
+
+ /** Saved gamma used to restore display settings */
+ private ByteBuffer saved_gamma;
+ private ByteBuffer current_gamma;
+
+ /** Saved mode to restore with */
+ private DisplayMode saved_mode;
+ private DisplayMode current_mode;
+
+ private Screen[] savedXrandrConfig;
+
+ private boolean keyboard_grabbed;
+ private boolean pointer_grabbed;
+ private boolean input_released;
+ private boolean grab;
+ private boolean focused;
+ private boolean minimized;
+ private boolean dirty;
+ private boolean close_requested;
+ private long current_cursor;
+ private long blank_cursor;
+ private Canvas parent;
+ private long parent_window;
+ private boolean xembedded;
+ private boolean parent_focus;
+
+ private LinuxKeyboard keyboard;
+ private LinuxMouse mouse;
+
+ private static ByteBuffer getCurrentGammaRamp() throws LWJGLException {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ if (isXF86VidModeSupported())
+ return nGetCurrentGammaRamp(getDisplay(), getDefaultScreen());
+ else
+ return null;
+ } finally {
+ decDisplay();
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native ByteBuffer nGetCurrentGammaRamp(long display, int screen) throws LWJGLException;
+
+ private static int getBestDisplayModeExtension() {
+ int result;
+ if (isXrandrSupported()) {
+ LWJGLUtil.log("Using Xrandr for display mode switching");
+ result = XRANDR;
+ } else if (isXF86VidModeSupported()) {
+ LWJGLUtil.log("Using XF86VidMode for display mode switching");
+ result = XF86VIDMODE;
+ } else {
+ LWJGLUtil.log("No display mode extensions available");
+ result = NONE;
+ }
+ return result;
+ }
+
+ private static boolean isXrandrSupported() {
+ if (Display.getPrivilegedBoolean("LWJGL_DISABLE_XRANDR"))
+ return false;
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ return nIsXrandrSupported(getDisplay());
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Got exception while querying Xrandr support: " + e);
+ return false;
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native boolean nIsXrandrSupported(long display) throws LWJGLException;
+
+ private static boolean isXF86VidModeSupported() {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ return nIsXF86VidModeSupported(getDisplay());
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Got exception while querying XF86VM support: " + e);
+ return false;
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native boolean nIsXF86VidModeSupported(long display) throws LWJGLException;
+
+ private static boolean isNetWMFullscreenSupported() throws LWJGLException {
+ if (Display.getPrivilegedBoolean("LWJGL_DISABLE_NETWM"))
+ return false;
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ return nIsNetWMFullscreenSupported(getDisplay(), getDefaultScreen());
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Got exception while querying NetWM support: " + e);
+ return false;
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native boolean nIsNetWMFullscreenSupported(long display, int screen) throws LWJGLException;
+
+ /* 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 Lock()/Unlock() to
+ * do just that.
+ */
+ static void lockAWT() {
+ try {
+ nLockAWT();
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Caught exception while locking AWT: " + e);
+ }
+ }
+ private static native void nLockAWT() throws LWJGLException;
+
+ static void unlockAWT() {
+ try {
+ nUnlockAWT();
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Caught exception while unlocking AWT: " + e);
+ }
+ }
+ private static native void nUnlockAWT() throws LWJGLException;
+
+ /**
+ * increment and decrement display usage.
+ */
+ static void incDisplay() throws LWJGLException {
+ if (display_connection_usage_count == 0) {
+ GLContext.loadOpenGLLibrary();
+ saved_error_handler = setErrorHandler();
+ display = openDisplay();
+// synchronize(display, true);
+ }
+ display_connection_usage_count++;
+ }
+ private static native int callErrorHandler(long handler, long display, long error_ptr);
+ private static native long setErrorHandler();
+ private static native long resetErrorHandler(long handler);
+ private static native void synchronize(long display, boolean synchronize);
+
+ private static int globalErrorHandler(long display, long event_ptr, long error_display, long serial, long error_code, long request_code, long minor_code) throws LWJGLException {
+ if (display == getDisplay()) {
+ String error_msg = getErrorText(display, error_code);
+ throw new LWJGLException("X Error - disp: 0x" + Long.toHexString(error_display) + " serial: " + serial + " error: " + error_msg + " request_code: " + request_code + " minor_code: " + minor_code);
+ } else if (saved_error_handler != 0)
+ return callErrorHandler(saved_error_handler, display, event_ptr);
+ return 0;
+ }
+ private static native String getErrorText(long display, long error_code);
+
+ static void decDisplay() {
+ /*
+ * Some drivers (at least some versions of the radeon dri driver)
+ * don't like it when the display is closed and later re-opened,
+ * so we'll just let the singleton display connection leak.
+ */
+/* display_connection_usage_count--;
+ if (display_connection_usage_count < 0)
+ throw new InternalError("display_connection_usage_count < 0: " + display_connection_usage_count);
+ if (display_connection_usage_count == 0) {
+ closeDisplay(display);
+ resetErrorHandler(saved_error_handler);
+ display = 0;
+ GLContext.unloadOpenGLLibrary();
+ }*/
+ }
+
+ static native long openDisplay() throws LWJGLException;
+ static native void closeDisplay(long display);
+
+ private int getWindowMode(boolean fullscreen) throws LWJGLException {
+ if (fullscreen) {
+ if (current_displaymode_extension == XRANDR && isNetWMFullscreenSupported()) {
+ LWJGLUtil.log("Using NetWM for fullscreen window");
+ return FULLSCREEN_NETWM;
+ } else {
+ LWJGLUtil.log("Using legacy mode for fullscreen window");
+ return FULLSCREEN_LEGACY;
+ }
+ } else
+ return WINDOWED;
+ }
+
+ static long getDisplay() {
+ if (display_connection_usage_count <= 0)
+ throw new InternalError("display_connection_usage_count = " + display_connection_usage_count);
+ return display;
+ }
+
+ static int getDefaultScreen() {
+ return nGetDefaultScreen(getDisplay());
+ }
+ static native int nGetDefaultScreen(long display);
+
+ static long getWindow() {
+ return current_window;
+ }
+
+ private void ungrabKeyboard() {
+ if (keyboard_grabbed) {
+ nUngrabKeyboard(getDisplay());
+ keyboard_grabbed = false;
+ }
+ }
+ static native int nUngrabKeyboard(long display);
+
+ private void grabKeyboard() {
+ if (!keyboard_grabbed) {
+ int res = nGrabKeyboard(getDisplay(), getWindow());
+ if (res == GrabSuccess)
+ keyboard_grabbed = true;
+ }
+ }
+ static native int nGrabKeyboard(long display, long window);
+
+ private void grabPointer() {
+ if (!pointer_grabbed) {
+ int result = nGrabPointer(getDisplay(), getWindow(), None);
+ if (result == GrabSuccess) {
+ pointer_grabbed = true;
+ // make sure we have a centered window
+ if (isLegacyFullscreen()) {
+ nSetViewPort(getDisplay(), getWindow(), getDefaultScreen());
+ }
+ }
+ }
+ }
+ static native int nGrabPointer(long display, long window, long cursor);
+ private static native void nSetViewPort(long display, long window, int screen);
+
+ private void ungrabPointer() {
+ if (pointer_grabbed) {
+ pointer_grabbed = false;
+ nUngrabPointer(getDisplay());
+ }
+ }
+ static native int nUngrabPointer(long display);
+
+ private boolean isFullscreen() {
+ return current_window_mode == FULLSCREEN_LEGACY || current_window_mode == FULLSCREEN_NETWM;
+ }
+
+ private boolean shouldGrab() {
+ return !input_released && grab && mouse != null;
+ }
+
+ private void updatePointerGrab() {
+ if (isFullscreen() || shouldGrab()) {
+ grabPointer();
+ } else {
+ ungrabPointer();
+ }
+ updateCursor();
+ }
+
+ private void updateCursor() {
+ long cursor;
+ if (shouldGrab()) {
+ cursor = blank_cursor;
+ } else {
+ cursor = current_cursor;
+ }
+ nDefineCursor(getDisplay(), getWindow(), cursor);
+ }
+ private static native void nDefineCursor(long display, long window, long cursor_handle);
+
+ private boolean isLegacyFullscreen() {
+ return current_window_mode == FULLSCREEN_LEGACY;
+ }
+
+ private void updateKeyboardGrab() {
+ if (isLegacyFullscreen())
+ grabKeyboard();
+ else
+ ungrabKeyboard();
+ }
+
+ public void createWindow(DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ ByteBuffer handle = peer_info.lockAndGetHandle();
+ try {
+ current_window_mode = getWindowMode(Display.isFullscreen());
+ boolean undecorated = Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated") || current_window_mode != WINDOWED;
+ this.parent = parent;
+ parent_window = parent != null ? getHandle(parent) : getRootWindow(getDisplay(), getDefaultScreen());
+ current_window = nCreateWindow(getDisplay(), getDefaultScreen(), handle, mode, current_window_mode, x, y, undecorated, parent_window);
+ mapRaised(getDisplay(), current_window);
+ xembedded = parent != null && isAncestorXEmbedded(parent_window);
+ blank_cursor = createBlankCursor();
+ current_cursor = None;
+ focused = false;
+ input_released = false;
+ pointer_grabbed = false;
+ keyboard_grabbed = false;
+ close_requested = false;
+ grab = false;
+ minimized = false;
+ dirty = true;
+ } finally {
+ peer_info.unlock();
+ }
+ } catch (LWJGLException e) {
+ decDisplay();
+ throw e;
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native long nCreateWindow(long display, int screen, ByteBuffer peer_info_handle, DisplayMode mode, int window_mode, int x, int y, boolean undecorated, long parent_handle) throws LWJGLException;
+ private static native long getRootWindow(long display, int screen);
+ private static native boolean hasProperty(long display, long window, long property);
+ private static native long getParentWindow(long display, long window) throws LWJGLException;
+ private static native void mapRaised(long display, long window);
+ private static native void reparentWindow(long display, long window, long parent, int x, int y);
+
+ private boolean isAncestorXEmbedded(long window) throws LWJGLException {
+ long xembed_atom = internAtom("_XEMBED_INFO", true);
+ if (xembed_atom != None) {
+ long w = window;
+ while (w != None) {
+ if (hasProperty(getDisplay(), w, xembed_atom))
+ return true;
+ w = getParentWindow(getDisplay(), w);
+ }
+ }
+ return false;
+ }
+
+ private static long getHandle(Canvas parent) throws LWJGLException {
+ AWTCanvasImplementation awt_impl = AWTGLCanvas.createImplementation();
+ LinuxPeerInfo parent_peer_info = (LinuxPeerInfo)awt_impl.createPeerInfo(parent, null);
+ ByteBuffer parent_peer_info_handle = parent_peer_info.lockAndGetHandle();
+ try {
+ return parent_peer_info.getDrawable();
+ } finally {
+ parent_peer_info.unlock();
+ }
+ }
+
+ private void updateInputGrab() {
+ updatePointerGrab();
+ updateKeyboardGrab();
+ }
+
+ public void destroyWindow() {
+ lockAWT();
+ try {
+ try {
+ setNativeCursor(null);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to reset cursor: " + e.getMessage());
+ }
+ nDestroyCursor(getDisplay(), blank_cursor);
+ blank_cursor = None;
+ ungrabKeyboard();
+ nDestroyWindow(getDisplay(), getWindow());
+ decDisplay();
+ } finally {
+ unlockAWT();
+ }
+ }
+ static native void nDestroyWindow(long display, long window);
+
+ public void switchDisplayMode(DisplayMode mode) throws LWJGLException {
+ lockAWT();
+ try {
+ switchDisplayModeOnTmpDisplay(mode);
+ current_mode = mode;
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ private void switchDisplayModeOnTmpDisplay(DisplayMode mode) throws LWJGLException {
+ incDisplay();
+ try {
+ nSwitchDisplayMode(getDisplay(), getDefaultScreen(), current_displaymode_extension, mode);
+ } finally {
+ decDisplay();
+ }
+ }
+ private static native void nSwitchDisplayMode(long display, int screen, int extension, DisplayMode mode) throws LWJGLException;
+
+ private static long internAtom(String atom_name, boolean only_if_exists) throws LWJGLException {
+ incDisplay();
+ try {
+ return nInternAtom(getDisplay(), atom_name, only_if_exists);
+ } finally {
+ decDisplay();
+ }
+ }
+ static native long nInternAtom(long display, String atom_name, boolean only_if_exists);
+
+ public void resetDisplayMode() {
+ lockAWT();
+ try {
+ if( current_displaymode_extension == XRANDR && savedXrandrConfig.length > 0 )
+ {
+ XRandR.setConfiguration( savedXrandrConfig );
+ }
+ else
+ {
+ switchDisplayMode(saved_mode);
+ }
+ if (isXF86VidModeSupported())
+ doSetGamma(saved_gamma);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Caught exception while resetting mode: " + e);
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public int getGammaRampLength() {
+ if (!isXF86VidModeSupported())
+ return 0;
+ lockAWT();
+ try {
+ try {
+ incDisplay();
+ try {
+ return nGetGammaRampLength(getDisplay(), getDefaultScreen());
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Got exception while querying gamma length: " + e);
+ return 0;
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to get gamma ramp length: " + e);
+ return 0;
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native int nGetGammaRampLength(long display, int screen) throws LWJGLException;
+
+ public void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException {
+ if (!isXF86VidModeSupported())
+ throw new LWJGLException("No gamma ramp support (Missing XF86VM extension)");
+ doSetGamma(convertToNativeRamp(gammaRamp));
+ }
+
+ private void doSetGamma(ByteBuffer native_gamma) throws LWJGLException {
+ lockAWT();
+ try {
+ setGammaRampOnTmpDisplay(native_gamma);
+ current_gamma = native_gamma;
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ private void setGammaRampOnTmpDisplay(ByteBuffer native_gamma) throws LWJGLException {
+ incDisplay();
+ try {
+ nSetGammaRamp(getDisplay(), getDefaultScreen(), native_gamma);
+ } finally {
+ decDisplay();
+ }
+ }
+ private static native void nSetGammaRamp(long display, int screen, ByteBuffer gammaRamp) throws LWJGLException;
+
+ private static ByteBuffer convertToNativeRamp(FloatBuffer ramp) throws LWJGLException {
+ return nConvertToNativeRamp(ramp, ramp.position(), ramp.remaining());
+ }
+ private static native ByteBuffer nConvertToNativeRamp(FloatBuffer ramp, int offset, int length) throws LWJGLException;
+
+ public String getAdapter() {
+ return null;
+ }
+
+ public String getVersion() {
+ return null;
+ }
+
+ public DisplayMode init() throws LWJGLException {
+ lockAWT();
+ try {
+ delete_atom = internAtom("WM_DELETE_WINDOW", false);
+ current_displaymode_extension = getBestDisplayModeExtension();
+ if (current_displaymode_extension == NONE)
+ throw new LWJGLException("No display mode extension is available");
+ DisplayMode[] modes = getAvailableDisplayModes();
+ if (modes == null || modes.length == 0)
+ throw new LWJGLException("No modes available");
+ switch (current_displaymode_extension) {
+ case XRANDR:
+ savedXrandrConfig = XRandR.getConfiguration();
+ saved_mode = getCurrentXRandrMode();
+ break;
+ case XF86VIDMODE:
+ saved_mode = modes[0];
+ break;
+ default:
+ throw new LWJGLException("Unknown display mode extension: " + current_displaymode_extension);
+ }
+ current_mode = saved_mode;
+ saved_gamma = getCurrentGammaRamp();
+ current_gamma = saved_gamma;
+ return saved_mode;
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ private static DisplayMode getCurrentXRandrMode() throws LWJGLException {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ return nGetCurrentXRandrMode(getDisplay(), getDefaultScreen());
+ } finally {
+ decDisplay();
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ /** Assumes extension == XRANDR */
+ private static native DisplayMode nGetCurrentXRandrMode(long display, int screen) throws LWJGLException;
+
+ public void setTitle(String title) {
+ lockAWT();
+ try {
+ nSetTitle(getDisplay(), getWindow(), title);
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native void nSetTitle(long display, long window, String title);
+
+ public boolean isCloseRequested() {
+ boolean result = close_requested;
+ close_requested = false;
+ return result;
+ }
+
+ public boolean isVisible() {
+ return !minimized;
+ }
+
+ public boolean isActive() {
+ return focused || isLegacyFullscreen();
+ }
+
+ public boolean isDirty() {
+ boolean result = dirty;
+ dirty = false;
+ return result;
+ }
+
+ public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException {
+ peer_info = new LinuxDisplayPeerInfo(pixel_format);
+ return peer_info;
+ }
+
+ static native void setInputFocus(long display, long window, long time);
+
+ private void relayEventToParent(LinuxEvent event_buffer, int event_mask) {
+ tmp_event_buffer.copyFrom(event_buffer);
+ tmp_event_buffer.setWindow(parent_window);
+ tmp_event_buffer.sendEvent(getDisplay(), parent_window, true, event_mask);
+ }
+
+ private void relayEventToParent(LinuxEvent event_buffer) {
+ if (parent == null)
+ return;
+ switch (event_buffer.getType()) {
+ case LinuxEvent.KeyPress:
+ relayEventToParent(event_buffer, KeyPressMask);
+ break;
+ case LinuxEvent.KeyRelease:
+ relayEventToParent(event_buffer, KeyPressMask);
+ break;
+ case LinuxEvent.ButtonPress:
+ relayEventToParent(event_buffer, KeyPressMask);
+ break;
+ case LinuxEvent.ButtonRelease:
+ relayEventToParent(event_buffer, KeyPressMask);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void processEvents() {
+ while (LinuxEvent.getPending(getDisplay()) > 0) {
+ event_buffer.nextEvent(getDisplay());
+ long event_window = event_buffer.getWindow();
+ relayEventToParent(event_buffer);
+ if (event_window != getWindow() || event_buffer.filterEvent(event_window) ||
+ (mouse != null && mouse.filterEvent(grab, shouldWarpPointer(), event_buffer)) ||
+ (keyboard != null && keyboard.filterEvent(event_buffer)))
+ continue;
+ switch (event_buffer.getType()) {
+ case LinuxEvent.FocusIn:
+ setFocused(true, event_buffer.getFocusDetail());
+ break;
+ case LinuxEvent.FocusOut:
+ setFocused(false, event_buffer.getFocusDetail());
+ break;
+ case LinuxEvent.ClientMessage:
+ if ((event_buffer.getClientFormat() == 32) && (event_buffer.getClientData(0) == delete_atom))
+ close_requested = true;
+ break;
+ case LinuxEvent.MapNotify:
+ dirty = true;
+ minimized = false;
+ break;
+ case LinuxEvent.UnmapNotify:
+ dirty = true;
+ minimized = true;
+ break;
+ case LinuxEvent.Expose:
+ dirty = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ public void update() {
+ lockAWT();
+ try {
+ processEvents();
+ checkInput();
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void reshape(int x, int y, int width, int height) {
+ lockAWT();
+ try {
+ nReshape(getDisplay(), getWindow(), x, y, width, height);
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native void nReshape(long display, long window, int x, int y, int width, int height);
+
+ public DisplayMode[] getAvailableDisplayModes() throws LWJGLException {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ DisplayMode[] modes = nGetAvailableDisplayModes(getDisplay(), getDefaultScreen(), current_displaymode_extension);
+ return modes;
+ } finally {
+ decDisplay();
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native DisplayMode[] nGetAvailableDisplayModes(long display, int screen, int extension) throws LWJGLException;
+
+ /* Mouse */
+ public boolean hasWheel() {
+ return true;
+ }
+
+ public int getButtonCount() {
+ return mouse.getButtonCount();
+ }
+
+ public void createMouse() throws LWJGLException {
+ lockAWT();
+ try {
+ mouse = new LinuxMouse(getDisplay(), getWindow(), getWindow());
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void destroyMouse() {
+ mouse = null;
+ updateInputGrab();
+ }
+
+ public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons) {
+ lockAWT();
+ try {
+ mouse.poll(grab, coord_buffer, buttons);
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void readMouse(ByteBuffer buffer) {
+ lockAWT();
+ try {
+ mouse.read(buffer);
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void setCursorPosition(int x, int y) {
+ lockAWT();
+ try {
+ mouse.setCursorPosition(x, y);
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ private void checkInput() {
+ if (parent == null) return;
+
+ if (parent_focus != parent.hasFocus()) {
+ parent_focus = parent.hasFocus();
+
+ if (parent_focus) {
+ setInputFocusUnsafe(current_window);
+ }
+ else if (xembedded) {
+ setInputFocusUnsafe(0);
+ }
+ }
+ else if (parent_focus && !focused) {
+ setInputFocusUnsafe(current_window);
+ }
+ }
+
+ private void setFocused(boolean got_focus, int focus_detail) {
+ if (focused == got_focus || focus_detail == NotifyDetailNone || focus_detail == NotifyPointer || focus_detail == NotifyPointerRoot)
+ return;
+ focused = got_focus;
+
+ if (focused) {
+ acquireInput();
+ }
+ else {
+ releaseInput();
+ }
+ }
+ static native long nGetInputFocus(long display);
+
+ private void setInputFocusUnsafe(long window) {
+ try {
+ setInputFocus(getDisplay(), window, CurrentTime);
+ sync(getDisplay(), false);
+ } catch (LWJGLException e) {
+ // Since we don't have any event timings for XSetInputFocus, a race condition might give a BadMatch, which we'll catch and ignore
+ LWJGLUtil.log("Got exception while trying to focus: " + e);
+ }
+ }
+ private static native void sync(long display, boolean throw_away_events) throws LWJGLException;
+
+ private void releaseInput() {
+ if (isLegacyFullscreen() || input_released)
+ return;
+ input_released = true;
+ updateInputGrab();
+ if (current_window_mode == FULLSCREEN_NETWM) {
+ nIconifyWindow(getDisplay(), getWindow(), getDefaultScreen());
+ try {
+ if( current_displaymode_extension == XRANDR && savedXrandrConfig.length > 0 )
+ {
+ XRandR.setConfiguration( savedXrandrConfig );
+ }
+ else
+ {
+ switchDisplayModeOnTmpDisplay(saved_mode);
+ }
+ setGammaRampOnTmpDisplay(saved_gamma);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to restore saved mode: " + e.getMessage());
+ }
+ }
+ }
+ private static native void nIconifyWindow(long display, long window, int screen);
+
+ private void acquireInput() {
+ if (isLegacyFullscreen() || !input_released)
+ return;
+ input_released = false;
+ updateInputGrab();
+ if (current_window_mode == FULLSCREEN_NETWM) {
+ try {
+ switchDisplayModeOnTmpDisplay(current_mode);
+ setGammaRampOnTmpDisplay(current_gamma);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to restore mode: " + e.getMessage());
+ }
+ }
+ }
+
+ public void grabMouse(boolean new_grab) {
+ lockAWT();
+ try {
+ if (new_grab != grab) {
+ grab = new_grab;
+ updateInputGrab();
+ mouse.changeGrabbed(grab, shouldWarpPointer());
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ private boolean shouldWarpPointer() {
+ return pointer_grabbed && shouldGrab();
+ }
+
+ public int getNativeCursorCapabilities() {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ return nGetNativeCursorCapabilities(getDisplay());
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native int nGetNativeCursorCapabilities(long display) throws LWJGLException;
+
+ public void setNativeCursor(Object handle) throws LWJGLException {
+ current_cursor = getCursorHandle(handle);
+ lockAWT();
+ try {
+ updateCursor();
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public int getMinCursorSize() {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ return nGetMinCursorSize(getDisplay(), getWindow());
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred in getMinCursorSize: " + e);
+ return 0;
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native int nGetMinCursorSize(long display, long window);
+
+ public int getMaxCursorSize() {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ return nGetMaxCursorSize(getDisplay(), getWindow());
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred in getMaxCursorSize: " + e);
+ return 0;
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native int nGetMaxCursorSize(long display, long window);
+
+ /* Keyboard */
+ public void createKeyboard() throws LWJGLException {
+ lockAWT();
+ try {
+ keyboard = new LinuxKeyboard(getDisplay(), getWindow());
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void destroyKeyboard() {
+ lockAWT();
+ try {
+ keyboard.destroy(getDisplay());
+ keyboard = null;
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void pollKeyboard(ByteBuffer keyDownBuffer) {
+ lockAWT();
+ try {
+ keyboard.poll(keyDownBuffer);
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void readKeyboard(ByteBuffer buffer) {
+ lockAWT();
+ try {
+ keyboard.read(buffer);
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ private static native long nCreateCursor(long display, int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset, IntBuffer delays, int delays_offset) throws LWJGLException;
+
+ private static long createBlankCursor() {
+ return nCreateBlankCursor(getDisplay(), getWindow());
+ }
+ static native long nCreateBlankCursor(long display, long window);
+
+ public Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ long cursor = nCreateCursor(getDisplay(), width, height, xHotspot, yHotspot, numImages, images, images.position(), delays, delays != null ? delays.position() : -1);
+ return new Long(cursor);
+ } catch (LWJGLException e) {
+ decDisplay();
+ throw e;
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ private static long getCursorHandle(Object cursor_handle) {
+ return cursor_handle != null ? ((Long)cursor_handle).longValue() : None;
+ }
+
+ public void destroyCursor(Object cursorHandle) {
+ lockAWT();
+ try {
+ nDestroyCursor(getDisplay(), getCursorHandle(cursorHandle));
+ decDisplay();
+ } finally {
+ unlockAWT();
+ }
+ }
+ static native void nDestroyCursor(long display, long cursorHandle);
+
+ public int getPbufferCapabilities() {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ return nGetPbufferCapabilities(getDisplay(), getDefaultScreen());
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred in getPbufferCapabilities: " + e);
+ return 0;
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native int nGetPbufferCapabilities(long display, int screen);
+
+ public boolean isBufferLost(PeerInfo handle) {
+ return false;
+ }
+
+ public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format,
+ IntBuffer pixelFormatCaps,
+ IntBuffer pBufferAttribs) throws LWJGLException {
+ return new LinuxPbufferPeerInfo(width, height, pixel_format);
+ }
+
+ public void setPbufferAttrib(PeerInfo handle, int attrib, int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void bindTexImageToPbuffer(PeerInfo handle, int buffer) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void releaseTexImageFromPbuffer(PeerInfo handle, int buffer) {
+ throw new UnsupportedOperationException();
+ }
+
+ private static ByteBuffer convertIcon(ByteBuffer icon, int width, int height) {
+ ByteBuffer icon_rgb = BufferUtils.createByteBuffer(icon.capacity());
+ int x;
+ int y;
+ byte r,g,b;
+
+ int depth = 4;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ r = icon.get((x*4)+(y*width*4));
+ g = icon.get((x*4)+(y*width*4)+1);
+ b = icon.get((x*4)+(y*width*4)+2);
+
+ icon_rgb.put((x*depth)+(y*width*depth), b); // blue
+ icon_rgb.put((x*depth)+(y*width*depth)+1, g); // green
+ icon_rgb.put((x*depth)+(y*width*depth)+2, r);
+ }
+ }
+ return icon_rgb;
+ }
+
+ private static ByteBuffer convertIconMask(ByteBuffer icon, int width, int height) {
+ ByteBuffer icon_mask = BufferUtils.createByteBuffer((icon.capacity()/4)/8);
+ int x;
+ int y;
+ byte a;
+
+ int depth = 4;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ a = icon.get((x*4)+(y*width*4)+3);
+
+ int mask_index = x + y*width;
+ int mask_byte_index = mask_index/8;
+ int mask_bit_index = mask_index%8;
+ byte bit = (((int)a) & 0xff) >= 127 ? (byte)1 : (byte)0;
+ byte new_byte = (byte)((icon_mask.get(mask_byte_index) | (bit<
+ * On Windows you should supply at least one 16x16 icon and one 32x32.
+ * Linux (and similar platforms) expect one 32x32 icon.
+ * Mac OS X should be supplied one 128x128 icon
+ *
+ * The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions necessary for the specific platform.
+ *
+ * @param icons Array of icons in RGBA mode
+ * @return number of icons used.
+ */
+ public int setIcon(ByteBuffer[] icons) {
+ lockAWT();
+ try {
+ incDisplay();
+ try {
+ for (int i=0;i 0) {
+ ByteBuffer icon_rgb = convertIcon(icons[i], dimension, dimension);
+ ByteBuffer icon_mask = convertIconMask(icons[i], dimension, dimension);
+ nSetWindowIcon(getDisplay(), getWindow(), icon_rgb, icon_rgb.capacity(), icon_mask, icon_mask.capacity(), dimension, dimension);
+ return 1;
+ }
+ }
+ return 0;
+ } finally {
+ decDisplay();
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to set display icon: " + e);
+ return 0;
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ private static native void nSetWindowIcon(long display, long window, ByteBuffer icon_rgb, int icon_rgb_size, ByteBuffer icon_mask, int icon_mask_size, int width, int height);
+
+ public int getWidth() {
+ return Display.getDisplayMode().getWidth();
+ }
+
+ public int getHeight() {
+ return Display.getDisplayMode().getHeight();
+ }
+
+ public boolean isInsideWindow() {
+ return true;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java
new file mode 100644
index 0000000..d702170
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: LinuxDisplayPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class LinuxDisplayPeerInfo extends LinuxPeerInfo {
+ LinuxDisplayPeerInfo(PixelFormat pixel_format) throws LWJGLException {
+ LinuxDisplay.lockAWT();
+ try {
+ GLContext.loadOpenGLLibrary();
+ try {
+ LinuxDisplay.incDisplay();
+ try {
+ initDefaultPeerInfo(LinuxDisplay.getDisplay(), LinuxDisplay.getDefaultScreen(), getHandle(), pixel_format);
+ } catch (LWJGLException e) {
+ LinuxDisplay.decDisplay();
+ throw e;
+ }
+ } catch (LWJGLException e) {
+ GLContext.unloadOpenGLLibrary();
+ throw e;
+ }
+ } finally {
+ LinuxDisplay.unlockAWT();
+ }
+ }
+ private static native void initDefaultPeerInfo(long display, int screen, ByteBuffer peer_info_handle, PixelFormat pixel_format) throws LWJGLException;
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ LinuxDisplay.lockAWT();
+ try {
+ initDrawable(LinuxDisplay.getWindow(), getHandle());
+ } finally {
+ LinuxDisplay.unlockAWT();
+ }
+ }
+ private static native void initDrawable(long window, ByteBuffer peer_info_handle);
+
+ protected void doUnlock() throws LWJGLException {
+ // NO-OP
+ }
+
+ public void destroy() {
+ super.destroy();
+ LinuxDisplay.lockAWT();
+ LinuxDisplay.decDisplay();
+ GLContext.unloadOpenGLLibrary();
+ LinuxDisplay.unlockAWT();
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxEvent.java b/src/java/org/lwjgl/opengl/LinuxEvent.java
new file mode 100644
index 0000000..a29b76e
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxEvent.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * Wrapper class for X11 events.
+ *
+ * @author elias_naur
+ * @version $Revision: 2286 $
+ * $Id: LinuxPeerInfo.java 2286 2006-03-23 19:32:21Z matzon $
+ */
+final class LinuxEvent {
+ public final static int FocusIn = 9;
+ public final static int FocusOut = 10;
+ public final static int KeyPress = 2;
+ public final static int KeyRelease = 3;
+ public final static int ButtonPress = 4;
+ public final static int ButtonRelease = 5;
+ public final static int MotionNotify = 6;
+ public final static int UnmapNotify = 18;
+ public final static int MapNotify = 19;
+ public final static int Expose = 12;
+ public final static int ClientMessage = 33;
+
+ private final ByteBuffer event_buffer;
+
+ LinuxEvent() {
+ this.event_buffer = createEventBuffer();
+ }
+ private static native ByteBuffer createEventBuffer();
+
+ public void copyFrom(LinuxEvent event) {
+ int pos = event_buffer.position();
+ int event_pos = event.event_buffer.position();
+ event_buffer.put(event.event_buffer);
+ event_buffer.position(pos);
+ event.event_buffer.position(event_pos);
+ }
+
+ public static native int getPending(long display);
+
+ public void sendEvent(long display, long window, boolean propagate, long event_mask) {
+ nSendEvent(event_buffer, display, window, propagate, event_mask);
+ }
+ private static native void nSendEvent(ByteBuffer event_buffer, long display, long window, boolean propagate, long event_mask);
+
+ public boolean filterEvent(long window) {
+ return nFilterEvent(event_buffer, window);
+ }
+ private static native boolean nFilterEvent(ByteBuffer event_buffer, long window);
+
+ public void nextEvent(long display) {
+ nNextEvent(display, event_buffer);
+ }
+ private static native void nNextEvent(long display, ByteBuffer event_buffer);
+
+ public int getType() {
+ return nGetType(event_buffer);
+ }
+ private static native int nGetType(ByteBuffer event_buffer);
+
+ public long getWindow() {
+ return nGetWindow(event_buffer);
+ }
+ private static native long nGetWindow(ByteBuffer event_buffer);
+
+ public void setWindow(long window) {
+ nSetWindow(event_buffer, window);
+ }
+ private static native void nSetWindow(ByteBuffer event_buffer, long window);
+
+ /* Focus methods */
+
+ public int getFocusMode() {
+ return nGetFocusMode(event_buffer);
+ }
+ private static native int nGetFocusMode(ByteBuffer event_buffer);
+
+ public int getFocusDetail() {
+ return nGetFocusDetail(event_buffer);
+ }
+ private static native int nGetFocusDetail(ByteBuffer event_buffer);
+
+ /* ClientMessage methods */
+
+ public long getClientMessageType() {
+ return nGetClientMessageType(event_buffer);
+ }
+ private static native long nGetClientMessageType(ByteBuffer event_buffer);
+
+ public int getClientData(int index) {
+ return nGetClientData(event_buffer, index);
+ }
+ private static native int nGetClientData(ByteBuffer event_buffer, int index);
+
+ public int getClientFormat() {
+ return nGetClientFormat(event_buffer);
+ }
+ private static native int nGetClientFormat(ByteBuffer event_buffer);
+
+ /* Button methods */
+
+ public long getButtonTime() {
+ return nGetButtonTime(event_buffer);
+ }
+ private static native long nGetButtonTime(ByteBuffer event_buffer);
+
+ public int getButtonState() {
+ return nGetButtonState(event_buffer);
+ }
+ private static native int nGetButtonState(ByteBuffer event_buffer);
+
+ public int getButtonType() {
+ return nGetButtonType(event_buffer);
+ }
+ private static native int nGetButtonType(ByteBuffer event_buffer);
+
+ public int getButtonButton() {
+ return nGetButtonButton(event_buffer);
+ }
+ private static native int nGetButtonButton(ByteBuffer event_buffer);
+
+ public long getButtonRoot() {
+ return nGetButtonRoot(event_buffer);
+ }
+ private static native long nGetButtonRoot(ByteBuffer event_buffer);
+
+ public int getButtonXRoot() {
+ return nGetButtonXRoot(event_buffer);
+ }
+ private static native int nGetButtonXRoot(ByteBuffer event_buffer);
+
+ public int getButtonYRoot() {
+ return nGetButtonYRoot(event_buffer);
+ }
+ private static native int nGetButtonYRoot(ByteBuffer event_buffer);
+
+ public int getButtonX() {
+ return nGetButtonX(event_buffer);
+ }
+ private static native int nGetButtonX(ByteBuffer event_buffer);
+
+ public int getButtonY() {
+ return nGetButtonY(event_buffer);
+ }
+ private static native int nGetButtonY(ByteBuffer event_buffer);
+
+ /* Key methods */
+
+ public long getKeyAddress() {
+ return nGetKeyAddress(event_buffer);
+ }
+ private static native long nGetKeyAddress(ByteBuffer event_buffer);
+
+ public long getKeyTime() {
+ return nGetKeyTime(event_buffer);
+ }
+ private static native int nGetKeyTime(ByteBuffer event_buffer);
+
+ public int getKeyType() {
+ return nGetKeyType(event_buffer);
+ }
+ private static native int nGetKeyType(ByteBuffer event_buffer);
+
+ public int getKeyKeyCode() {
+ return nGetKeyKeyCode(event_buffer);
+ }
+ private static native int nGetKeyKeyCode(ByteBuffer event_buffer);
+
+ public int getKeyState() {
+ return nGetKeyState(event_buffer);
+ }
+ private static native int nGetKeyState(ByteBuffer event_buffer);
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxKeyboard.java b/src/java/org/lwjgl/opengl/LinuxKeyboard.java
new file mode 100644
index 0000000..2777671
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxKeyboard.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * @author elias_naur
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.input.Keyboard;
+
+final class LinuxKeyboard {
+ private static final int LockMapIndex = 1;
+ private static final long NoSymbol = 0;
+ private static final long ShiftMask = 1 << 0;
+ private static final long LockMask = 1 << 1;
+ private static final int XLookupChars = 2;
+ private static final int XLookupBoth = 4;
+
+ private static final int KEYBOARD_BUFFER_SIZE = 50;
+
+ private final long xim;
+ private final long xic;
+
+ private final int numlock_mask;
+ private final int modeswitch_mask;
+ private final int caps_lock_mask;
+ private final int shift_lock_mask;
+
+ private final ByteBuffer compose_status;
+
+ private final byte[] key_down_buffer = new byte[Keyboard.KEYBOARD_SIZE];
+ private final EventQueue event_queue = new EventQueue(Keyboard.EVENT_SIZE);
+
+ private final ByteBuffer tmp_event = ByteBuffer.allocate(Keyboard.EVENT_SIZE);
+ private final int[] temp_translation_buffer = new int[KEYBOARD_BUFFER_SIZE];
+ private final ByteBuffer native_translation_buffer = BufferUtils.createByteBuffer(KEYBOARD_BUFFER_SIZE);
+ private final CharsetDecoder utf8_decoder = Charset.forName("UTF-8").newDecoder();
+ private final CharBuffer char_buffer = CharBuffer.allocate(KEYBOARD_BUFFER_SIZE);
+
+ // Deferred key released event, to detect key repeat
+ private boolean has_deferred_event;
+ private int deferred_keycode;
+ private int deferred_event_keycode;
+ private long deferred_nanos;
+ private byte deferred_key_state;
+
+ LinuxKeyboard(long display, long window) {
+ long modifier_map = getModifierMapping(display);
+ int tmp_numlock_mask = 0;
+ int tmp_modeswitch_mask = 0;
+ int tmp_caps_lock_mask = 0;
+ int tmp_shift_lock_mask = 0;
+ if (modifier_map != 0) {
+ int max_keypermod = getMaxKeyPerMod(modifier_map);
+ // Find modifier masks
+ int i, j;
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < max_keypermod; j++) {
+ int key_code = lookupModifierMap(modifier_map, i*max_keypermod + j);
+ int key_sym = (int)keycodeToKeySym(display, key_code);
+ int mask = 1 << i;
+ switch (key_sym) {
+ case LinuxKeycodes.XK_Num_Lock:
+ tmp_numlock_mask |= mask;
+ break;
+ case LinuxKeycodes.XK_Mode_switch:
+ tmp_modeswitch_mask |= mask;
+ break;
+ case LinuxKeycodes.XK_Caps_Lock:
+ if (i == LockMapIndex) {
+ tmp_caps_lock_mask = mask;
+ tmp_shift_lock_mask = 0;
+ }
+ break;
+ case LinuxKeycodes.XK_Shift_Lock:
+ if (i == LockMapIndex && tmp_caps_lock_mask == 0)
+ tmp_shift_lock_mask = mask;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ freeModifierMapping(modifier_map);
+ }
+ numlock_mask = tmp_numlock_mask;
+ modeswitch_mask = tmp_modeswitch_mask;
+ caps_lock_mask = tmp_caps_lock_mask;
+ shift_lock_mask = tmp_shift_lock_mask;
+ setDetectableKeyRepeat(display, true);
+ xim = openIM(display);
+ if (xim != 0) {
+ xic = createIC(xim, window);
+ if (xic != 0) {
+ setupIMEventMask(display, window, xic);
+ } else {
+ destroy(display);
+ }
+ } else {
+ xic = 0;
+ }
+ compose_status = allocateComposeStatus();
+ }
+ private static native long getModifierMapping(long display);
+ private static native void freeModifierMapping(long modifier_map);
+ private static native int getMaxKeyPerMod(long modifier_map);
+ private static native int lookupModifierMap(long modifier_map, int index);
+ private static native long keycodeToKeySym(long display, int key_code);
+
+ private static native long openIM(long display);
+ private static native long createIC(long xim, long window);
+ private static native void setupIMEventMask(long display, long window, long xic);
+ private static native ByteBuffer allocateComposeStatus();
+
+ private static void setDetectableKeyRepeat(long display, boolean enabled) {
+ boolean success = nSetDetectableKeyRepeat(display, enabled);
+ if (!success)
+ LWJGLUtil.log("Failed to set detectable key repeat to " + enabled);
+ }
+ private static native boolean nSetDetectableKeyRepeat(long display, boolean enabled);
+
+ public void destroy(long display) {
+ if (xic != 0)
+ destroyIC(xic);
+ if (xim != 0)
+ closeIM(xim);
+ setDetectableKeyRepeat(display, false);
+ }
+ private static native void destroyIC(long xic);
+ private static native void closeIM(long xim);
+
+ public void read(ByteBuffer buffer) {
+ flushDeferredEvent();
+ event_queue.copyEvents(buffer);
+ }
+
+ public void poll(ByteBuffer keyDownBuffer) {
+ flushDeferredEvent();
+ int old_position = keyDownBuffer.position();
+ keyDownBuffer.put(key_down_buffer);
+ keyDownBuffer.position(old_position);
+ }
+
+ private void putKeyboardEvent(int keycode, byte state, int ch, long nanos, boolean repeat) {
+ tmp_event.clear();
+ tmp_event.putInt(keycode).put(state).putInt(ch).putLong(nanos).put(repeat ? (byte)1 : (byte)0);
+ tmp_event.flip();
+ event_queue.putEvent(tmp_event);
+ }
+
+ private int lookupStringISO88591(long event_ptr, int[] translation_buffer) {
+ int i;
+
+ int num_chars = lookupString(event_ptr, native_translation_buffer, compose_status);
+ for (i = 0; i < num_chars; i++) {
+ translation_buffer[i] = ((int)native_translation_buffer.get(i)) & 0xff;
+ }
+ return num_chars;
+ }
+ private static native int lookupString(long event_ptr, ByteBuffer buffer, ByteBuffer compose_status);
+
+ private int lookupStringUnicode(long event_ptr, int[] translation_buffer) {
+ int status = utf8LookupString(xic, event_ptr, native_translation_buffer, native_translation_buffer.position(), native_translation_buffer.remaining());
+ if (status != XLookupChars && status != XLookupBoth)
+ return 0;
+ native_translation_buffer.flip();
+ utf8_decoder.decode(native_translation_buffer, char_buffer, true);
+ native_translation_buffer.compact();
+ char_buffer.flip();
+ int i = 0;
+ while (char_buffer.hasRemaining() && i < translation_buffer.length) {
+ translation_buffer[i++] = char_buffer.get();
+ }
+ char_buffer.compact();
+ return i;
+ }
+ private static native int utf8LookupString(long xic, long event_ptr, ByteBuffer buffer, int pos, int size);
+
+ private int lookupString(long event_ptr, int[] translation_buffer) {
+ if (xic != 0) {
+ return lookupStringUnicode(event_ptr, translation_buffer);
+ } else
+ return lookupStringISO88591(event_ptr, translation_buffer);
+ }
+
+ private void translateEvent(long event_ptr, int keycode, byte key_state, long nanos, boolean repeat) {
+ int num_chars, i;
+ int ch;
+
+ num_chars = lookupString(event_ptr, temp_translation_buffer);
+ if (num_chars > 0) {
+ ch = temp_translation_buffer[0];
+ putKeyboardEvent(keycode, key_state, ch, nanos, repeat);
+ for (i = 1; i < num_chars; i++) {
+ ch = temp_translation_buffer[i];
+ putKeyboardEvent(0, (byte)0, ch, nanos, repeat);
+ }
+ } else {
+ putKeyboardEvent(keycode, key_state, 0, nanos, repeat);
+ }
+ }
+
+ private static boolean isKeypadKeysym(long keysym) {
+ return (0xFF80 <= keysym && keysym <= 0xFFBD) ||
+ (0x11000000 <= keysym && keysym <= 0x1100FFFF);
+ }
+
+ private static boolean isNoSymbolOrVendorSpecific(long keysym) {
+ return keysym == NoSymbol || (keysym & (1 << 28)) != 0;
+ }
+
+ private static long getKeySym(long event_ptr, int group, int index) {
+ long keysym = lookupKeysym(event_ptr, group*2 + index);
+ if (isNoSymbolOrVendorSpecific(keysym) && index == 1) {
+ keysym = lookupKeysym(event_ptr, group*2 + 0);
+ }
+ if (isNoSymbolOrVendorSpecific(keysym) && group == 1)
+ keysym = getKeySym(event_ptr, 0, index);
+ return keysym;
+ }
+ private static native long lookupKeysym(long event_ptr, int index);
+ private static native long toUpper(long keysym);
+
+ private long mapEventToKeySym(long event_ptr, int event_state) {
+ int group;
+ long keysym;
+ if ((event_state & modeswitch_mask) != 0)
+ group = 1;
+ else
+ group = 0;
+ if ((event_state & numlock_mask) != 0 && isKeypadKeysym(keysym = getKeySym(event_ptr, group, 1))) {
+ if ((event_state & (ShiftMask | shift_lock_mask)) != 0) {
+ return getKeySym(event_ptr, group, 0);
+ } else {
+ return keysym;
+ }
+ } else if ((event_state & (ShiftMask | LockMask)) == 0) {
+ return getKeySym(event_ptr, group, 0);
+ } else if ((event_state & ShiftMask) == 0) {
+ keysym = getKeySym(event_ptr, group, 0);
+ if ((event_state & caps_lock_mask) != 0)
+ keysym = toUpper(keysym);
+ return keysym;
+ } else {
+ keysym = getKeySym(event_ptr, group, 1);
+ if ((event_state & caps_lock_mask) != 0)
+ keysym = toUpper(keysym);
+ return keysym;
+ }
+ }
+
+ private int getKeycode(long event_ptr, int event_state) {
+ long keysym = mapEventToKeySym(event_ptr, event_state);
+ int keycode = LinuxKeycodes.mapKeySymToLWJGLKeyCode(keysym);
+ if (keycode == Keyboard.KEY_NONE) {
+ // Try unshifted keysym mapping
+ keysym = lookupKeysym(event_ptr, 0);
+ keycode = LinuxKeycodes.mapKeySymToLWJGLKeyCode(keysym);
+ }
+ return keycode;
+ }
+
+ private byte getKeyState(int event_type) {
+ switch (event_type) {
+ case LinuxEvent.KeyPress:
+ return 1;
+ case LinuxEvent.KeyRelease:
+ return 0;
+ default:
+ throw new IllegalArgumentException("Unknown event_type: " + event_type);
+ }
+ }
+
+ private void handleKeyEvent(long event_ptr, long millis, int event_type, int event_keycode, int event_state) {
+ int keycode = getKeycode(event_ptr, event_state);
+ byte key_state = getKeyState(event_type);
+ boolean repeat = key_state == key_down_buffer[keycode];
+ key_down_buffer[keycode] = key_state;
+ long nanos = millis*1000000;
+ if (event_type == LinuxEvent.KeyPress) {
+ if (has_deferred_event) {
+ if (nanos == deferred_nanos && event_keycode == deferred_event_keycode) {
+ has_deferred_event = false;
+ repeat = true; // Repeated event
+ } else
+ flushDeferredEvent();
+ }
+ translateEvent(event_ptr, keycode, key_state, nanos, repeat);
+ } else {
+ flushDeferredEvent();
+ has_deferred_event = true;
+ deferred_keycode = keycode;
+ deferred_event_keycode = event_keycode;
+ deferred_nanos = nanos;
+ deferred_key_state = key_state;
+ }
+ }
+
+ private void flushDeferredEvent() {
+ if (has_deferred_event) {
+ putKeyboardEvent(deferred_keycode, deferred_key_state, 0, deferred_nanos, false);
+ has_deferred_event = false;
+ }
+ }
+
+ public boolean filterEvent(LinuxEvent event) {
+ switch (event.getType()) {
+ case LinuxEvent.KeyPress: /* Fall through */
+ case LinuxEvent.KeyRelease:
+ handleKeyEvent(event.getKeyAddress(), event.getKeyTime(), event.getKeyType(), event.getKeyKeyCode(), event.getKeyState());
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxKeycodes.java b/src/java/org/lwjgl/opengl/LinuxKeycodes.java
new file mode 100644
index 0000000..9542d08
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxKeycodes.java
@@ -0,0 +1,763 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * @author elias_naur
+ */
+
+import org.lwjgl.input.Keyboard;
+
+final class LinuxKeycodes {
+ public final static int XK_Kanji = 0xff21;
+
+ public final static int XK_ISO_Left_Tab = 0xfe20;
+
+ public final static int XK_dead_grave = 0xfe50;
+ public final static int XK_dead_acute = 0xfe51;
+ public final static int XK_dead_circumflex = 0xfe52;
+ public final static int XK_dead_tilde = 0xfe53;
+ public final static int XK_dead_macron = 0xfe54;
+ public final static int XK_dead_breve = 0xfe55;
+ public final static int XK_dead_abovedot = 0xfe56;
+ public final static int XK_dead_diaeresis = 0xfe57;
+ public final static int XK_dead_abovering = 0xfe58;
+ public final static int XK_dead_doubleacute = 0xfe59;
+ public final static int XK_dead_caron = 0xfe5a;
+ public final static int XK_dead_cedilla = 0xfe5b;
+ public final static int XK_dead_ogonek = 0xfe5c;
+ public final static int XK_dead_iota = 0xfe5d;
+ public final static int XK_dead_voiced_sound = 0xfe5e;
+ public final static int XK_dead_semivoiced_sound = 0xfe5f;
+ public final static int XK_dead_belowdot = 0xfe60;
+ public final static int XK_dead_hook = 0xfe61;
+ public final static int XK_dead_horn = 0xfe62;
+
+ public final static int XK_BackSpace = 0xff08;
+ public final static int XK_Tab = 0xff09;
+ public final static int XK_Linefeed = 0xff0a;
+ public final static int XK_Clear = 0xff0b;
+ public final static int XK_Return = 0xff0d;
+ public final static int XK_Pause = 0xff13;
+ public final static int XK_Scroll_Lock = 0xff14;
+ public final static int XK_Sys_Req = 0xff15;
+ public final static int XK_Escape = 0xff1b;
+ public final static int XK_Delete = 0xffff;
+
+ public final static int XK_Home = 0xff50;
+ public final static int XK_Left = 0xff51;
+ public final static int XK_Up = 0xff52;
+ public final static int XK_Right = 0xff53;
+ public final static int XK_Down = 0xff54;
+ public final static int XK_Prior = 0xff55;
+ public final static int XK_Page_Up = 0xff55;
+ public final static int XK_Next = 0xff56;
+ public final static int XK_Page_Down = 0xff56;
+ public final static int XK_End = 0xff57;
+ public final static int XK_Begin = 0xff58;
+
+
+/* Misc functions */
+
+ public final static int XK_Select = 0xff60;
+ public final static int XK_Print = 0xff61;
+ public final static int XK_Execute = 0xff62;
+ public final static int XK_Insert = 0xff63;
+ public final static int XK_Undo = 0xff65;
+ public final static int XK_Redo = 0xff66;
+ public final static int XK_Menu = 0xff67;
+ public final static int XK_Find = 0xff68;
+ public final static int XK_Cancel = 0xff69;
+ public final static int XK_Help = 0xff6a;
+ public final static int XK_Break = 0xff6b;
+ public final static int XK_Mode_switch = 0xff7e;
+ public final static int XK_script_switch = 0xff7e;
+ public final static int XK_Num_Lock = 0xff7f;
+
+/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */
+
+ public final static int XK_KP_Space = 0xff80;
+ public final static int XK_KP_Tab = 0xff89;
+ public final static int XK_KP_Enter = 0xff8d;
+ public final static int XK_KP_F1 = 0xff91;
+ public final static int XK_KP_F2 = 0xff92;
+ public final static int XK_KP_F3 = 0xff93;
+ public final static int XK_KP_F4 = 0xff94;
+ public final static int XK_KP_Home = 0xff95;
+ public final static int XK_KP_Left = 0xff96;
+ public final static int XK_KP_Up = 0xff97;
+ public final static int XK_KP_Right = 0xff98;
+ public final static int XK_KP_Down = 0xff99;
+ public final static int XK_KP_Prior = 0xff9a;
+ public final static int XK_KP_Page_Up = 0xff9a;
+ public final static int XK_KP_Next = 0xff9b;
+ public final static int XK_KP_Page_Down = 0xff9b;
+ public final static int XK_KP_End = 0xff9c;
+ public final static int XK_KP_Begin = 0xff9d;
+ public final static int XK_KP_Insert = 0xff9e;
+ public final static int XK_KP_Delete = 0xff9f;
+ public final static int XK_KP_Equal = 0xffbd;
+ public final static int XK_KP_Multiply = 0xffaa;
+ public final static int XK_KP_Add = 0xffab;
+ public final static int XK_KP_Separator = 0xffac;
+ public final static int XK_KP_Subtract = 0xffad;
+ public final static int XK_KP_Decimal = 0xffae;
+ public final static int XK_KP_Divide = 0xffaf;
+
+ public final static int XK_KP_0 = 0xffb0;
+ public final static int XK_KP_1 = 0xffb1;
+ public final static int XK_KP_2 = 0xffb2;
+ public final static int XK_KP_3 = 0xffb3;
+ public final static int XK_KP_4 = 0xffb4;
+ public final static int XK_KP_5 = 0xffb5;
+ public final static int XK_KP_6 = 0xffb6;
+ public final static int XK_KP_7 = 0xffb7;
+ public final static int XK_KP_8 = 0xffb8;
+ public final static int XK_KP_9 = 0xffb9;
+
+
+
+/*
+ * Auxilliary functions; note the duplicate definitions for left and right
+ * function keys; Sun keyboards and a few other manufactures have such
+ * function key groups on the left and/or right sides of the keyboard.
+ * We've not found a keyboard with more than 35 function keys total.
+ */
+
+ public final static int XK_F1 = 0xffbe;
+ public final static int XK_F2 = 0xffbf;
+ public final static int XK_F3 = 0xffc0;
+ public final static int XK_F4 = 0xffc1;
+ public final static int XK_F5 = 0xffc2;
+ public final static int XK_F6 = 0xffc3;
+ public final static int XK_F7 = 0xffc4;
+ public final static int XK_F8 = 0xffc5;
+ public final static int XK_F9 = 0xffc6;
+ public final static int XK_F10 = 0xffc7;
+ public final static int XK_F11 = 0xffc8;
+ public final static int XK_L1 = 0xffc8;
+ public final static int XK_F12 = 0xffc9;
+ public final static int XK_L2 = 0xffc9;
+ public final static int XK_F13 = 0xffca;
+ public final static int XK_L3 = 0xffca;
+ public final static int XK_F14 = 0xffcb;
+ public final static int XK_L4 = 0xffcb;
+ public final static int XK_F15 = 0xffcc;
+ public final static int XK_L5 = 0xffcc;
+ public final static int XK_F16 = 0xffcd;
+ public final static int XK_L6 = 0xffcd;
+ public final static int XK_F17 = 0xffce;
+ public final static int XK_L7 = 0xffce;
+ public final static int XK_F18 = 0xffcf;
+ public final static int XK_L8 = 0xffcf;
+ public final static int XK_F19 = 0xffd0;
+ public final static int XK_L9 = 0xffd0;
+ public final static int XK_F20 = 0xffd1;
+ public final static int XK_L10 = 0xffd1;
+ public final static int XK_F21 = 0xffd2;
+ public final static int XK_R1 = 0xffd2;
+ public final static int XK_F22 = 0xffd3;
+ public final static int XK_R2 = 0xffd3;
+ public final static int XK_F23 = 0xffd4;
+ public final static int XK_R3 = 0xffd4;
+ public final static int XK_F24 = 0xffd5;
+ public final static int XK_R4 = 0xffd5;
+ public final static int XK_F25 = 0xffd6;
+ public final static int XK_R5 = 0xffd6;
+ public final static int XK_F26 = 0xffd7;
+ public final static int XK_R6 = 0xffd7;
+ public final static int XK_F27 = 0xffd8;
+ public final static int XK_R7 = 0xffd8;
+ public final static int XK_F28 = 0xffd9;
+ public final static int XK_R8 = 0xffd9;
+ public final static int XK_F29 = 0xffda;
+ public final static int XK_R9 = 0xffda;
+ public final static int XK_F30 = 0xffdb;
+ public final static int XK_R10 = 0xffdb;
+ public final static int XK_F31 = 0xffdc;
+ public final static int XK_R11 = 0xffdc;
+ public final static int XK_F32 = 0xffdd;
+ public final static int XK_R12 = 0xffdd;
+ public final static int XK_F33 = 0xffde;
+ public final static int XK_R13 = 0xffde;
+ public final static int XK_F34 = 0xffdf;
+ public final static int XK_R14 = 0xffdf;
+ public final static int XK_F35 = 0xffe0;
+ public final static int XK_R15 = 0xffe0;
+
+/* Modifiers */
+
+ public final static int XK_Shift_L = 0xffe1;
+ public final static int XK_Shift_R = 0xffe2;
+ public final static int XK_Control_L = 0xffe3;
+ public final static int XK_Control_R = 0xffe4;
+ public final static int XK_Caps_Lock = 0xffe5;
+ public final static int XK_Shift_Lock = 0xffe6;
+
+ public final static int XK_Meta_L = 0xffe7;
+ public final static int XK_Meta_R = 0xffe8;
+ public final static int XK_Alt_L = 0xffe9;
+ public final static int XK_Alt_R = 0xffea;
+ public final static int XK_Super_L = 0xffeb;
+ public final static int XK_Super_R = 0xffec;
+ public final static int XK_Hyper_L = 0xffed;
+ public final static int XK_Hyper_R = 0xffee;
+ public final static int XK_space = 0x0020;
+ public final static int XK_exclam = 0x0021;
+ public final static int XK_quotedbl = 0x0022;
+ public final static int XK_numbersign = 0x0023;
+ public final static int XK_dollar = 0x0024;
+ public final static int XK_percent = 0x0025;
+ public final static int XK_ampersand = 0x0026;
+ public final static int XK_apostrophe = 0x0027;
+ public final static int XK_quoteright = 0x0027;
+ public final static int XK_parenleft = 0x0028;
+ public final static int XK_parenright = 0x0029;
+ public final static int XK_asterisk = 0x002a;
+ public final static int XK_plus = 0x002b;
+ public final static int XK_comma = 0x002c;
+ public final static int XK_minus = 0x002d;
+ public final static int XK_period = 0x002e;
+ public final static int XK_slash = 0x002f;
+
+ public final static int XK_0 = 0x0030;
+ public final static int XK_1 = 0x0031;
+ public final static int XK_2 = 0x0032;
+ public final static int XK_3 = 0x0033;
+ public final static int XK_4 = 0x0034;
+ public final static int XK_5 = 0x0035;
+ public final static int XK_6 = 0x0036;
+ public final static int XK_7 = 0x0037;
+ public final static int XK_8 = 0x0038;
+ public final static int XK_9 = 0x0039;
+ public final static int XK_colon = 0x003a;
+ public final static int XK_semicolon = 0x003b;
+ public final static int XK_less = 0x003c;
+ public final static int XK_equal = 0x003d;
+ public final static int XK_greater = 0x003e;
+ public final static int XK_question = 0x003f;
+ public final static int XK_at = 0x0040;
+ public final static int XK_A = 0x0041;
+ public final static int XK_B = 0x0042;
+ public final static int XK_C = 0x0043;
+ public final static int XK_D = 0x0044;
+ public final static int XK_E = 0x0045;
+ public final static int XK_F = 0x0046;
+ public final static int XK_G = 0x0047;
+ public final static int XK_H = 0x0048;
+ public final static int XK_I = 0x0049;
+ public final static int XK_J = 0x004a;
+ public final static int XK_K = 0x004b;
+ public final static int XK_L = 0x004c;
+ public final static int XK_M = 0x004d;
+ public final static int XK_N = 0x004e;
+ public final static int XK_O = 0x004f;
+ public final static int XK_P = 0x0050;
+ public final static int XK_Q = 0x0051;
+ public final static int XK_R = 0x0052;
+ public final static int XK_S = 0x0053;
+ public final static int XK_T = 0x0054;
+ public final static int XK_U = 0x0055;
+ public final static int XK_V = 0x0056;
+ public final static int XK_W = 0x0057;
+ public final static int XK_X = 0x0058;
+ public final static int XK_Y = 0x0059;
+ public final static int XK_Z = 0x005a;
+ public final static int XK_bracketleft = 0x005b;
+ public final static int XK_backslash = 0x005c;
+ public final static int XK_bracketright = 0x005d;
+ public final static int XK_asciicircum = 0x005e;
+ public final static int XK_underscore = 0x005f;
+ public final static int XK_grave = 0x0060;
+ public final static int XK_quoteleft = 0x0060;
+ public final static int XK_a = 0x0061;
+ public final static int XK_b = 0x0062;
+ public final static int XK_c = 0x0063;
+ public final static int XK_d = 0x0064;
+ public final static int XK_e = 0x0065;
+ public final static int XK_f = 0x0066;
+ public final static int XK_g = 0x0067;
+ public final static int XK_h = 0x0068;
+ public final static int XK_i = 0x0069;
+ public final static int XK_j = 0x006a;
+ public final static int XK_k = 0x006b;
+ public final static int XK_l = 0x006c;
+ public final static int XK_m = 0x006d;
+ public final static int XK_n = 0x006e;
+ public final static int XK_o = 0x006f;
+ public final static int XK_p = 0x0070;
+ public final static int XK_q = 0x0071;
+ public final static int XK_r = 0x0072;
+ public final static int XK_s = 0x0073;
+ public final static int XK_t = 0x0074;
+ public final static int XK_u = 0x0075;
+ public final static int XK_v = 0x0076;
+ public final static int XK_w = 0x0077;
+ public final static int XK_x = 0x0078;
+ public final static int XK_y = 0x0079;
+ public final static int XK_z = 0x007a;
+ public final static int XK_braceleft = 0x007b;
+ public final static int XK_bar = 0x007c;
+ public final static int XK_braceright = 0x007d;
+ public final static int XK_asciitilde = 0x007e;
+
+ public final static int XK_nobreakspace = 0x00a0;
+ public final static int XK_exclamdown = 0x00a1;
+ public final static int XK_cent = 0x00a2;
+ public final static int XK_sterling = 0x00a3;
+ public final static int XK_currency = 0x00a4;
+ public final static int XK_yen = 0x00a5;
+ public final static int XK_brokenbar = 0x00a6;
+ public final static int XK_section = 0x00a7;
+ public final static int XK_diaeresis = 0x00a8;
+ public final static int XK_copyright = 0x00a9;
+ public final static int XK_ordfeminine = 0x00aa;
+ public final static int XK_guillemotleft = 0x00ab;
+ public final static int XK_notsign = 0x00ac;
+ public final static int XK_hyphen = 0x00ad;
+ public final static int XK_registered = 0x00ae;
+ public final static int XK_macron = 0x00af;
+ public final static int XK_degree = 0x00b0;
+ public final static int XK_plusminus = 0x00b1;
+ public final static int XK_twosuperior = 0x00b2;
+ public final static int XK_threesuperior = 0x00b3;
+ public final static int XK_acute = 0x00b4;
+ public final static int XK_mu = 0x00b5;
+ public final static int XK_paragraph = 0x00b6;
+ public final static int XK_periodcentered = 0x00b7;
+ public final static int XK_cedilla = 0x00b8;
+ public final static int XK_onesuperior = 0x00b9;
+ public final static int XK_masculine = 0x00ba;
+ public final static int XK_guillemotright = 0x00bb;
+ public final static int XK_onequarter = 0x00bc;
+ public final static int XK_onehalf = 0x00bd;
+ public final static int XK_threequarters = 0x00be;
+ public final static int XK_questiondown = 0x00bf;
+ public final static int XK_Agrave = 0x00c0;
+ public final static int XK_Aacute = 0x00c1;
+ public final static int XK_Acircumflex = 0x00c2;
+ public final static int XK_Atilde = 0x00c3;
+ public final static int XK_Adiaeresis = 0x00c4;
+ public final static int XK_Aring = 0x00c5;
+ public final static int XK_AE = 0x00c6;
+ public final static int XK_Ccedilla = 0x00c7;
+ public final static int XK_Egrave = 0x00c8;
+ public final static int XK_Eacute = 0x00c9;
+ public final static int XK_Ecircumflex = 0x00ca;
+ public final static int XK_Ediaeresis = 0x00cb;
+ public final static int XK_Igrave = 0x00cc;
+ public final static int XK_Iacute = 0x00cd;
+ public final static int XK_Icircumflex = 0x00ce;
+ public final static int XK_Idiaeresis = 0x00cf;
+ public final static int XK_ETH = 0x00d0;
+ public final static int XK_Eth = 0x00d0;
+ public final static int XK_Ntilde = 0x00d1;
+ public final static int XK_Ograve = 0x00d2;
+ public final static int XK_Oacute = 0x00d3;
+ public final static int XK_Ocircumflex = 0x00d4;
+ public final static int XK_Otilde = 0x00d5;
+ public final static int XK_Odiaeresis = 0x00d6;
+ public final static int XK_multiply = 0x00d7;
+ public final static int XK_Oslash = 0x00d8;
+ public final static int XK_Ooblique = 0x00d8;
+ public final static int XK_Ugrave = 0x00d9;
+ public final static int XK_Uacute = 0x00da;
+ public final static int XK_Ucircumflex = 0x00db;
+ public final static int XK_Udiaeresis = 0x00dc;
+ public final static int XK_Yacute = 0x00dd;
+ public final static int XK_THORN = 0x00de;
+ public final static int XK_Thorn = 0x00de;
+ public final static int XK_ssharp = 0x00df;
+ public final static int XK_agrave = 0x00e0;
+ public final static int XK_aacute = 0x00e1;
+ public final static int XK_acircumflex = 0x00e2;
+ public final static int XK_atilde = 0x00e3;
+ public final static int XK_adiaeresis = 0x00e4;
+ public final static int XK_aring = 0x00e5;
+ public final static int XK_ae = 0x00e6;
+ public final static int XK_ccedilla = 0x00e7;
+ public final static int XK_egrave = 0x00e8;
+ public final static int XK_eacute = 0x00e9;
+ public final static int XK_ecircumflex = 0x00ea;
+ public final static int XK_ediaeresis = 0x00eb;
+ public final static int XK_igrave = 0x00ec;
+ public final static int XK_iacute = 0x00ed;
+ public final static int XK_icircumflex = 0x00ee;
+ public final static int XK_idiaeresis = 0x00ef;
+ public final static int XK_eth = 0x00f0;
+ public final static int XK_ntilde = 0x00f1;
+ public final static int XK_ograve = 0x00f2;
+ public final static int XK_oacute = 0x00f3;
+ public final static int XK_ocircumflex = 0x00f4;
+ public final static int XK_otilde = 0x00f5;
+ public final static int XK_odiaeresis = 0x00f6;
+ public final static int XK_division = 0x00f7;
+ public final static int XK_oslash = 0x00f8;
+ public final static int XK_ooblique = 0x00f8;
+ public final static int XK_ugrave = 0x00f9;
+ public final static int XK_uacute = 0x00fa;
+ public final static int XK_ucircumflex = 0x00fb;
+ public final static int XK_udiaeresis = 0x00fc;
+ public final static int XK_yacute = 0x00fd;
+ public final static int XK_thorn = 0x00fe;
+ public final static int XK_ydiaeresis = 0x00ff;
+
+ public final static int XK_ISO_Level3_Shift = 0xfe03;
+
+ public static int mapKeySymToLWJGLKeyCode(long keysym) {
+ switch ((int)keysym) {
+ case XK_BackSpace:
+ return Keyboard.KEY_BACK;
+ case XK_ISO_Left_Tab:
+ case XK_Tab:
+ return Keyboard.KEY_TAB;
+ case XK_Return:
+ return Keyboard.KEY_RETURN;
+ case XK_Pause:
+ return Keyboard.KEY_PAUSE;
+ case XK_Scroll_Lock:
+ return Keyboard.KEY_SCROLL;
+ case XK_Sys_Req:
+ return Keyboard.KEY_SYSRQ;
+ case XK_Escape:
+ return Keyboard.KEY_ESCAPE;
+ case XK_Delete:
+ return Keyboard.KEY_DELETE;
+
+ /* Japanese keyboard support */
+
+ case XK_Kanji:
+ return Keyboard.KEY_KANJI;
+
+ /* Cursor control & motion */
+
+ case XK_Home:
+ return Keyboard.KEY_HOME;
+ case XK_Left:
+ return Keyboard.KEY_LEFT;
+ case XK_Up:
+ return Keyboard.KEY_UP;
+ case XK_Right:
+ return Keyboard.KEY_RIGHT;
+ case XK_Down:
+ return Keyboard.KEY_DOWN;
+ case XK_Page_Up:
+ return Keyboard.KEY_PRIOR;
+ case XK_Page_Down:
+ return Keyboard.KEY_NEXT;
+ case XK_End:
+ return Keyboard.KEY_END;
+
+
+ /* Misc Functions */
+
+ case XK_Break:
+ return Keyboard.KEY_PAUSE;
+ case XK_Insert:
+ return Keyboard.KEY_INSERT;
+ case XK_Num_Lock:
+ return Keyboard.KEY_NUMLOCK;
+
+ /* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
+
+ case XK_KP_Space:
+ return Keyboard.KEY_SPACE;
+ case XK_KP_Tab:
+ return Keyboard.KEY_TAB;
+ case XK_KP_Enter:
+ return Keyboard.KEY_NUMPADENTER;
+ case XK_KP_F1:
+ return Keyboard.KEY_F1;
+ case XK_KP_F2:
+ return Keyboard.KEY_F2;
+ case XK_KP_F3:
+ return Keyboard.KEY_F3;
+ case XK_KP_F4:
+ return Keyboard.KEY_F4;
+ case XK_KP_Home:
+ return Keyboard.KEY_HOME;
+ case XK_KP_Left:
+ return Keyboard.KEY_LEFT;
+ case XK_KP_Up:
+ return Keyboard.KEY_UP;
+ case XK_KP_Right:
+ return Keyboard.KEY_RIGHT;
+ case XK_KP_Down:
+ return Keyboard.KEY_DOWN;
+ case XK_KP_Page_Up:
+ return Keyboard.KEY_PRIOR;
+ case XK_KP_Page_Down:
+ return Keyboard.KEY_NEXT;
+ case XK_KP_End:
+ return Keyboard.KEY_END;
+ case XK_KP_Insert:
+ return Keyboard.KEY_INSERT;
+ case XK_KP_Delete:
+ return Keyboard.KEY_DELETE;
+ case XK_KP_Equal:
+ return Keyboard.KEY_NUMPADEQUALS;
+ case XK_KP_Multiply:
+ return Keyboard.KEY_MULTIPLY;
+ case XK_KP_Add:
+ return Keyboard.KEY_ADD;
+ case XK_KP_Subtract:
+ return Keyboard.KEY_SUBTRACT;
+ case XK_KP_Decimal:
+ return Keyboard.KEY_DECIMAL;
+ case XK_KP_Divide:
+ return Keyboard.KEY_DIVIDE;
+
+ case XK_KP_0:
+ return Keyboard.KEY_NUMPAD0;
+ case XK_KP_1:
+ return Keyboard.KEY_NUMPAD1;
+ case XK_KP_2:
+ return Keyboard.KEY_NUMPAD2;
+ case XK_KP_3:
+ return Keyboard.KEY_NUMPAD3;
+ case XK_KP_4:
+ return Keyboard.KEY_NUMPAD4;
+ case XK_KP_5:
+ return Keyboard.KEY_NUMPAD5;
+ case XK_KP_6:
+ return Keyboard.KEY_NUMPAD6;
+ case XK_KP_7:
+ return Keyboard.KEY_NUMPAD7;
+ case XK_KP_8:
+ return Keyboard.KEY_NUMPAD8;
+ case XK_KP_9:
+ return Keyboard.KEY_NUMPAD9;
+
+ /*
+ * Auxilliary Functions; note the duplicate definitions for left and right
+ * function keys; Sun keyboards and a few other manufactures have such
+ * function key groups on the left and/or right sides of the keyboard.
+ * We've not found a keyboard with more than 35 function keys total.
+ */
+
+ case XK_F1:
+ return Keyboard.KEY_F1;
+ case XK_F2:
+ return Keyboard.KEY_F2;
+ case XK_F3:
+ return Keyboard.KEY_F3;
+ case XK_F4:
+ return Keyboard.KEY_F4;
+ case XK_F5:
+ return Keyboard.KEY_F5;
+ case XK_F6:
+ return Keyboard.KEY_F6;
+ case XK_F7:
+ return Keyboard.KEY_F7;
+ case XK_F8:
+ return Keyboard.KEY_F8;
+ case XK_F9:
+ return Keyboard.KEY_F9;
+ case XK_F10:
+ return Keyboard.KEY_F10;
+ case XK_F11:
+ return Keyboard.KEY_F11;
+ case XK_F12:
+ return Keyboard.KEY_F12;
+ case XK_F13:
+ return Keyboard.KEY_F13;
+ case XK_F14:
+ return Keyboard.KEY_F14;
+ case XK_F15:
+ return Keyboard.KEY_F15;
+
+ /* Modifiers */
+
+ case XK_Shift_L:
+ return Keyboard.KEY_LSHIFT;
+ case XK_Shift_R:
+ return Keyboard.KEY_RSHIFT;
+ case XK_Control_L:
+ return Keyboard.KEY_LCONTROL;
+ case XK_Control_R:
+ return Keyboard.KEY_RCONTROL;
+ case XK_Caps_Lock:
+ return Keyboard.KEY_CAPITAL;
+
+ case XK_Meta_L:
+ return Keyboard.KEY_LMENU;
+ case XK_ISO_Level3_Shift:
+ case XK_Meta_R:
+ return Keyboard.KEY_RMENU;
+ case XK_Alt_L:
+ return Keyboard.KEY_LMENU;
+ case XK_Alt_R:
+ return Keyboard.KEY_RMENU;
+
+ case XK_dead_grave:
+ return Keyboard.KEY_GRAVE;
+ case XK_dead_circumflex:
+ return Keyboard.KEY_CIRCUMFLEX;
+
+ /*
+ * Latin 1
+ * Byte 3 = 0
+ */
+ case XK_space:
+ return Keyboard.KEY_SPACE;
+ case XK_apostrophe:
+ return Keyboard.KEY_APOSTROPHE;
+ case XK_comma:
+ return Keyboard.KEY_COMMA;
+ case XK_minus:
+ return Keyboard.KEY_MINUS;
+ case XK_period:
+ return Keyboard.KEY_PERIOD;
+ case XK_slash:
+ return Keyboard.KEY_SLASH;
+ case XK_0:
+ return Keyboard.KEY_0;
+ case XK_1:
+ return Keyboard.KEY_1;
+ case XK_2:
+ return Keyboard.KEY_2;
+ case XK_3:
+ return Keyboard.KEY_3;
+ case XK_4:
+ return Keyboard.KEY_4;
+ case XK_5:
+ return Keyboard.KEY_5;
+ case XK_6:
+ return Keyboard.KEY_6;
+ case XK_7:
+ return Keyboard.KEY_7;
+ case XK_8:
+ return Keyboard.KEY_8;
+ case XK_9:
+ return Keyboard.KEY_9;
+ case XK_colon:
+ return Keyboard.KEY_COLON;
+ case XK_semicolon:
+ return Keyboard.KEY_SEMICOLON;
+ case XK_equal:
+ return Keyboard.KEY_EQUALS;
+ case XK_at:
+ return Keyboard.KEY_AT;
+ case XK_bracketleft:
+ return Keyboard.KEY_LBRACKET;
+ case XK_bracketright:
+ return Keyboard.KEY_RBRACKET;
+ case XK_asciicircum:
+ return Keyboard.KEY_CIRCUMFLEX;
+ case XK_underscore:
+ return Keyboard.KEY_UNDERLINE;
+ case XK_grave:
+ return Keyboard.KEY_GRAVE;
+ case XK_a:
+ case XK_A:
+ return Keyboard.KEY_A;
+ case XK_b:
+ case XK_B:
+ return Keyboard.KEY_B;
+ case XK_c:
+ case XK_C:
+ return Keyboard.KEY_C;
+ case XK_d:
+ case XK_D:
+ return Keyboard.KEY_D;
+ case XK_e:
+ case XK_E:
+ return Keyboard.KEY_E;
+ case XK_f:
+ case XK_F:
+ return Keyboard.KEY_F;
+ case XK_g:
+ case XK_G:
+ return Keyboard.KEY_G;
+ case XK_h:
+ case XK_H:
+ return Keyboard.KEY_H;
+ case XK_i:
+ case XK_I:
+ return Keyboard.KEY_I;
+ case XK_j:
+ case XK_J:
+ return Keyboard.KEY_J;
+ case XK_k:
+ case XK_K:
+ return Keyboard.KEY_K;
+ case XK_l:
+ case XK_L:
+ return Keyboard.KEY_L;
+ case XK_m:
+ case XK_M:
+ return Keyboard.KEY_M;
+ case XK_n:
+ case XK_N:
+ return Keyboard.KEY_N;
+ case XK_o:
+ case XK_O:
+ return Keyboard.KEY_O;
+ case XK_p:
+ case XK_P:
+ return Keyboard.KEY_P;
+ case XK_q:
+ case XK_Q:
+ return Keyboard.KEY_Q;
+ case XK_r:
+ case XK_R:
+ return Keyboard.KEY_R;
+ case XK_s:
+ case XK_S:
+ return Keyboard.KEY_S;
+ case XK_t:
+ case XK_T:
+ return Keyboard.KEY_T;
+ case XK_u:
+ case XK_U:
+ return Keyboard.KEY_U;
+ case XK_v:
+ case XK_V:
+ return Keyboard.KEY_V;
+ case XK_w:
+ case XK_W:
+ return Keyboard.KEY_W;
+ case XK_x:
+ case XK_X:
+ return Keyboard.KEY_X;
+ case XK_y:
+ case XK_Y:
+ return Keyboard.KEY_Y;
+ case XK_z:
+ case XK_Z:
+ return Keyboard.KEY_Z;
+ default:
+ return Keyboard.KEY_NONE;
+ }
+ }
+
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxMouse.java b/src/java/org/lwjgl/opengl/LinuxMouse.java
new file mode 100644
index 0000000..407d926
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxMouse.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * @author elias_naur
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Mouse;
+
+final class LinuxMouse {
+ private static final int NUM_BUTTONS = 3;
+ private static final int POINTER_WARP_BORDER = 10;
+ // scale the mouse wheel according to DirectInput
+ private static final int WHEEL_SCALE = 120;
+
+ /* X11 constants */
+ private final static int Button1 = 1;
+ private final static int Button2 = 2;
+ private final static int Button3 = 3;
+ private final static int Button4 = 4;
+ private final static int Button5 = 5;
+
+ private final static int ButtonPress = 4;
+ private final static int ButtonRelease = 5;
+
+ private final long display;
+ private final long window;
+ private final long input_window;
+ private final long warp_atom;
+ private final IntBuffer query_pointer_buffer = BufferUtils.createIntBuffer(4);
+ private final ByteBuffer event_buffer = ByteBuffer.allocate(Mouse.EVENT_SIZE);
+
+ private int last_x;
+ private int last_y;
+ private int accum_dx;
+ private int accum_dy;
+ private int accum_dz;
+ private byte[] buttons = new byte[NUM_BUTTONS];
+ private EventQueue event_queue;
+ private long last_event_nanos;
+
+ LinuxMouse(long display, long window, long input_window) throws LWJGLException {
+ this.display = display;
+ this.window = window;
+ this.input_window = input_window;
+ this.warp_atom = LinuxDisplay.nInternAtom(display, "_LWJGL", false);
+ reset(false, false);
+ }
+
+ private void reset(boolean grab, boolean warp_pointer) {
+ event_queue = new EventQueue(event_buffer.capacity());
+ accum_dx = accum_dy = 0;
+ long root_window = nQueryPointer(display, window, query_pointer_buffer);
+
+ int root_x = query_pointer_buffer.get(0);
+ int root_y = query_pointer_buffer.get(1);
+ int win_x = query_pointer_buffer.get(2);
+ int win_y = query_pointer_buffer.get(3);
+ // Pretend that the cursor never moved
+ last_x = win_x;
+ last_y = transformY(win_y);
+ doHandlePointerMotion(grab, warp_pointer, root_window, root_x, root_y, win_x, win_y, last_event_nanos);
+ }
+
+ public void read(ByteBuffer buffer) {
+ event_queue.copyEvents(buffer);
+ }
+
+ public void poll(boolean grab, IntBuffer coord_buffer, ByteBuffer buttons_buffer) {
+ if (grab) {
+ coord_buffer.put(0, accum_dx);
+ coord_buffer.put(1, accum_dy);
+ } else {
+ coord_buffer.put(0, last_x);
+ coord_buffer.put(1, last_y);
+ }
+ coord_buffer.put(2, accum_dz);
+ accum_dx = accum_dy = accum_dz = 0;
+ for (int i = 0; i < buttons.length; i++)
+ buttons_buffer.put(i, buttons[i]);
+ }
+
+ private void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) {
+ event_buffer.clear();
+ event_buffer.put(button).put(state).putInt(coord1).putInt(coord2).putInt(dz).putLong(nanos);
+ event_buffer.flip();
+ event_queue.putEvent(event_buffer);
+ last_event_nanos = nanos;
+ }
+
+ private void setCursorPos(boolean grab, int x, int y, long nanos) {
+ y = transformY(y);
+ int dx = x - last_x;
+ int dy = y - last_y;
+ if (dx != 0 || dy != 0) {
+ accum_dx += dx;
+ accum_dy += dy;
+ last_x = x;
+ last_y = y;
+ if (grab) {
+ putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos);
+ } else {
+ putMouseEventWithCoords((byte)-1, (byte)0, x, y, 0, nanos);
+ }
+ }
+ }
+
+ private void doWarpPointer(int center_x, int center_y) {
+ nSendWarpEvent(display, input_window, warp_atom, center_x, center_y);
+ nWarpCursor(display, window, center_x, center_y);
+ }
+ private static native void nSendWarpEvent(long display, long window, long warp_atom, int center_x, int center_y);
+
+ private void doHandlePointerMotion(boolean grab, boolean warp_pointer, long root_window, int root_x, int root_y, int win_x, int win_y, long nanos) {
+ setCursorPos(grab, win_x, win_y, nanos);
+ if (!warp_pointer)
+ return;
+ int root_window_height = nGetWindowHeight(display, root_window);
+ int root_window_width = nGetWindowWidth(display, root_window);
+ int window_height = nGetWindowHeight(display, window);
+ int window_width = nGetWindowWidth(display, window);
+
+ // find the window position in root coordinates
+ int win_left = root_x - win_x;
+ int win_top = root_y - win_y;
+ int win_right = win_left + window_width;
+ int win_bottom = win_top + window_height;
+ // cap the window position to the screen dimensions
+ int border_left = Math.max(0, win_left);
+ int border_top = Math.max(0, win_top);
+ int border_right = Math.min(root_window_width, win_right);
+ int border_bottom = Math.min(root_window_height, win_bottom);
+ // determine whether the cursor is outside the bounds
+ boolean outside_limits = root_x < border_left + POINTER_WARP_BORDER || root_y < border_top + POINTER_WARP_BORDER ||
+ root_x > border_right - POINTER_WARP_BORDER || root_y > border_bottom - POINTER_WARP_BORDER;
+ if (outside_limits) {
+ // Find the center of the limits in window coordinates
+ int center_x = (border_right - border_left)/2;
+ int center_y = (border_bottom - border_top)/2;
+ doWarpPointer(center_x, center_y);
+ }
+ }
+
+ public void changeGrabbed(boolean grab, boolean warp_pointer) {
+ reset(grab, warp_pointer);
+ }
+
+ public int getButtonCount() {
+ return buttons.length;
+ }
+
+ private int transformY(int y) {
+ return nGetWindowHeight(display, window) - 1 - y;
+ }
+ private static native int nGetWindowHeight(long display, long window);
+ private static native int nGetWindowWidth(long display, long window);
+
+ private static native long nQueryPointer(long display, long window, IntBuffer result);
+
+ public void setCursorPosition(int x, int y) {
+ nWarpCursor(display, window, x, transformY(y));
+ }
+ private static native void nWarpCursor(long display, long window, int x, int y);
+
+ private void handlePointerMotion(boolean grab, boolean warp_pointer, long millis, long root_window, int x_root, int y_root, int x, int y) {
+ doHandlePointerMotion(grab, warp_pointer, root_window, x_root, y_root, x, y, millis*1000000);
+ }
+
+ private void handleButton(boolean grab, int button, byte state, long nanos) {
+ byte button_num;
+ switch (button) {
+ case Button1:
+ button_num = (byte)0;
+ break;
+ case Button2:
+ button_num = (byte)2;
+ break;
+ case Button3:
+ button_num = (byte)1;
+ break;
+ default:
+ return;
+ }
+ buttons[button_num] = state;
+ putMouseEvent(grab, button_num, state, 0, nanos);
+ }
+
+ private void putMouseEvent(boolean grab, byte button, byte state, int dz, long nanos) {
+ if (grab)
+ putMouseEventWithCoords(button, state, 0, 0, dz, nanos);
+ else
+ putMouseEventWithCoords(button, state, last_x, last_y, dz, nanos);
+ }
+
+ private void handleButtonPress(boolean grab, byte button, long nanos) {
+ int delta = 0;
+ switch (button) {
+ case Button4:
+ delta = WHEEL_SCALE;
+ putMouseEvent(grab, (byte)-1, (byte)0, delta, nanos);
+ accum_dz += delta;
+ break;
+ case Button5:
+ delta = -WHEEL_SCALE;
+ putMouseEvent(grab, (byte)-1, (byte)0, delta, nanos);
+ accum_dz += delta;
+ break;
+ default:
+ handleButton(grab, button, (byte)1, nanos);
+ break;
+ }
+ }
+
+ private void handleButtonEvent(boolean grab, long millis, int type, byte button) {
+ long nanos = millis*1000000;
+ switch (type) {
+ case ButtonRelease:
+ handleButton(grab, button, (byte)0, nanos);
+ break;
+ case ButtonPress:
+ handleButtonPress(grab, button, nanos);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void resetCursor(int x, int y) {
+ last_x = x;
+ last_y = transformY(y);
+ }
+
+ private void handleWarpEvent(int x, int y) {
+ resetCursor(x, y);
+ }
+
+ public boolean filterEvent(boolean grab, boolean warp_pointer, LinuxEvent event) {
+ switch (event.getType()) {
+ case LinuxEvent.ClientMessage:
+ if (event.getClientMessageType() == warp_atom) {
+ handleWarpEvent(event.getClientData(0), event.getClientData(1));
+ return true;
+ }
+ break;
+ case LinuxEvent.ButtonPress: /* Fall through */
+ case LinuxEvent.ButtonRelease:
+ handleButtonEvent(grab, event.getButtonTime(), event.getButtonType(), (byte)event.getButtonButton());
+ return true;
+ case LinuxEvent.MotionNotify:
+ handlePointerMotion(grab, warp_pointer, event.getButtonTime(), event.getButtonRoot(), event.getButtonXRoot(), event.getButtonYRoot(), event.getButtonX(), event.getButtonY());
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxPbufferPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxPbufferPeerInfo.java
new file mode 100644
index 0000000..6e3e2b7
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxPbufferPeerInfo.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: LinuxPbufferPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class LinuxPbufferPeerInfo extends LinuxPeerInfo {
+ LinuxPbufferPeerInfo(int width, int height, PixelFormat pixel_format) throws LWJGLException {
+ LinuxDisplay.lockAWT();
+ try {
+ GLContext.loadOpenGLLibrary();
+ try {
+ LinuxDisplay.incDisplay();
+ try {
+ nInitHandle(LinuxDisplay.getDisplay(), LinuxDisplay.getDefaultScreen(), getHandle(), width, height, pixel_format);
+ } catch (LWJGLException e) {
+ LinuxDisplay.decDisplay();
+ throw e;
+ }
+ } catch (LWJGLException e) {
+ GLContext.unloadOpenGLLibrary();
+ throw e;
+ }
+ } finally {
+ LinuxDisplay.unlockAWT();
+ }
+ }
+ private static native void nInitHandle(long display, int screen, ByteBuffer handle, int width, int height, PixelFormat pixel_format) throws LWJGLException;
+
+ public void destroy() {
+ LinuxDisplay.lockAWT();
+ nDestroy(getHandle());
+ LinuxDisplay.decDisplay();
+ GLContext.unloadOpenGLLibrary();
+ LinuxDisplay.unlockAWT();
+ }
+ private static native void nDestroy(ByteBuffer handle);
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ // NO-OP
+ }
+
+ 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 0000000..2654f73
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/LinuxPeerInfo.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: LinuxPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+abstract class LinuxPeerInfo extends PeerInfo {
+ LinuxPeerInfo() {
+ super(createHandle());
+ }
+ private static native ByteBuffer createHandle();
+
+ public final long getDisplay() {
+ return nGetDisplay(getHandle());
+ }
+ private static native long nGetDisplay(ByteBuffer handle);
+
+ public final long getDrawable() {
+ return nGetDrawable(getHandle());
+ }
+ private static native long nGetDrawable(ByteBuffer handle);
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXAWTGLCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXAWTGLCanvasPeerInfo.java
new file mode 100644
index 0000000..4f09051
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXAWTGLCanvasPeerInfo.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.LWJGLException;
+
+import java.awt.Canvas;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: MacOSXAWTGLCanvasPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class MacOSXAWTGLCanvasPeerInfo extends MacOSXCanvasPeerInfo {
+ private final Canvas component;
+
+ MacOSXAWTGLCanvasPeerInfo(Canvas component, PixelFormat pixel_format, boolean support_pbuffer) throws LWJGLException {
+ super(pixel_format, support_pbuffer);
+ this.component = component;
+ }
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ initHandle(component);
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java b/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java
new file mode 100644
index 0000000..e040bfe
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2002-2008 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.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Canvas;
+
+import org.lwjgl.LWJGLException;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3002 $
+ * $Id: MacOSXCanvasImplementation.java 3002 2008-04-10 20:25:54Z elias_naur $
+ */
+final class MacOSXCanvasImplementation implements AWTCanvasImplementation {
+ public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
+ try {
+ return new MacOSXAWTGLCanvasPeerInfo(component, pixel_format, true);
+ } catch (LWJGLException e) {
+ return new MacOSXAWTGLCanvasPeerInfo(component, pixel_format, false);
+ }
+ }
+
+ /**
+ * 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 {
+ /*
+ * It seems like the best way is to simply return null
+ */
+ return null;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXCanvasListener.java b/src/java/org/lwjgl/opengl/MacOSXCanvasListener.java
new file mode 100644
index 0000000..c0111bf
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXCanvasListener.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2002-2008 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 AWT compatible Canvas for Mac OS X.
+ * @author elias_naur
+ */
+
+import java.awt.Canvas;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+
+final class MacOSXCanvasListener implements ComponentListener, HierarchyListener {
+ private final Canvas canvas;
+ private int width;
+ private int height;
+ private boolean context_update;
+
+ MacOSXCanvasListener(Canvas canvas) {
+ this.canvas = canvas;
+ canvas.addComponentListener(this);
+ canvas.addHierarchyListener(this);
+ setUpdate();
+ }
+
+ public void disableListeners() {
+ // Mac OS X applets will hang in Display.destroy() when parented when removing the listeners directly
+ java.awt.EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ canvas.removeComponentListener(MacOSXCanvasListener.this);
+ canvas.removeHierarchyListener(MacOSXCanvasListener.this);
+ }
+ });
+ }
+
+ public boolean syncShouldUpdateContext() {
+ boolean should_update;
+ synchronized ( this ) {
+ should_update = context_update;
+ context_update = false;
+ }
+ return should_update;
+ }
+
+ private synchronized void setUpdate() {
+ synchronized ( this ) {
+ width = canvas.getWidth();
+ height = canvas.getHeight();
+ context_update = true;
+ }
+ }
+
+ public int syncGetWidth() {
+ synchronized ( this ) {
+ return width;
+ }
+ }
+
+ public int syncGetHeight() {
+ synchronized ( this ) {
+ return height;
+ }
+ }
+
+ public void componentShown(ComponentEvent e) {
+ }
+
+ public void componentHidden(ComponentEvent e) {
+ }
+
+ public void componentResized(ComponentEvent e) {
+ setUpdate();
+ }
+
+ public void componentMoved(ComponentEvent e) {
+ setUpdate();
+ }
+
+ public void hierarchyChanged(HierarchyEvent e) {
+ setUpdate();
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java
new file mode 100644
index 0000000..95e8014
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2002-2008 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.awt.Canvas;
+import java.nio.ByteBuffer;
+
+import org.lwjgl.LWJGLException;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: MacOSXCanvasPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+abstract class MacOSXCanvasPeerInfo extends MacOSXPeerInfo {
+ private final AWTSurfaceLock awt_surface = new AWTSurfaceLock();
+
+ protected MacOSXCanvasPeerInfo(PixelFormat pixel_format, boolean support_pbuffer) throws LWJGLException {
+ super(pixel_format, true, true, support_pbuffer, true);
+ }
+
+ protected void initHandle(Canvas component) throws LWJGLException {
+ nInitHandle(awt_surface.lockAndGetHandle(component), getHandle());
+ }
+ private static native void nInitHandle(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/MacOSXContextAttribs.java b/src/java/org/lwjgl/opengl/MacOSXContextAttribs.java
new file mode 100644
index 0000000..01a5c5a
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXContextAttribs.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * An implementation of ContextAttribs for MacOS X.
+ *
+ * ---- WIP - No XGL_create_context has been defined for MacOS X yet ----
+ *
+ * @author spasi
+ */
+final class MacOSXContextAttribs implements ContextAttribsImplementation {
+
+ private static final int XGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
+ private static final int XGL_CONTEXT_MINOR_VERSION_ARB = 0x2092;
+ private static final int XGL_CONTEXT_LAYER_PLANE_ARB = 0x2093;
+ private static final int XGL_CONTEXT_FLAGS_ARB = 0x2094;
+ private static final int XGL_CONTEXT_PROFILE_MASK_ARB = 0x9126;
+
+ private static final int XGL_CONTEXT_DEBUG_BIT_ARB = 0x0001;
+ private static final int XGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002;
+
+ private static final int XGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
+ private static final int XGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
+
+ MacOSXContextAttribs() {
+ }
+
+ public int getMajorVersionAttrib() {
+ return XGL_CONTEXT_MAJOR_VERSION_ARB;
+ }
+
+ public int getMinorVersionAttrib() {
+ return XGL_CONTEXT_MINOR_VERSION_ARB;
+ }
+
+ public int getLayerPlaneAttrib() {
+ return XGL_CONTEXT_LAYER_PLANE_ARB;
+ }
+
+ public int getFlagsAttrib() {
+ return XGL_CONTEXT_FLAGS_ARB;
+ }
+
+ public int getDebugBit() {
+ return XGL_CONTEXT_DEBUG_BIT_ARB;
+ }
+
+ public int getForwardCompatibleBit() {
+ return XGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+ }
+
+ public int getProfileMaskAttrib() {
+ return XGL_CONTEXT_PROFILE_MASK_ARB;
+ }
+
+ public int getProfileCoreBit() {
+ return XGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+
+ public int getProfileCompatibilityBit() {
+ return XGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java b/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java
new file mode 100644
index 0000000..70ff274
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.LWJGLException;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+/**
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: MacOSXContextImplementation.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class MacOSXContextImplementation implements ContextImplementation {
+
+ public ByteBuffer create(PeerInfo peer_info, IntBuffer attribs, ByteBuffer shared_context_handle) throws LWJGLException {
+ ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ try {
+ return nCreate(peer_handle, attribs, shared_context_handle);
+ } finally {
+ peer_info.unlock();
+ }
+ }
+
+ private static native ByteBuffer nCreate(ByteBuffer peer_handle, IntBuffer attribs, ByteBuffer shared_context_handle) throws LWJGLException;
+
+ public void swapBuffers() throws LWJGLException {
+ Context current_context = Context.getCurrentContext();
+ if ( current_context == null )
+ throw new IllegalStateException("No context is current");
+ synchronized ( current_context ) {
+ nSwapBuffers(current_context.getHandle());
+ }
+ }
+
+ private static native void nSwapBuffers(ByteBuffer context_handle) throws LWJGLException;
+
+ public void update(ByteBuffer context_handle) {
+ nUpdate(context_handle);
+ }
+
+ private static native void nUpdate(ByteBuffer context_handle);
+
+ public void releaseCurrentContext() throws LWJGLException {
+ nReleaseCurrentContext();
+ }
+
+ private static native void nReleaseCurrentContext() throws LWJGLException;
+
+ public void releaseDrawable(ByteBuffer context_handle) throws LWJGLException {
+ clearDrawable(context_handle);
+ }
+
+ private static native void clearDrawable(ByteBuffer handle) throws LWJGLException;
+
+ static void resetView(PeerInfo peer_info, Context context) throws LWJGLException {
+ ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ try {
+ synchronized ( context ) {
+ clearDrawable(context.getHandle());
+ setView(peer_handle, context.getHandle());
+ }
+ } finally {
+ peer_info.unlock();
+ }
+ }
+
+ public void makeCurrent(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException {
+ ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ try {
+ setView(peer_handle, handle);
+ nMakeCurrent(handle);
+ } finally {
+ peer_info.unlock();
+ }
+ }
+
+ private static native void setView(ByteBuffer peer_handle, ByteBuffer context_handle) throws LWJGLException;
+
+ private static native void nMakeCurrent(ByteBuffer context_handle) throws LWJGLException;
+
+ public boolean isCurrent(ByteBuffer handle) throws LWJGLException {
+ boolean result = nIsCurrent(handle);
+ return result;
+ }
+
+ private static native boolean nIsCurrent(ByteBuffer context_handle) throws LWJGLException;
+
+ public void setSwapInterval(int value) {
+ Context current_context = Context.getCurrentContext();
+ synchronized ( current_context ) {
+ nSetSwapInterval(current_context.getHandle(), value);
+ }
+ }
+
+ private static native void nSetSwapInterval(ByteBuffer context_handle, int value);
+
+ public void destroy(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException {
+ nDestroy(handle);
+ }
+
+ private static native void nDestroy(ByteBuffer context_handle) throws LWJGLException;
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXDisplay.java b/src/java/org/lwjgl/opengl/MacOSXDisplay.java
new file mode 100644
index 0000000..bdbeb96
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXDisplay.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is the Display implementation interface. Display delegates
+ * to implementors of this interface. There is one DisplayImplementation
+ * for each supported platform.
+ * @author elias_naur
+ */
+
+import java.awt.Canvas;
+import java.awt.Cursor;
+import java.awt.Robot;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+
+import com.apple.eawt.Application;
+import com.apple.eawt.ApplicationAdapter;
+import com.apple.eawt.ApplicationEvent;
+
+final class MacOSXDisplay implements DisplayImplementation {
+ private static final int PBUFFER_HANDLE_SIZE = 24;
+ private static final int GAMMA_LENGTH = 256;
+
+ private MacOSXCanvasListener canvas_listener;
+ private MacOSXFrame frame;
+ private Canvas canvas;
+ private Robot robot;
+ private MacOSXMouseEventQueue mouse_queue;
+ private KeyboardEventQueue keyboard_queue;
+ private java.awt.DisplayMode requested_mode;
+
+ /* States */
+ private boolean close_requested;
+
+ MacOSXDisplay() {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ Application.getApplication().addApplicationListener(new ApplicationAdapter() {
+ public final void handleQuit(ApplicationEvent event) {
+ doHandleQuit();
+ }
+ });
+ return null;
+ }
+ });
+ } catch (Throwable e) {
+ /**
+ * In an applet environment, referencing com.apple.eawt.Application can fail with
+ * a native exception. So log any exceptions instead of re-throwing.
+ */
+ LWJGLUtil.log("Failed to register quit handler: " + e.getMessage());
+ }
+ }
+
+ public void createWindow(DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
+ boolean fullscreen = Display.isFullscreen();
+ hideUI(fullscreen);
+ close_requested = false;
+ try {
+ if (parent == null) {
+ frame = new MacOSXFrame(mode, requested_mode, fullscreen, x, y);
+ canvas = frame.getCanvas();
+ } else {
+ frame = null;
+ canvas = parent;
+ }
+ canvas_listener = new MacOSXCanvasListener(canvas);
+ robot = AWTUtil.createRobot(canvas);
+ } catch (LWJGLException e) {
+ destroyWindow();
+ throw e;
+ }
+ }
+
+ private void doHandleQuit() {
+ synchronized (this) {
+ close_requested = true;
+ }
+ }
+
+ public void destroyWindow() {
+ if (canvas_listener != null) {
+ canvas_listener.disableListeners();
+ canvas_listener = null;
+ }
+ if (frame != null) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ if (MacOSXFrame.getDevice().getFullScreenWindow() == frame)
+ MacOSXFrame.getDevice().setFullScreenWindow(null);
+ return null;
+ }
+ });
+ if (frame.isDisplayable())
+ frame.dispose();
+ frame = null;
+ }
+ hideUI(false);
+ }
+
+ public int getGammaRampLength() {
+ return GAMMA_LENGTH;
+ }
+
+ public native void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException;
+
+ public String getAdapter() {
+ return null;
+ }
+
+ public String getVersion() {
+ return null;
+ }
+
+ private boolean equals(java.awt.DisplayMode awt_mode, DisplayMode mode) {
+ return awt_mode.getWidth() == mode.getWidth() && awt_mode.getHeight() == mode.getHeight()
+ && awt_mode.getBitDepth() == mode.getBitsPerPixel() && awt_mode.getRefreshRate() == mode.getFrequency();
+ }
+
+ public void switchDisplayMode(DisplayMode mode) throws LWJGLException {
+ java.awt.DisplayMode[] awt_modes = MacOSXFrame.getDevice().getDisplayModes();
+ for (int i = 0; i < awt_modes.length; i++)
+ if (equals(awt_modes[i], mode)) {
+ requested_mode = awt_modes[i];
+ return;
+ }
+ throw new LWJGLException(mode + " is not supported");
+ }
+
+ public void resetDisplayMode() {
+ if (MacOSXFrame.getDevice().getFullScreenWindow() != null)
+ MacOSXFrame.getDevice().setFullScreenWindow(null);
+ requested_mode = null;
+ restoreGamma();
+ }
+
+ private native void restoreGamma();
+
+ private DisplayMode createLWJGLDisplayMode(java.awt.DisplayMode awt_mode) {
+ int bit_depth;
+ int refresh_rate;
+ int awt_bit_depth = awt_mode.getBitDepth();
+ int awt_refresh_rate = awt_mode.getRefreshRate();
+ if (awt_bit_depth != java.awt.DisplayMode.BIT_DEPTH_MULTI)
+ bit_depth = awt_bit_depth;
+ else
+ bit_depth = 32; // Assume the best bit depth
+ if (awt_refresh_rate != java.awt.DisplayMode.REFRESH_RATE_UNKNOWN)
+ refresh_rate = awt_refresh_rate;
+ else
+ refresh_rate = 0;
+ return new DisplayMode(awt_mode.getWidth(), awt_mode.getHeight(), bit_depth, refresh_rate);
+ }
+
+ public DisplayMode init() throws LWJGLException {
+ return createLWJGLDisplayMode(MacOSXFrame.getDevice().getDisplayMode());
+ }
+
+ 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++)
+ if (awt_modes[i].getBitDepth() >= 16)
+ modes.add(createLWJGLDisplayMode(awt_modes[i]));
+ DisplayMode[] mode_list = new DisplayMode[modes.size()];
+ modes.toArray(mode_list);
+ return mode_list;
+ }
+
+ public void setTitle(String title) {
+ if (frame != null)
+ frame.setTitle(title);
+ }
+
+ public boolean isCloseRequested() {
+ boolean result;
+ synchronized (this) {
+ result = close_requested || (frame != null && frame.syncIsCloseRequested());
+ close_requested = false;
+ }
+ return result;
+ }
+
+ public boolean isVisible() {
+ return frame == null || frame.syncIsVisible();
+ }
+
+ public boolean isActive() {
+ return canvas.isFocusOwner();
+ }
+
+ public Canvas getCanvas() {
+ return canvas;
+ }
+
+ public boolean isDirty() {
+ return frame != null && frame.getCanvas().syncIsDirty();
+ }
+
+ public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException {
+ try {
+ return new MacOSXDisplayPeerInfo(pixel_format, true);
+ } catch (LWJGLException e) {
+ return new MacOSXDisplayPeerInfo(pixel_format, false);
+ }
+ }
+
+ private final static IntBuffer current_viewport = BufferUtils.createIntBuffer(16);
+ public void update() {
+ boolean should_update = canvas_listener.syncShouldUpdateContext();
+ /*
+ * Workaround for the "white screen in fullscreen mode" problem
+ *
+ * Sometimes, switching from windowed mode to fullscreen or simply creating the Display
+ * in fullscreen mode will result in the context not being bound to the window correctly.
+ * The program runs fine, but the canvas background (white) is shown instead of the context
+ * front buffer.
+ *
+ * I've discovered that re-binding the context with another setView() won't fix the problem, while a
+ * clearDrawable() followed by a setView() does work. A straightforward workaround would be
+ * to simply run the combination at every update(). This is not sufficient, since the clearDrawable()
+ * call makes the the background appear shortly, causing visual artifacts.
+ * What we really need is a way to detect that a setView() failed, and then do the magic combo. I've not
+ * been able to find such a detection so alternatively I'm triggering the combo if the display is fullscreen
+ * (I've not seen the white screen problem in windowed mode) and if the canvas has gotten a paint message or
+ * if its update flag was set.
+ *
+ * My testing seems to indicate that the workaround works, since I've not seen the problem after the fix.
+ *
+ * - elias
+ */
+ if (Display.isFullscreen() && (frame != null && frame.getCanvas().syncCanvasPainted() || should_update)) {
+ try {
+ MacOSXContextImplementation.resetView(Display.getDrawable().getContext().getPeerInfo(), Display.getDrawable().getContext());
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to reset context: " + e);
+ }
+ }
+ if (should_update) {
+ Display.getDrawable().getContext().update();
+ /* This is necessary to make sure the context won't "forget" about the view size */
+ GL11.glGetInteger(GL11.GL_VIEWPORT, current_viewport);
+ GL11.glViewport(current_viewport.get(0), current_viewport.get(1), current_viewport.get(2), current_viewport.get(3));
+ }
+ if (frame != null && mouse_queue != null) {
+ if (frame.syncShouldReleaseCursor())
+ MacOSXMouseEventQueue.nGrabMouse(false);
+ if (frame.syncShouldWarpCursor())
+ mouse_queue.warpCursor();
+ }
+ }
+
+ /**
+ * This is an interface to the native Carbon call
+ * SetSystemUIMode. It is used to hide the dock in a way
+ * that will prevent AWT from shifting the fullscreen window
+ *
+ * The workaround is not necessary on 10.4, and since 10.4 shows
+ * instability problems calling SetSystemUIMode, we'll only call it
+ * when the OS version is 10.3 or lower.
+ */
+ private void hideUI(boolean hide) {
+ if (!LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 4))
+ nHideUI(hide);
+ }
+
+ private native void nHideUI(boolean hide);
+
+ public void reshape(int x, int y, int width, int height) {
+ if (frame != null)
+ frame.resize(x, y, width, height);
+ }
+
+ /* Mouse */
+ public boolean hasWheel() {
+ return AWTUtil.hasWheel();
+ }
+
+ public int getButtonCount() {
+ return AWTUtil.getButtonCount();
+ }
+
+ public void createMouse() throws LWJGLException {
+ this.mouse_queue = new MacOSXMouseEventQueue(canvas);
+ mouse_queue.register();
+ }
+
+ public void destroyMouse() {
+ if (mouse_queue != null) {
+ MacOSXMouseEventQueue.nGrabMouse(false);
+ mouse_queue.unregister();
+ }
+ this.mouse_queue = null;
+ }
+
+ public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons_buffer) {
+ mouse_queue.poll(coord_buffer, buttons_buffer);
+ }
+
+ public void readMouse(ByteBuffer buffer) {
+ mouse_queue.copyEvents(buffer);
+ }
+
+ public void grabMouse(boolean grab) {
+ mouse_queue.setGrabbed(grab);
+ }
+
+ public int getNativeCursorCapabilities() {
+ return AWTUtil.getNativeCursorCapabilities();
+ }
+
+ public void setCursorPosition(int x, int y) {
+ AWTUtil.setCursorPosition(canvas, robot, x, y);
+ }
+
+ public void setNativeCursor(Object handle) throws LWJGLException {
+ Cursor awt_cursor = (Cursor)handle;
+ if (frame != null)
+ frame.setCursor(awt_cursor);
+ }
+
+ public int getMinCursorSize() {
+ return AWTUtil.getMinCursorSize();
+ }
+
+ public int getMaxCursorSize() {
+ return AWTUtil.getMaxCursorSize();
+ }
+
+ /* Keyboard */
+ public void createKeyboard() throws LWJGLException {
+ this.keyboard_queue = new KeyboardEventQueue(canvas);
+ keyboard_queue.register();
+ }
+
+ public void destroyKeyboard() {
+ if (keyboard_queue != null)
+ keyboard_queue.unregister();
+ this.keyboard_queue = null;
+ }
+
+ public void pollKeyboard(ByteBuffer keyDownBuffer) {
+ keyboard_queue.poll(keyDownBuffer);
+ }
+
+ public void readKeyboard(ByteBuffer buffer) {
+ keyboard_queue.copyEvents(buffer);
+ }
+
+/* public int isStateKeySet(int key) {
+ int awt_key;
+ switch (key) {
+ case Keyboard.KEY_CAPITAL:
+ awt_key = KeyEvent.VK_CAPS_LOCK;
+ break;
+ case Keyboard.KEY_NUMLOCK:
+ awt_key = KeyEvent.VK_NUM_LOCK;
+ break;
+ case Keyboard.KEY_SYSRQ:
+ awt_key = KeyEvent.VK_SCROLL_LOCK;
+ break;
+ default:
+ return Keyboard.STATE_UNKNOWN;
+ }
+ try {
+ boolean state = Toolkit.getDefaultToolkit().getLockingKeyState(awt_key);
+ return state ? Keyboard.STATE_ON : Keyboard.STATE_OFF;
+ } catch (Exception e) {
+ LWJGLUtil.log("Failed to query key state: " + e);
+ return Keyboard.STATE_UNKNOWN;
+ }
+ }
+*/
+ /** Native cursor handles */
+ public Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
+ return AWTUtil.createCursor(width, height, xHotspot, yHotspot, numImages, images, delays);
+ }
+
+ public void destroyCursor(Object cursor_handle) {
+ }
+
+ public int getPbufferCapabilities() {
+ if (LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 3))
+ return Pbuffer.PBUFFER_SUPPORTED;
+ else
+ return 0;
+ }
+
+ public boolean isBufferLost(PeerInfo handle) {
+ return false;
+ }
+
+ public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format,
+ IntBuffer pixelFormatCaps,
+ IntBuffer pBufferAttribs) throws LWJGLException {
+ return new MacOSXPbufferPeerInfo(width, height, pixel_format);
+ }
+
+ public void setPbufferAttrib(PeerInfo handle, int attrib, int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void bindTexImageToPbuffer(PeerInfo handle, int buffer) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void releaseTexImageFromPbuffer(PeerInfo handle, int buffer) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Sets one or more icons for the Display.
+ *
+ * - On Windows you should supply at least one 16x16 icon and one 32x32.
+ * - Linux (and similar platforms) expect one 32x32 icon.
+ * - Mac OS X should be supplied one 128x128 icon
+ *
+ * The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions nescesarry for the specific platform.
+ *
+ * @param icons Array of icons in RGBA mode
+ * @return number of icons used.
+ */
+ public int setIcon(ByteBuffer[] icons) {
+/* int size = 0;
+ int biggest = -1;
+
+ for (int i=0;i size) {
+ biggest = i;
+ size = icons[i].remaining();
+ }
+ }
+
+ if (biggest == -1) {
+ return 0;
+ }
+
+ int width;
+ int height;
+
+ IntBuffer biggest_icon = icons[biggest].asIntBuffer();
+ int[] imageData = new int[biggest_icon.remaining()];
+ width = height = (int) Math.sqrt(imageData.length);
+ biggest_icon.get(imageData);
+
+ BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ img.setRGB(0, 0, width, height, imageData, 0, width);
+ frame.setIconImage(img);
+
+ return 1;*/
+ // Don't use any icon, since Mac OS X windows don't have window icons
+ return 0;
+ }
+
+ public int getWidth() {
+ return Display.getDisplayMode().getWidth();
+ }
+
+ public int getHeight() {
+ return Display.getDisplayMode().getHeight();
+ }
+
+ public boolean isInsideWindow() {
+ return true;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXDisplayPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXDisplayPeerInfo.java
new file mode 100644
index 0000000..853b520
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXDisplayPeerInfo.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2002-2008 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.awt.Canvas;
+
+import org.lwjgl.LWJGLException;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: MacOSXDisplayPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class MacOSXDisplayPeerInfo extends MacOSXCanvasPeerInfo {
+ private boolean locked = false;
+
+ MacOSXDisplayPeerInfo(PixelFormat pixel_format, boolean support_pbuffer) throws LWJGLException {
+ super(pixel_format, support_pbuffer);
+ }
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ if (locked)
+ throw new RuntimeException("Already locked");
+ Canvas canvas = ((MacOSXDisplay)Display.getImplementation()).getCanvas();
+ if (canvas != null) {
+ initHandle(canvas);
+ locked = true;
+ }
+ }
+
+ protected void doUnlock() throws LWJGLException {
+ if (locked) {
+ super.doUnlock();
+ locked = false;
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXFrame.java b/src/java/org/lwjgl/opengl/MacOSXFrame.java
new file mode 100644
index 0000000..2ca1c72
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXFrame.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is the Mac OS X AWT Frame. It contains thread safe
+ * methods to manipulateit from non-AWT threads
+ * @author elias_naur
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.lwjgl.LWJGLException;
+
+final class MacOSXFrame extends Frame implements WindowListener, ComponentListener {
+
+ private static final long serialVersionUID = -5823294716668988777L;
+
+ private final MacOSXGLCanvas canvas;
+ private boolean close_requested;
+
+ /* States */
+ private Rectangle bounds;
+ private boolean active;
+ private boolean minimized;
+ private boolean should_warp_cursor;
+ private boolean should_release_cursor;
+
+ MacOSXFrame(DisplayMode mode, final java.awt.DisplayMode requested_mode, boolean fullscreen, int x, int y) throws LWJGLException {
+ setResizable(false);
+ addWindowListener(this);
+ addComponentListener(this);
+ canvas = new MacOSXGLCanvas();
+ canvas.setFocusTraversalKeysEnabled(false);
+ add(canvas, BorderLayout.CENTER);
+ boolean undecorated = Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated");
+ setUndecorated(fullscreen || undecorated);
+ if ( fullscreen ) {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ getDevice().setFullScreenWindow(MacOSXFrame.this);
+ getDevice().setDisplayMode(requested_mode);
+ java.awt.DisplayMode real_mode = getDevice().getDisplayMode();
+ /** For some strange reason, the display mode is sometimes silently capped even though the mode is reported as supported */
+ if ( requested_mode.getWidth() != real_mode.getWidth() || requested_mode.getHeight() != real_mode.getHeight() ) {
+ getDevice().setFullScreenWindow(null);
+ if (isDisplayable())
+ dispose();
+ throw new LWJGLException("AWT capped mode: requested mode = " + requested_mode.getWidth() + "x" + requested_mode.getHeight() +
+ " but got " + real_mode.getWidth() + " " + real_mode.getHeight());
+ }
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw new LWJGLException(e);
+ }
+ }
+ pack();
+ resize(x, y, mode.getWidth(), mode.getHeight());
+ setVisible(true);
+ requestFocus();
+ canvas.requestFocus();
+ updateBounds();
+ }
+
+ public void resize(int x, int y, int width, int height) {
+ Insets insets = getInsets();
+ setBounds(x, y, width + insets.left + insets.right, height + insets.top + insets.bottom);
+ }
+
+ public Rectangle syncGetBounds() {
+ synchronized ( this ) {
+ return bounds;
+ }
+ }
+
+ public void componentShown(ComponentEvent e) {
+ }
+
+ public void componentHidden(ComponentEvent e) {
+ }
+
+ private void updateBounds() {
+ synchronized ( this ) {
+ bounds = getBounds();
+ }
+ }
+
+ public void componentResized(ComponentEvent e) {
+ updateBounds();
+ }
+
+ public void componentMoved(ComponentEvent e) {
+ updateBounds();
+ }
+
+ public static GraphicsDevice getDevice() {
+ GraphicsEnvironment g_env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice device = g_env.getDefaultScreenDevice();
+ return device;
+ }
+
+ public void windowIconified(WindowEvent e) {
+ synchronized ( this ) {
+ minimized = true;
+ }
+ }
+
+ public void windowDeiconified(WindowEvent e) {
+ synchronized ( this ) {
+ minimized = false;
+ }
+ }
+
+ public void windowOpened(WindowEvent e) {
+ }
+
+ public void windowClosed(WindowEvent e) {
+ }
+
+ public void windowClosing(WindowEvent e) {
+ synchronized ( this ) {
+ close_requested = true;
+ }
+ }
+
+ public void windowDeactivated(WindowEvent e) {
+ synchronized ( this ) {
+ active = false;
+ should_release_cursor = true;
+ should_warp_cursor = false;
+ }
+ }
+
+ public void windowActivated(WindowEvent e) {
+ synchronized ( this ) {
+ active = true;
+ should_warp_cursor = true;
+ should_release_cursor = false;
+ }
+ }
+
+ public boolean syncIsCloseRequested() {
+ boolean result;
+ synchronized ( this ) {
+ result = close_requested;
+ close_requested = false;
+ }
+ return result;
+ }
+
+ public boolean syncIsVisible() {
+ synchronized ( this ) {
+ return !minimized;
+ }
+ }
+
+ public boolean syncIsActive() {
+ synchronized ( this ) {
+ return active;
+ }
+ }
+
+ public MacOSXGLCanvas getCanvas() {
+ return canvas;
+ }
+
+ public boolean syncShouldReleaseCursor() {
+ boolean result;
+ synchronized ( this ) {
+ result = should_release_cursor;
+ should_release_cursor = false;
+ }
+ return result;
+ }
+
+ public boolean syncShouldWarpCursor() {
+ boolean result;
+ synchronized ( this ) {
+ result = should_warp_cursor;
+ should_warp_cursor = false;
+ }
+ return result;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXGLCanvas.java b/src/java/org/lwjgl/opengl/MacOSXGLCanvas.java
new file mode 100644
index 0000000..39f8050
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXGLCanvas.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2002-2008 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 AWT compatible Canvas for Mac OS X.
+ * @author elias_naur
+ */
+
+import java.awt.Canvas;
+import java.awt.Graphics;
+
+final class MacOSXGLCanvas extends Canvas {
+
+ private static final long serialVersionUID = 6916664741667434870L;
+
+ private boolean canvas_painted;
+ private boolean dirty;
+
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+ public void paint(Graphics g) {
+ synchronized ( this ) {
+ dirty = true;
+ canvas_painted = true;
+ }
+ }
+
+ public boolean syncCanvasPainted() {
+ boolean result;
+ synchronized (this) {
+ result = canvas_painted;
+ canvas_painted = false;
+ }
+ return result;
+ }
+
+ public boolean syncIsDirty() {
+ boolean result;
+ synchronized ( this ) {
+ result = dirty;
+ dirty = false;
+ }
+ return result;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java b/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java
new file mode 100644
index 0000000..c6b6195
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * An AWT implementation of a LWJGL compatible Mouse event queue.
+ * @author elias_naur
+ */
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+
+final class MacOSXMouseEventQueue extends MouseEventQueue {
+ private final IntBuffer delta_buffer = BufferUtils.createIntBuffer(2);
+
+ private boolean skip_event;
+ private static boolean is_grabbed;
+
+ MacOSXMouseEventQueue(Component component) {
+ super(component);
+ }
+
+ public void setGrabbed(boolean grab) {
+ super.setGrabbed(grab);
+ warpCursor();
+ grabMouse(grab);
+ }
+
+ private static synchronized void grabMouse(boolean grab) {
+ if (is_grabbed != grab) {
+ is_grabbed = grab;
+ if (!grab)
+ nGrabMouse(grab);
+ }
+ }
+
+ protected void resetCursorToCenter() {
+ super.resetCursorToCenter();
+ /* Clear accumulated deltas */
+ getMouseDeltas(delta_buffer);
+ }
+
+ protected void updateDeltas(long nanos) {
+ super.updateDeltas(nanos);
+ synchronized ( this ) {
+ getMouseDeltas(delta_buffer);
+ int dx = delta_buffer.get(0);
+ int dy = -delta_buffer.get(1);
+ if (skip_event) {
+ skip_event = false;
+ nGrabMouse(isGrabbed());
+ return;
+ }
+ if ( dx != 0 || dy != 0 ) {
+ putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos);
+ addDelta(dx, dy);
+ }
+ }
+ }
+
+ void warpCursor() {
+ synchronized (this) {
+ // If we're going to warp the cursor position, we'll skip the next event to avoid bogus delta values
+ skip_event = isGrabbed();
+ }
+/* if (isGrabbed()) {
+ Rectangle bounds = getComponent().getBounds();
+ Point location_on_screen = getComponent().getLocationOnScreen();
+ int x = location_on_screen.x + bounds.width/2;
+ int y = location_on_screen.y + bounds.height/2;
+ nWarpCursor(x, y);
+ }*/
+ }
+
+ private static native void getMouseDeltas(IntBuffer delta_buffer);
+
+ private static native void nWarpCursor(int x, int y);
+
+ static native void nGrabMouse(boolean grab);
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXPbufferPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXPbufferPeerInfo.java
new file mode 100644
index 0000000..574853d
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXPbufferPeerInfo.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: MacOSXPbufferPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class MacOSXPbufferPeerInfo extends MacOSXPeerInfo {
+ MacOSXPbufferPeerInfo(int width, int height, PixelFormat pixel_format) throws LWJGLException {
+ super(pixel_format, false, false, true, false);
+ nCreate(getHandle(), width, height);
+ }
+ private static native void nCreate(ByteBuffer handle, int width, int height) throws LWJGLException;
+
+ public void destroy() {
+ nDestroy(getHandle());
+ }
+ private static native void nDestroy(ByteBuffer handle);
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ // NO-OP
+ }
+
+ protected void doUnlock() throws LWJGLException {
+ // NO-OP
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXPeerInfo.java
new file mode 100644
index 0000000..f7e6ddb
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXPeerInfo.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2002-2008 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.LWJGLUtil;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: MacOSXPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+abstract class MacOSXPeerInfo extends PeerInfo {
+ MacOSXPeerInfo(PixelFormat pixel_format, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException {
+ super(createHandle());
+ if (pixel_format.isFloatingPoint() && !LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 4))
+ throw new LWJGLException("Floating point pixel format requested, but is not supported");
+ choosePixelFormat(pixel_format, use_display_bpp, support_window, support_pbuffer, double_buffered);
+ }
+ private static native ByteBuffer createHandle();
+
+ private void choosePixelFormat(PixelFormat pixel_format, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException {
+ nChoosePixelFormat(getHandle(), pixel_format, use_display_bpp, support_window, support_pbuffer, double_buffered);
+ }
+ private static native void nChoosePixelFormat(ByteBuffer peer_info_handle, PixelFormat pixel_format, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException;
+
+ public void destroy() {
+ nDestroy(getHandle());
+ }
+ private static native void nDestroy(ByteBuffer handle);
+}
diff --git a/src/java/org/lwjgl/opengl/MouseEventQueue.java b/src/java/org/lwjgl/opengl/MouseEventQueue.java
new file mode 100644
index 0000000..167eee3
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MouseEventQueue.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * An AWT implementation of a LWJGL compatible Mouse event queue.
+ * @author elias_naur
+ */
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.input.Mouse;
+
+class MouseEventQueue extends EventQueue implements MouseListener, MouseMotionListener, MouseWheelListener {
+ private static final int WHEEL_SCALE = 120;
+ public static final int NUM_BUTTONS = 3;
+
+ private final Component component;
+
+ private boolean grabbed;
+
+ /** The accumulated mouse deltas returned by poll() */
+ private int accum_dx;
+ private int accum_dy;
+ private int accum_dz;
+
+ /** The last mouse position */
+ private int last_x;
+ private int last_y;
+
+ /** Saved control key state for ctrl-click right button emulation */
+ private boolean saved_control_state;
+
+ /** Event scratch array */
+ private final ByteBuffer event = ByteBuffer.allocate(Mouse.EVENT_SIZE);
+
+ /** Buttons array */
+ private final byte[] buttons = new byte[NUM_BUTTONS];
+
+ MouseEventQueue(Component component) {
+ super(Mouse.EVENT_SIZE);
+ this.component = component;
+ }
+
+ public synchronized void register() {
+ resetCursorToCenter();
+ component.addMouseListener(this);
+ component.addMouseMotionListener(this);
+ component.addMouseWheelListener(this);
+ }
+
+ public synchronized void unregister() {
+ component.removeMouseListener(this);
+ component.removeMouseMotionListener(this);
+ component.removeMouseWheelListener(this);
+ }
+
+ protected Component getComponent() {
+ return component;
+ }
+
+ public synchronized void setGrabbed(boolean grabbed) {
+ this.grabbed = grabbed;
+ resetCursorToCenter();
+ }
+
+ public synchronized boolean isGrabbed() {
+ return grabbed;
+ }
+
+ private int transformY(int y) {
+ return component.getHeight() - 1 - y;
+ }
+
+ protected void resetCursorToCenter() {
+ clearEvents();
+ accum_dx = accum_dy = 0;
+ Point cursor_location = AWTUtil.getCursorPosition(component);
+ if (cursor_location != null) {
+ last_x = cursor_location.x;
+ last_y = cursor_location.y;
+ }
+ }
+
+ private void putMouseEvent(byte button, byte state, int dz, long nanos) {
+ if (grabbed)
+ putMouseEventWithCoords(button, state, 0, 0, dz, nanos);
+ else
+ putMouseEventWithCoords(button, state, last_x, last_y, dz, nanos);
+ }
+
+ protected void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) {
+ event.clear();
+ event.put(button).put(state).putInt(coord1).putInt(coord2).putInt(dz).putLong(nanos);
+ event.flip();
+ putEvent(event);
+ }
+
+ public synchronized void poll(IntBuffer coord_buffer, ByteBuffer buttons_buffer) {
+ if ( grabbed ) {
+ coord_buffer.put(0, accum_dx);
+ coord_buffer.put(1, accum_dy);
+ } else {
+ coord_buffer.put(0, last_x);
+ coord_buffer.put(1, last_y);
+ }
+ coord_buffer.put(2, accum_dz);
+ accum_dx = accum_dy = accum_dz = 0;
+ int old_position = buttons_buffer.position();
+ buttons_buffer.put(buttons, 0, buttons.length);
+ buttons_buffer.position(old_position);
+ }
+
+ private void setCursorPos(int x, int y, long nanos) {
+ y = transformY(y);
+ if ( grabbed )
+ return;
+ int dx = x - last_x;
+ int dy = y - last_y;
+ addDelta(dx, dy);
+ last_x = x;
+ last_y = y;
+ putMouseEventWithCoords((byte)-1, (byte)0, x, y, 0, nanos);
+ }
+
+ protected void addDelta(int dx, int dy) {
+ accum_dx += dx;
+ accum_dy += dy;
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ public void mouseExited(MouseEvent e) {
+ }
+
+ private void handleButton(MouseEvent e) {
+ byte state;
+ switch (e.getID()) {
+ case MouseEvent.MOUSE_PRESSED:
+ state = 1;
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ state = 0;
+ break;
+ default:
+ throw new IllegalArgumentException("Not a valid event ID: " + e.getID());
+ }
+ byte button;
+ switch (e.getButton()) {
+ case MouseEvent.NOBUTTON:
+ // Nothing to do, so return
+ return;
+ case MouseEvent.BUTTON1:
+ // Emulate right click if ctrl is down
+ if (state == 1)
+ saved_control_state = e.isControlDown();
+ if (saved_control_state) {
+ if (buttons[1] == state)
+ return; // ignore
+ button = (byte)1;
+ } else {
+ button = (byte)0;
+ }
+ break;
+ case MouseEvent.BUTTON2:
+ button = (byte)2;
+ break;
+ case MouseEvent.BUTTON3:
+ if (buttons[1] == state)
+ return; // ignore
+ button = (byte)1;
+ break;
+ default:
+ throw new IllegalArgumentException("Not a valid button: " + e.getButton());
+ }
+ setButton(button, state, e.getWhen()*1000000);
+ }
+
+ public synchronized void mousePressed(MouseEvent e) {
+ handleButton(e);
+ }
+
+ private void setButton(byte button, byte state, long nanos) {
+ buttons[button] = state;
+ putMouseEvent(button, state, 0, nanos);
+ }
+
+ public synchronized void mouseReleased(MouseEvent e) {
+ handleButton(e);
+ }
+
+ private void handleMotion(MouseEvent e) {
+ if (grabbed) {
+ updateDeltas(e.getWhen()*1000000);
+ } else {
+ setCursorPos(e.getX(), e.getY(), e.getWhen()*1000000);
+ }
+ }
+
+ public synchronized void mouseDragged(MouseEvent e) {
+ handleMotion(e);
+ }
+
+ public synchronized void mouseMoved(MouseEvent e) {
+ handleMotion(e);
+ }
+
+ private void handleWheel(int amount, long nanos) {
+ accum_dz += amount;
+ putMouseEvent((byte)-1, (byte)0, amount, nanos);
+ }
+
+ protected void updateDeltas(long nanos) {
+ }
+
+ public synchronized void mouseWheelMoved(MouseWheelEvent e) {
+ int wheel_amount = -e.getWheelRotation() * WHEEL_SCALE;
+ handleWheel(wheel_amount, e.getWhen()*1000000);
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/OpenGLException.java b/src/java/org/lwjgl/opengl/OpenGLException.java
new file mode 100644
index 0000000..aad05fa
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/OpenGLException.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ *
+ * Thrown by the debug build library of the LWJGL if any OpenGL operation causes an error.
+ *
+ * @author cix_foo
+ * @version $Revision: 2983 $
+ * $Id: OpenGLException.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class OpenGLException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ /** Constructor for OpenGLException. */
+ public OpenGLException(int gl_error_code) {
+ this(createErrorMessage(gl_error_code));
+ }
+
+ private static String createErrorMessage(int gl_error_code) {
+ String error_string = Util.translateGLErrorString(gl_error_code);
+ return error_string + " (" + gl_error_code + ")";
+ }
+
+ /** Constructor for OpenGLException. */
+ public OpenGLException() {
+ super();
+ }
+
+ /**
+ * Constructor for OpenGLException.
+ *
+ * @param message
+ */
+ public OpenGLException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor for OpenGLException.
+ *
+ * @param message
+ * @param cause
+ */
+ public OpenGLException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructor for OpenGLException.
+ *
+ * @param cause
+ */
+ public OpenGLException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/src/java/org/lwjgl/opengl/Pbuffer.java b/src/java/org/lwjgl/opengl/Pbuffer.java
new file mode 100644
index 0000000..066328e
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/Pbuffer.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2002-2008 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.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+
+/**
+ *
+ * Pbuffer encapsulates an OpenGL pbuffer.
+ *
+ *
+ * This class is thread-safe.
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: Pbuffer.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+public final class Pbuffer implements Drawable {
+ /**
+ * Indicates that Pbuffers can be created.
+ */
+ public static final int PBUFFER_SUPPORTED = 1 << 0;
+
+ /**
+ * Indicates that Pbuffers can be used as render-textures.
+ */
+ public static final int RENDER_TEXTURE_SUPPORTED = 1 << 1;
+
+ /**
+ * Indicates that Pbuffers can be used as non-power-of-two render-textures.
+ */
+ public static final int RENDER_TEXTURE_RECTANGLE_SUPPORTED = 1 << 2;
+
+ /**
+ * Indicates that Pbuffers can be used as depth render-textures.
+ */
+ public static final int RENDER_DEPTH_TEXTURE_SUPPORTED = 1 << 3;
+
+ /**
+ * The render-to-texture mipmap level attribute.
+ */
+ public static final int MIPMAP_LEVEL = RenderTexture.WGL_MIPMAP_LEVEL_ARB;
+
+ /**
+ * The render-to-texture cube map face attribute.
+ */
+ public static final int CUBE_MAP_FACE = RenderTexture.WGL_CUBE_MAP_FACE_ARB;
+
+ /**
+ * The render-to-texture cube map positive X face value.
+ */
+ public static final int TEXTURE_CUBE_MAP_POSITIVE_X = RenderTexture.WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
+
+ /**
+ * The render-to-texture cube map negative X face value.
+ */
+ public static final int TEXTURE_CUBE_MAP_NEGATIVE_X = RenderTexture.WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
+
+ /**
+ * The render-to-texture cube map positive Y face value.
+ */
+ public static final int TEXTURE_CUBE_MAP_POSITIVE_Y = RenderTexture.WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
+
+ /**
+ * The render-to-texture cube map negative Y face value.
+ */
+ public static final int TEXTURE_CUBE_MAP_NEGATIVE_Y = RenderTexture.WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
+
+ /**
+ * The render-to-texture cube map positive Z face value.
+ */
+ public static final int TEXTURE_CUBE_MAP_POSITIVE_Z = RenderTexture.WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
+
+ /**
+ * The render-to-texture cube map negative Z face value.
+ */
+ public static final int TEXTURE_CUBE_MAP_NEGATIVE_Z = RenderTexture.WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
+
+ /**
+ * The Pbuffer front left buffer.
+ */
+ public static final int FRONT_LEFT_BUFFER = RenderTexture.WGL_FRONT_LEFT_ARB;
+
+ /**
+ * The Pbuffer front right buffer.
+ */
+ public static final int FRONT_RIGHT_BUFFER = RenderTexture.WGL_FRONT_RIGHT_ARB;
+
+ /**
+ * The Pbuffer back left buffer.
+ */
+ public static final int BACK_LEFT_BUFFER = RenderTexture.WGL_BACK_LEFT_ARB;
+
+ /**
+ * The Pbuffer back right buffer.
+ */
+ public static final int BACK_RIGHT_BUFFER = RenderTexture.WGL_BACK_RIGHT_ARB;
+
+ /**
+ * The Pbuffer depth buffer.
+ */
+ public static final int DEPTH_BUFFER = RenderTexture.WGL_DEPTH_COMPONENT_NV;
+
+ /**
+ * Handle to the native GL rendering context
+ */
+ private final PeerInfo peer_info;
+
+ /**
+ * Width
+ */
+ private final int width;
+
+ /**
+ * Height
+ */
+ private final int height;
+
+ private final Context context;
+
+ private boolean destroyed;
+
+ static {
+ Sys.initialize();
+ }
+
+ /**
+ * Create an instance of a Pbuffer with a unique OpenGL context. The buffer is single-buffered.
+ *
+ * NOTE: The Pbuffer will have its own context that shares display lists and textures with shared_context
,
+ * or, if shared_context
is null
, the Display context if it is created. The Pbuffer
+ * will have its own OpenGL state. Therefore, state changes to a pbuffer will not be seen in the window context and vice versa.
+ *
+ *
+ * @param width Pbuffer width
+ * @param height Pbuffer height
+ * @param pixel_format Minimum Pbuffer context properties
+ * @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, Drawable shared_drawable) throws LWJGLException {
+ this(width, height, pixel_format, null, shared_drawable);
+ }
+
+ /**
+ * Create an instance of a Pbuffer with a unique OpenGL context. The buffer is single-buffered.
+ *
+ * NOTE: The Pbuffer will have its own context that shares display lists and textures with shared_context
,
+ * or, if shared_context
is null
, the Display context if it is created. The Pbuffer
+ * will have its own OpenGL state. Therefore, state changes to a pbuffer will not be seen in the window context and vice versa.
+ *
+ * The renderTexture parameter defines the necessary state for enabling render-to-texture. When this parameter is null,
+ * render-to-texture is not available. Before using render-to-texture, the Pbuffer capabilities must be queried to ensure that
+ * it is supported. Currently only windows platform can support this feature, so it is recommended that EXT_framebuffer_object
+ * or similar is used if available, for maximum portability.
+ *
+ *
+ * @param width Pbuffer width
+ * @param height Pbuffer height
+ * @param pixel_format Minimum Pbuffer context properties
+ * @param renderTexture
+ * @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, Drawable shared_drawable) throws LWJGLException {
+ this(width, height, pixel_format, renderTexture, shared_drawable, null);
+ }
+
+ /**
+ * Create an instance of a Pbuffer with a unique OpenGL context. The buffer is single-buffered.
+ *
+ * NOTE: The Pbuffer will have its own context that shares display lists and textures with shared_context
,
+ * or, if shared_context
is null
, the Display context if it is created. The Pbuffer
+ * will have its own OpenGL state. Therefore, state changes to a pbuffer will not be seen in the window context and vice versa.
+ *
+ * The renderTexture parameter defines the necessary state for enabling render-to-texture. When this parameter is null,
+ * render-to-texture is not available. Before using render-to-texture, the Pbuffer capabilities must be queried to ensure that
+ * it is supported. Currently only windows platform can support this feature, so it is recommended that EXT_framebuffer_object
+ * or similar is used if available, for maximum portability.
+ *
+ *
+ * @param width Pbuffer width
+ * @param height Pbuffer height
+ * @param pixel_format Minimum Pbuffer context properties
+ * @param renderTexture
+ * @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).
+ * @param attribs The ContextAttribs to use when creating the context. (optional, may be null)
+ */
+ public Pbuffer(int width, int height, PixelFormat pixel_format, RenderTexture renderTexture, Drawable shared_drawable, ContextAttribs attribs) throws LWJGLException {
+ if (pixel_format == null)
+ throw new NullPointerException("Pixel format must be non-null");
+ this.width = width;
+ this.height = height;
+ 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, attribs, shared_context);
+ }
+
+ private static PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, RenderTexture renderTexture) throws LWJGLException {
+ if ( renderTexture == null ) {
+ // Though null is a perfectly valid argument, Matrox Parhelia drivers expect
+ // a 0 terminated list, or else they crash. Supplying NULL or 0, should
+ // cause the drivers to use default settings
+ IntBuffer defaultAttribs = BufferUtils.createIntBuffer(1);
+ return Display.getImplementation().createPbuffer(width, height, pixel_format, null, defaultAttribs);
+ } 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");
+ }
+
+ /**
+ * Method to test for validity of the buffer. If this function returns true, the buffer contents is lost. The buffer can still
+ * be used, but the results are undefined. The application is expected to release the buffer if needed, destroy it and recreate
+ * a new buffer.
+ *
+ * @return true if the buffer is lost and destroyed, false if the buffer is valid.
+ */
+ 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 synchronized void makeCurrent() throws LWJGLException {
+ checkDestroyed();
+ context.makeCurrent();
+ }
+
+ /**
+ * Gets the Pbuffer capabilities.
+ *
+ * @return a bitmask of Pbuffer capabilities.
+ */
+ public static int getCapabilities() {
+ return Display.getImplementation().getPbufferCapabilities();
+ }
+
+ /**
+ * 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 synchronized void destroy() {
+ if (destroyed)
+ return;
+ try {
+ context.forceDestroy();
+ peer_info.destroy();
+ destroyed = true;
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while destroying pbuffer: " + e);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // ------------------------------- Render-to-Texture Methods -------------------------------
+ // -----------------------------------------------------------------------------------------
+
+ /**
+ * Sets a render-to-texture attribute.
+ *
+ * The attrib parameter can be one of MIPMAP_LEVEL and CUBE_MAP_FACE. When the attrib parameter is CUBE_MAP_FACE then the value
+ * parameter can be on of the following:
+ *
+ * TEXTURE_CUBE_MAP_POSITIVE_X TEXTURE_CUBE_MAP_NEGATIVE_X TEXTURE_CUBE_MAP_POSITIVE_Y TEXTURE_CUBE_MAP_NEGATIVE_Y
+ * TEXTURE_CUBE_MAP_POSITIVE_Z TEXTURE_CUBE_MAP_NEGATIVE_Z
+ *
+ * @param attrib
+ * @param value
+ */
+ public synchronized void setAttrib(int attrib, int value) {
+ checkDestroyed();
+ Display.getImplementation().setPbufferAttrib(peer_info, attrib, value);
+ }
+
+ /**
+ * Binds the currently bound texture to the buffer specified. The buffer can be one of the following:
+ *
+ * FRONT_LEFT_BUFFER FRONT_RIGHT_BUFFER BACK_LEFT_BUFFER BACK_RIGHT_BUFFER DEPTH_BUFFER
+ *
+ * @param buffer
+ */
+ public synchronized void bindTexImage(int buffer) {
+ checkDestroyed();
+ Display.getImplementation().bindTexImageToPbuffer(peer_info, buffer);
+ }
+
+ /**
+ * Releases the currently bound texture from the buffer specified.
+ *
+ * @param buffer
+ */
+ public synchronized void releaseTexImage(int buffer) {
+ checkDestroyed();
+ Display.getImplementation().releaseTexImageFromPbuffer(peer_info, buffer);
+ }
+
+ /**
+ * @return Returns the height.
+ */
+ public synchronized int getHeight() {
+ checkDestroyed();
+ return height;
+ }
+
+ /**
+ * @return Returns the width.
+ */
+ 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 0000000..26c9563
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/PeerInfo.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2002-2008 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.LWJGLUtil;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: PeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+abstract class PeerInfo {
+ private final ByteBuffer handle;
+ private Thread locking_thread; // Thread that has locked this PeerInfo
+ private int lock_count;
+
+ protected PeerInfo(ByteBuffer handle) {
+ this.handle = handle;
+ }
+
+ private void lockAndInitHandle() throws LWJGLException {
+ doLockAndInitHandle();
+ }
+
+ public synchronized final void unlock() throws LWJGLException {
+ if (lock_count <= 0)
+ throw new IllegalStateException("PeerInfo not locked!");
+ if (Thread.currentThread() != locking_thread)
+ throw new IllegalStateException("PeerInfo already locked by " + locking_thread);
+ lock_count--;
+ if (lock_count == 0) {
+ doUnlock();
+ locking_thread = null;
+ notify();
+ }
+ }
+
+ protected abstract void doLockAndInitHandle() throws LWJGLException;
+ protected abstract void doUnlock() throws LWJGLException;
+
+ public synchronized final ByteBuffer lockAndGetHandle() throws LWJGLException {
+ Thread this_thread = Thread.currentThread();
+ while (locking_thread != null && locking_thread != this_thread) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ LWJGLUtil.log("Interrupted while waiting for PeerInfo lock: " + e);
+ }
+ }
+ if (lock_count == 0) {
+ locking_thread = this_thread;
+ doLockAndInitHandle();
+ }
+ lock_count++;
+ return getHandle();
+ }
+
+ protected final ByteBuffer getHandle() {
+ return handle;
+ }
+
+ public void destroy() {
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/PixelFormat.java b/src/java/org/lwjgl/opengl/PixelFormat.java
new file mode 100644
index 0000000..a94233f
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/PixelFormat.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This class describes pixel format properties for an OpenGL context. Instances
+ * of this class is used as arguments to Display.create(), Pbuffer.create() and
+ * AWTGLCanvas, to indicate minimum required properties.
+ *
+ * Instants of this class are immutable. An example of the expected way to set
+ * the PixelFormat property values is the following:
+ * PixelFormat pf = new PixelFormat().withDepth(24).withSamples(4).withSRGB(true);
+ *
+ * WARNING: Some pixel formats are known to cause troubles on certain buggy drivers.
+ * Example: Under Windows, specifying samples != 0 will enable the ARB
+ * pixel format selection path, which could trigger a crash.
+ *
+ * @author elias_naur@sourceforge.net
+ * @version $Revision: 3116 $
+ */
+
+public final class PixelFormat {
+
+ /**
+ * The number of bits per pixel, exluding alpha.
+ * This parameter is ignored in Display.create().
+ */
+ private int bpp;
+ /** The number of alpha bits. */
+ private int alpha;
+ /** The number of depth buffer bits */
+ private int depth;
+ /** The number of stencil bits */
+ private int stencil;
+ /**
+ * The number of samples to use in anti-aliasing.
+ * 0 means that anti-aliasing is disabled.
+ */
+ private int samples;
+ /** The number of auxiliary buffers */
+ private int num_aux_buffers;
+ /** The number of bits per pixel in the accumulation buffer */
+ private int accum_bpp;
+ /** The number of alpha bits in the accumulation buffer */
+ private int accum_alpha;
+ /** Whether this format requires a stereo buffer */
+ private boolean stereo;
+ /** Whether this format specifies a floating point format */
+ private boolean floating_point;
+ /** Whether this format specifies a packed floating point format (32 bit unsigned - R11F_G11F_B10F) */
+ private boolean floating_point_packed;
+ /** Whether this format specifies an sRGB format */
+ private boolean sRGB;
+
+ /**
+ * Default pixel format is minimum 8 bits depth, and no alpha
+ * nor stencil requirements.
+ */
+ public PixelFormat() {
+ this(0, 8, 0);
+ }
+
+ public PixelFormat(int alpha, int depth, int stencil) {
+ this(alpha, depth, stencil, 0);
+ }
+
+ public PixelFormat(int alpha, int depth, int stencil, int samples) {
+ this(0, alpha, depth, stencil, samples);
+ }
+
+ public PixelFormat(int bpp, int alpha, int depth, int stencil, int samples) {
+ this(bpp, alpha, depth, stencil, samples, 0, 0, 0, false);
+ }
+
+ public PixelFormat(int bpp, int alpha, int depth, int stencil, int samples, int num_aux_buffers, int accum_bpp, int accum_alpha, boolean stereo) {
+ this(bpp, alpha, depth, stencil, samples, num_aux_buffers, accum_bpp, accum_alpha, stereo, false);
+ }
+
+ public PixelFormat(int bpp, int alpha, int depth, int stencil, int samples, int num_aux_buffers, int accum_bpp, int accum_alpha, boolean stereo, boolean floating_point) {
+ this.bpp = bpp;
+ this.alpha = alpha;
+ this.depth = depth;
+ this.stencil = stencil;
+
+ this.samples = samples;
+
+ this.num_aux_buffers = num_aux_buffers;
+
+ this.accum_bpp = accum_bpp;
+ this.accum_alpha = accum_alpha;
+
+ this.stereo = stereo;
+
+ this.floating_point = floating_point;
+ this.floating_point_packed = false;
+ this.sRGB = false;
+ }
+
+ private PixelFormat(final PixelFormat pf) {
+ this.bpp = pf.bpp;
+ this.alpha = pf.alpha;
+ this.depth = pf.depth;
+ this.stencil = pf.stencil;
+
+ this.samples = pf.samples;
+
+ this.num_aux_buffers = pf.num_aux_buffers;
+
+ this.accum_bpp = pf.accum_bpp;
+ this.accum_alpha = pf.accum_alpha;
+
+ this.stereo = pf.stereo;
+
+ this.floating_point = pf.floating_point;
+ this.floating_point_packed = pf.floating_point_packed;
+ this.sRGB = pf.sRGB;
+ }
+
+ public int getBitsPerPixel() {
+ return bpp;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new bits per pixel value.
+ *
+ * @param bpp the new bits per pixel value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withBitsPerPixel(final int bpp) {
+ if ( bpp < 0 )
+ throw new IllegalArgumentException("Invalid number of bits per pixel specified: " + bpp);
+
+ final PixelFormat pf = new PixelFormat(this);
+ pf.bpp = bpp;
+ return pf;
+ }
+
+ public int getAlphaBits() {
+ return alpha;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new alpha bits value.
+ *
+ * @param alpha the new alpha bits value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withAlphaBits(final int alpha) {
+ if ( alpha < 0 )
+ throw new IllegalArgumentException("Invalid number of alpha bits specified: " + alpha);
+
+ final PixelFormat pf = new PixelFormat(this);
+ pf.alpha = alpha;
+ return pf;
+ }
+
+ public int getDepthBits() {
+ return depth;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new depth bits value.
+ *
+ * @param depth the new depth bits value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withDepthBits(final int depth) {
+ if ( depth < 0 )
+ throw new IllegalArgumentException("Invalid number of depth bits specified: " + depth);
+
+ final PixelFormat pf = new PixelFormat(this);
+ pf.depth = depth;
+ return pf;
+ }
+
+ public int getStencilBits() {
+ return stencil;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new stencil bits value.
+ *
+ * @param stencil the new stencil bits value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withStencilBits(final int stencil) {
+ if ( stencil < 0 )
+ throw new IllegalArgumentException("Invalid number of stencil bits specified: " + stencil);
+
+ final PixelFormat pf = new PixelFormat(this);
+ pf.stencil = stencil;
+ return pf;
+ }
+
+ public int getSamples() {
+ return samples;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new samples value.
+ *
+ * @param samples the new samples value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withSamples(final int samples) {
+ if ( samples < 0 )
+ throw new IllegalArgumentException("Invalid number of samples specified: " + samples);
+
+ final PixelFormat pf = new PixelFormat(this);
+ pf.samples = samples;
+ return pf;
+ }
+
+ public int getAuxBuffers() {
+ return num_aux_buffers;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new auxiliary buffers value.
+ *
+ * @param num_aux_buffers the new auxiliary buffers value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withAuxBuffers(final int num_aux_buffers) {
+ if ( num_aux_buffers < 0 )
+ throw new IllegalArgumentException("Invalid number of auxiliary buffers specified: " + num_aux_buffers);
+
+ final PixelFormat pf = new PixelFormat(this);
+ pf.num_aux_buffers = num_aux_buffers;
+ return pf;
+ }
+
+ public int getAccumulationBitsPerPixel() {
+ return accum_bpp;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new bits per pixel in the accumulation buffer value.
+ *
+ * @param accum_bpp the new bits per pixel in the accumulation buffer value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withAccumulationBitsPerPixel(final int accum_bpp) {
+ if ( accum_bpp < 0 )
+ throw new IllegalArgumentException("Invalid number of bits per pixel in the accumulation buffer specified: " + accum_bpp);
+
+ final PixelFormat pf = new PixelFormat(this);
+ pf.accum_bpp = accum_bpp;
+ return pf;
+ }
+
+ public int getAccumulationAlpha() {
+ return accum_alpha;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new alpha bits in the accumulation buffer value.
+ *
+ * @param accum_alpha the new alpha bits in the accumulation buffer value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withAccumulationAlpha(final int accum_alpha) {
+ if ( accum_alpha < 0 )
+ throw new IllegalArgumentException("Invalid number of alpha bits in the accumulation buffer specified: " + accum_alpha);
+
+ final PixelFormat pf = new PixelFormat(this);
+ pf.accum_alpha = accum_alpha;
+ return pf;
+ }
+
+ public boolean isStereo() {
+ return stereo;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new stereo value.
+ *
+ * @param stereo the new stereo value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withStereo(final boolean stereo) {
+ final PixelFormat pf = new PixelFormat(this);
+ pf.stereo = stereo;
+ return pf;
+ }
+
+ public boolean isFloatingPoint() {
+ return floating_point;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new floating point value.
+ * If floating_point is true, floating_point_packed will be reset to false.
+ *
+ * @param floating_point the new floating point value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withFloatingPoint(final boolean floating_point) {
+ final PixelFormat pf = new PixelFormat(this);
+ pf.floating_point = floating_point;
+ if ( floating_point )
+ pf.floating_point_packed = false;
+ return pf;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new packed floating point value.
+ * If floating_point_packed is true, floating_point will be reset to false.
+ *
+ * @param floating_point_packed the new packed floating point value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withFloatingPointPacked(final boolean floating_point_packed) {
+ final PixelFormat pf = new PixelFormat(this);
+ pf.floating_point_packed = floating_point_packed;
+ if ( floating_point_packed )
+ pf.floating_point = false;
+ return pf;
+ }
+
+ public boolean isSRGB() {
+ return sRGB;
+ }
+
+ /**
+ * Returns a new PixelFormat object with the same properties as this PixelFormat and the new sRGB value.
+ *
+ * @param sRGB the new floating point value.
+ *
+ * @return the new PixelFormat
+ */
+ public PixelFormat withSRGB(final boolean sRGB) {
+ final PixelFormat pf = new PixelFormat(this);
+ pf.sRGB = sRGB;
+ return pf;
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/PointerWrapper.java b/src/java/org/lwjgl/opengl/PointerWrapper.java
new file mode 100644
index 0000000..123c602
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/PointerWrapper.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/** @author spasi */
+public interface PointerWrapper {
+
+ long getPointer();
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/ReferencesStack.java b/src/java/org/lwjgl/opengl/ReferencesStack.java
new file mode 100644
index 0000000..69936a8
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/ReferencesStack.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+class ReferencesStack {
+ private References[] references_stack;
+ private int stack_pos;
+
+ public References getReferences() {
+ return references_stack[stack_pos];
+ }
+
+ public void pushState() {
+ int pos = ++stack_pos;
+ if (pos == references_stack.length) {
+ growStack();
+ }
+ references_stack[pos].copy(references_stack[pos - 1], GL11.GL_ALL_CLIENT_ATTRIB_BITS);
+ }
+
+ public References popState(int mask) {
+ References result = references_stack[stack_pos--];
+
+ references_stack[stack_pos].copy(result, ~mask);
+ result.clear();
+
+ return result;
+ }
+
+ private void growStack() {
+ References[] new_references_stack = new References[references_stack.length + 1];
+ System.arraycopy(references_stack, 0, new_references_stack, 0, references_stack.length);
+ references_stack = new_references_stack;
+ references_stack[references_stack.length - 1] = new References(GLContext.getCapabilities());
+ }
+
+ ReferencesStack() {
+ ContextCapabilities caps = GLContext.getCapabilities();
+ references_stack = new References[1];
+ stack_pos = 0;
+ for (int i = 0; i < references_stack.length; i++)
+ references_stack[i] = new References(caps);
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/RenderTexture.java b/src/java/org/lwjgl/opengl/RenderTexture.java
new file mode 100644
index 0000000..008439d
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/RenderTexture.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2002-2008 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.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+
+/** This class represents the state necessary for render-to-texture. */
+public final class RenderTexture {
+
+ // ----------------------------------------------------------------------------------
+ // ----------------------------- WGL_ARB_render_texture -----------------------------
+ // ----------------------------------------------------------------------------------
+
+ /*
+ Accepted by the parameter of wglGetPixelFormatAttribivARB,
+ wglGetPixelFormatAttribfvARB, and the and
+ parameters of wglChoosePixelFormatARB:
+ */
+ private static final int WGL_BIND_TO_TEXTURE_RGB_ARB = 0x2070;
+ private static final int WGL_BIND_TO_TEXTURE_RGBA_ARB = 0x2071;
+
+ /*
+ Accepted by the parameter of wglCreatePbufferARB and
+ by the parameter of wglQueryPbufferARB:
+ */
+ private static final int WGL_TEXTURE_FORMAT_ARB = 0x2072;
+ private static final int WGL_TEXTURE_TARGET_ARB = 0x2073;
+ private static final int WGL_MIPMAP_TEXTURE_ARB = 0x2074;
+
+ /*
+ Accepted as a value in the parameter of
+ wglCreatePbufferARB and returned in the value parameter of
+ wglQueryPbufferARB when is WGL_TEXTURE_FORMAT_ARB:
+ */
+ private static final int WGL_TEXTURE_RGB_ARB = 0x2075;
+ private static final int WGL_TEXTURE_RGBA_ARB = 0x2076;
+
+ /*
+ Accepted as a value in the parameter of
+ wglCreatePbufferARB and returned in the value parameter of
+ wglQueryPbufferARB when is WGL_TEXTURE_TARGET_ARB:
+ */
+ private static final int WGL_TEXTURE_CUBE_MAP_ARB = 0x2078;
+ private static final int WGL_TEXTURE_1D_ARB = 0x2079;
+ private static final int WGL_TEXTURE_2D_ARB = 0x207A;
+ private static final int WGL_NO_TEXTURE_ARB = 0x2077;
+
+ /*
+ Accepted by the parameter of wglSetPbufferAttribARB and
+ by the parameter of wglQueryPbufferARB:
+ */
+ static final int WGL_MIPMAP_LEVEL_ARB = 0x207B;
+ static final int WGL_CUBE_MAP_FACE_ARB = 0x207C;
+
+ /*
+ Accepted as a value in the parameter of
+ wglSetPbufferAttribARB and returned in the value parameter of
+ wglQueryPbufferARB when is WGL_CUBE_MAP_FACE_ARB:
+ */
+ static final int WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB = 0x207D;
+ static final int WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB = 0x207E;
+ static final int WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB = 0x207F;
+ static final int WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB = 0x2080;
+ static final int WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB = 0x2081;
+ static final int WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB = 0x2082;
+
+ /*
+ Accepted by the parameter of wglBindTexImageARB and
+ wglReleaseTexImageARB:
+ */
+ static final int WGL_FRONT_LEFT_ARB = 0x2083;
+ static final int WGL_FRONT_RIGHT_ARB = 0x2084;
+ static final int WGL_BACK_LEFT_ARB = 0x2085;
+ static final int WGL_BACK_RIGHT_ARB = 0x2086;
+
+ /*
+ private static final int WGL_AUX0_ARB = 0x2087;
+ private static final int WGL_AUX1_ARB = 0x2088;
+ private static final int WGL_AUX2_ARB = 0x2089;
+ private static final int WGL_AUX3_ARB = 0x208A;
+ private static final int WGL_AUX4_ARB = 0x208B;
+ private static final int WGL_AUX5_ARB = 0x208C;
+ private static final int WGL_AUX6_ARB = 0x208D;
+ private static final int WGL_AUX7_ARB = 0x208E;
+ private static final int WGL_AUX8_ARB = 0x208F;
+ private static final int WGL_AUX9_ARB = 0x2090;
+ */
+
+ // -------------------------------------------------------------------------------------------
+ // ----------------------------- WGL_NV_render_texture_rectangle -----------------------------
+ // -------------------------------------------------------------------------------------------
+
+ /*
+ Accepted by the parameter of wglGetPixelFormatAttribivARB,
+ wglGetPixelFormatAttribfvARB, and the and
+ parameters of wglChoosePixelFormatARB:
+ */
+ private static final int WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV = 0x20A0;
+ private static final int WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV = 0x20A1;
+
+ /*
+ Accepted as a value in the parameter of wglCreatePbufferARB
+ and returned in the value parameter of wglQueryPbufferARB when
+ is WGL_TEXTURE_TARGET_ARB:
+ */
+ private static final int WGL_TEXTURE_RECTANGLE_NV = 0x20A2;
+
+ // ---------------------------------------------------------------------------------------
+ // ----------------------------- WGL_NV_render_depth_texture -----------------------------
+ // ---------------------------------------------------------------------------------------
+
+ /*
+ Accepted by the parameter of wglGetPixelFormatAttribivARB,
+ wglGetPixelFormatAttribfvARB, and the and
+ parameters of wglChoosePixelFormatARB:
+ */
+ private static final int WGL_BIND_TO_TEXTURE_DEPTH_NV = 0x20A3;
+ private static final int WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV = 0x20A4;
+
+ /*
+ Accepted by the parameter of wglCreatePbufferARB and
+ by the parameter of wglQueryPbufferARB:
+ */
+ private static final int WGL_DEPTH_TEXTURE_FORMAT_NV = 0x20A5;
+
+ /*
+ Accepted as a value in the parameter of wglCreatePbufferARB
+ and returned in the value parameter of wglQueryPbufferARB when
+ is WGL_DEPTH_TEXTURE_FORMAT_NV:
+ */
+ private static final int WGL_TEXTURE_DEPTH_COMPONENT_NV = 0x20A6;
+
+ /*
+ Accepted by the parameter of wglBindTexImageARB:
+ */
+ static final int WGL_DEPTH_COMPONENT_NV = 0x20A7;
+
+ /** The TEXTURE_1D target. */
+ public static final int RENDER_TEXTURE_1D = WGL_TEXTURE_1D_ARB;
+
+ /** The TEXTURE_2D target. */
+ public static final int RENDER_TEXTURE_2D = WGL_TEXTURE_2D_ARB;
+
+ /** The TEXTURE_RECTANGLE target. */
+ public static final int RENDER_TEXTURE_RECTANGLE = WGL_TEXTURE_RECTANGLE_NV;
+
+ /** The TEXTURE_CUBE_MAP target. */
+ public static final int RENDER_TEXTURE_CUBE_MAP = WGL_TEXTURE_CUBE_MAP_ARB;
+
+ IntBuffer pixelFormatCaps;
+ IntBuffer pBufferAttribs;
+
+ /**
+ * Creates a RenderTexture object for enabling render-to-texture on a P-buffer.
+ *
+ * NOTE: Only one of useRGB and useRGBA can be true at the same time.
+ *
+ * NOTE: useRGB(A) and useDepth can be true at the same time, thus allowing two different render textures.
+ *
+ * NOTE: The target parameter can be one of the following:
+ *
+ * RENDER_TEXTURE_1D RENDER_TEXTURE_2D RENDER_TEXTURE_RECTANGLE RENDER_TEXTURE_CUBE_MAP
+ *
+ * @param useRGB - When true the P-buffer can be used as an RGB render texture.
+ * @param useRGBA - When true the P-buffer can be used as an RGBA render texture.
+ * @param useDepth - When true the P-buffer can be used as a depth render texture.
+ * @param isRectangle - When true rectangle textures will be allowed on the P-buffer.
+ * @param target - The texture target of the render texture.
+ * @param mipmaps - How many mipmap levels to allocate on the P-buffer.
+ */
+ public RenderTexture(boolean useRGB, boolean useRGBA, boolean useDepth, boolean isRectangle, int target, int mipmaps) {
+ if ( useRGB && useRGBA )
+ throw new IllegalArgumentException("A RenderTexture can't be both RGB and RGBA.");
+
+ if ( mipmaps < 0 )
+ throw new IllegalArgumentException("The mipmap levels can't be negative.");
+
+ if ( isRectangle && target != RENDER_TEXTURE_RECTANGLE )
+ throw new IllegalArgumentException("When the RenderTexture is rectangle the target must be RENDER_TEXTURE_RECTANGLE.");
+
+ pixelFormatCaps = BufferUtils.createIntBuffer(4);
+ pBufferAttribs = BufferUtils.createIntBuffer(8);
+
+ if ( useRGB ) {
+ pixelFormatCaps.put(isRectangle ? WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : WGL_BIND_TO_TEXTURE_RGB_ARB);
+ pixelFormatCaps.put(GL11.GL_TRUE);
+
+ pBufferAttribs.put(WGL_TEXTURE_FORMAT_ARB);
+ pBufferAttribs.put(WGL_TEXTURE_RGB_ARB);
+ } else if ( useRGBA ) {
+ pixelFormatCaps.put(isRectangle ? WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV : WGL_BIND_TO_TEXTURE_RGBA_ARB);
+ pixelFormatCaps.put(GL11.GL_TRUE);
+
+ pBufferAttribs.put(WGL_TEXTURE_FORMAT_ARB);
+ pBufferAttribs.put(WGL_TEXTURE_RGBA_ARB);
+ }
+
+ if ( useDepth ) {
+ pixelFormatCaps.put(isRectangle ? WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV : WGL_BIND_TO_TEXTURE_DEPTH_NV);
+ pixelFormatCaps.put(GL11.GL_TRUE);
+
+ pBufferAttribs.put(WGL_DEPTH_TEXTURE_FORMAT_NV);
+ pBufferAttribs.put(WGL_TEXTURE_DEPTH_COMPONENT_NV);
+ }
+
+ pBufferAttribs.put(WGL_TEXTURE_TARGET_ARB);
+ pBufferAttribs.put(target);
+
+ if ( mipmaps != 0 ) {
+ pBufferAttribs.put(WGL_MIPMAP_TEXTURE_ARB);
+ pBufferAttribs.put(mipmaps);
+ }
+
+ pixelFormatCaps.flip();
+ pBufferAttribs.flip();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/StateStack.java b/src/java/org/lwjgl/opengl/StateStack.java
new file mode 100644
index 0000000..9d7755d
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/StateStack.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+class StateStack {
+ private int[] state_stack;
+ private int stack_pos;
+
+ public int getState() {
+ return state_stack[stack_pos];
+ }
+
+ public void pushState(int new_state) {
+ int pos = ++stack_pos;
+ if (pos == state_stack.length) {
+ growState();
+ }
+ state_stack[pos] = new_state;
+ }
+
+ public int popState() {
+ return state_stack[stack_pos--];
+ }
+
+ public void growState() {
+ int[] new_state_stack = new int[state_stack.length + 1];
+ System.arraycopy(state_stack, 0, new_state_stack, 0, state_stack.length);
+ state_stack = new_state_stack;
+ }
+
+ StateStack(int initial_value) {
+ state_stack = new int[1];
+ stack_pos = 0;
+ state_stack[stack_pos] = initial_value;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/StateTracker.java b/src/java/org/lwjgl/opengl/StateTracker.java
new file mode 100644
index 0000000..8918d27
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/StateTracker.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+final class StateTracker {
+ private ReferencesStack references_stack;
+ private final StateStack attrib_stack;
+
+ private boolean insideBeginEnd;
+
+ StateTracker() {
+ attrib_stack = new StateStack(0);
+ }
+
+ /** This is called after getting function addresses. */
+ void init() {
+ references_stack = new ReferencesStack();
+ }
+
+ static void setBeginEnd(ContextCapabilities caps, boolean inside) {
+ caps.tracker.insideBeginEnd = inside;
+ }
+
+ boolean isBeginEnd() {
+ return insideBeginEnd;
+ }
+
+ static void popAttrib(ContextCapabilities caps) {
+ caps.tracker.doPopAttrib();
+ }
+
+ private void doPopAttrib() {
+ references_stack.popState(attrib_stack.popState());
+ }
+
+ static void pushAttrib(ContextCapabilities caps, int mask) {
+ caps.tracker.doPushAttrib(mask);
+ }
+
+ private void doPushAttrib(int mask) {
+ attrib_stack.pushState(mask);
+ references_stack.pushState();
+ }
+
+ static ReferencesStack getReferencesStack(ContextCapabilities caps) {
+ return caps.tracker.references_stack;
+ }
+
+ static void bindBuffer(ContextCapabilities caps, int target, int buffer) {
+ ReferencesStack references_stack = getReferencesStack(caps);
+ switch(target) {
+ case GL15.GL_ELEMENT_ARRAY_BUFFER:
+ references_stack.getReferences().elementArrayBuffer = buffer;
+ break;
+ case GL15.GL_ARRAY_BUFFER:
+ references_stack.getReferences().arrayBuffer = buffer;
+ break;
+ case GL21.GL_PIXEL_PACK_BUFFER:
+ references_stack.getReferences().pixelPackBuffer = buffer;
+ break;
+ case GL21.GL_PIXEL_UNPACK_BUFFER:
+ references_stack.getReferences().pixelUnpackBuffer = buffer;
+ break;
+ case GL40.GL_DRAW_INDIRECT_BUFFER:
+ references_stack.getReferences().indirectBuffer = buffer;
+ break;
+
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/Util.java b/src/java/org/lwjgl/opengl/Util.java
new file mode 100644
index 0000000..04b4761
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/Util.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+
+/**
+ * Simple utility class.
+ *
+ * @author cix_foo
+ * @version $Revision: 3316 $
+ */
+
+public final class Util {
+ /** No c'tor */
+ private Util() {
+ }
+
+ /**
+ * Throws OpenGLException if GL11.glGetError() returns anything else than GL11.GL_NO_ERROR
+ *
+ */
+ public static void checkGLError() throws OpenGLException {
+ if ( ContextCapabilities.DEBUG && GLContext.getCapabilities().tracker.isBeginEnd() ) // Do not call GetError inside a Begin/End pair.
+ return;
+ int err = GL11.glGetError();
+ if ( err != GL11.GL_NO_ERROR ) {
+ throw new OpenGLException(err);
+ }
+ }
+
+ /**
+ * Translate a GL error code to a String describing the error
+ */
+ public static String translateGLErrorString(int error_code) {
+ switch (error_code) {
+ case GL11.GL_NO_ERROR:
+ return "No error";
+ case GL11.GL_INVALID_ENUM:
+ return "Invalid enum";
+ case GL11.GL_INVALID_VALUE:
+ return "Invalid value";
+ case GL11.GL_INVALID_OPERATION:
+ return "Invalid operation";
+ case GL11.GL_STACK_OVERFLOW:
+ return "Stack overflow";
+ case GL11.GL_STACK_UNDERFLOW:
+ return "Stack underflow";
+ case GL11.GL_OUT_OF_MEMORY:
+ return "Out of memory";
+ case ARBImaging.GL_TABLE_TOO_LARGE:
+ return "Table too large";
+ case EXTFramebufferObject.GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
+ return "Invalid framebuffer operation";
+ default:
+ return null;
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsAWTGLCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/WindowsAWTGLCanvasPeerInfo.java
new file mode 100644
index 0000000..c7acf7e
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsAWTGLCanvasPeerInfo.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2002-2008 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.Canvas;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: WindowsAWTGLCanvasPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class WindowsAWTGLCanvasPeerInfo extends WindowsPeerInfo {
+ private final Canvas component;
+ private final AWTSurfaceLock awt_surface = new AWTSurfaceLock();
+ private final PixelFormat pixel_format;
+ private boolean has_pixel_format= false;
+
+ WindowsAWTGLCanvasPeerInfo(Canvas component, PixelFormat pixel_format) {
+ this.component = component;
+ this.pixel_format = pixel_format;
+ }
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ nInitHandle(awt_surface.lockAndGetHandle(component), getHandle());
+ if (!has_pixel_format && pixel_format != null) {
+ // If we haven't applied a pixel format yet, do it now
+ int format = choosePixelFormat(getHdc(), component.getX(), component.getY(), pixel_format, null, true, true, false, true);
+ setPixelFormat(getHdc(), format);
+ has_pixel_format = true;
+ }
+ }
+ private static native void nInitHandle(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/WindowsCanvasImplementation.java b/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java
new file mode 100644
index 0000000..56f2510
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002-2008 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.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Toolkit;
+import java.awt.Canvas;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3002 $
+ * $Id: WindowsCanvasImplementation.java 3002 2008-04-10 20:25:54Z elias_naur $
+ */
+final class WindowsCanvasImplementation implements AWTCanvasImplementation {
+ static {
+ // Make sure the awt stuff is properly initialised (the jawt library in particular)
+ Toolkit.getDefaultToolkit();
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ try {
+ System.loadLibrary("jawt");
+ } catch (UnsatisfiedLinkError e) {
+ /* It is probably already loaded, potentially by a different ClassLoader
+ * so just log the exception and continue
+ */
+ LWJGLUtil.log("Failed to load jawt: " + e.getMessage());
+ }
+ return null;
+ }
+ });
+ }
+
+ public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
+ return new WindowsAWTGLCanvasPeerInfo(component, pixel_format);
+ }
+
+ /**
+ * 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 {
+ /*
+ * It seems like the best way is to simply return null and
+ * use SetPixelFormat in JNI later.
+ */
+ return null;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsContextAttribs.java b/src/java/org/lwjgl/opengl/WindowsContextAttribs.java
new file mode 100644
index 0000000..3273144
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsContextAttribs.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * An implementation of ContextAttribs using WGL_create_context.
+ *
+ * @author spasi
+ */
+final class WindowsContextAttribs implements ContextAttribsImplementation {
+
+ private static final int WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
+ private static final int WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092;
+ private static final int WGL_CONTEXT_LAYER_PLANE_ARB = 0x2093;
+ private static final int WGL_CONTEXT_FLAGS_ARB = 0x2094;
+ private static final int WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126;
+
+ private static final int WGL_CONTEXT_DEBUG_BIT_ARB = 0x0001;
+ private static final int WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002;
+
+ private static final int WGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
+ private static final int WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
+
+ WindowsContextAttribs() {
+ }
+
+ public int getMajorVersionAttrib() {
+ return WGL_CONTEXT_MAJOR_VERSION_ARB;
+ }
+
+ public int getMinorVersionAttrib() {
+ return WGL_CONTEXT_MINOR_VERSION_ARB;
+ }
+
+ public int getLayerPlaneAttrib() {
+ return WGL_CONTEXT_LAYER_PLANE_ARB;
+ }
+
+ public int getFlagsAttrib() {
+ return WGL_CONTEXT_FLAGS_ARB;
+ }
+
+ public int getDebugBit() {
+ return WGL_CONTEXT_DEBUG_BIT_ARB;
+ }
+
+ public int getForwardCompatibleBit() {
+ return WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+ }
+
+ public int getProfileMaskAttrib() {
+ return WGL_CONTEXT_PROFILE_MASK_ARB;
+ }
+
+ public int getProfileCoreBit() {
+ return WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+
+ public int getProfileCompatibilityBit() {
+ return WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/WindowsContextImplementation.java b/src/java/org/lwjgl/opengl/WindowsContextImplementation.java
new file mode 100644
index 0000000..33e535e
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsContextImplementation.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002-2008 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 org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+/**
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: WindowsContextImplementation.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class WindowsContextImplementation implements ContextImplementation {
+
+ public ByteBuffer create(PeerInfo peer_info, IntBuffer attribs, ByteBuffer shared_context_handle) throws LWJGLException {
+ ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ try {
+ return nCreate(peer_handle, attribs, shared_context_handle);
+ } finally {
+ peer_info.unlock();
+ }
+ }
+
+ private static native ByteBuffer nCreate(ByteBuffer peer_handle, IntBuffer attribs_handle, ByteBuffer shared_context_handle) throws LWJGLException;
+
+ public void swapBuffers() throws LWJGLException {
+ Context current_context = Context.getCurrentContext();
+ if ( current_context == null )
+ throw new IllegalStateException("No context is current");
+ synchronized ( current_context ) {
+ PeerInfo current_peer_info = current_context.getPeerInfo();
+ ByteBuffer peer_handle = current_peer_info.lockAndGetHandle();
+ try {
+ nSwapBuffers(peer_handle);
+ } finally {
+ current_peer_info.unlock();
+ }
+ }
+ }
+
+ private static native void nSwapBuffers(ByteBuffer peer_info_handle) throws LWJGLException;
+
+ public void releaseDrawable(ByteBuffer context_handle) throws LWJGLException {
+ }
+
+ public void update(ByteBuffer context_handle) {
+ }
+
+ public void releaseCurrentContext() throws LWJGLException {
+ nReleaseCurrentContext();
+ }
+
+ private static native void nReleaseCurrentContext() throws LWJGLException;
+
+ public void makeCurrent(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException {
+ ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ try {
+ nMakeCurrent(peer_handle, handle);
+ } finally {
+ peer_info.unlock();
+ }
+ }
+
+ private static native void nMakeCurrent(ByteBuffer peer_handle, ByteBuffer context_handle) throws LWJGLException;
+
+ public boolean isCurrent(ByteBuffer handle) throws LWJGLException {
+ boolean result = nIsCurrent(handle);
+ return result;
+ }
+
+ private static native boolean nIsCurrent(ByteBuffer context_handle) throws LWJGLException;
+
+ public void setSwapInterval(int value) {
+ boolean success = nSetSwapInterval(value);
+ if ( !success )
+ LWJGLUtil.log("Failed to set swap interval");
+ Util.checkGLError();
+ }
+
+ private static native boolean nSetSwapInterval(int value);
+
+ public void destroy(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException {
+ nDestroy(handle);
+ }
+
+ private static native void nDestroy(ByteBuffer context_handle) throws LWJGLException;
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsDisplay.java b/src/java/org/lwjgl/opengl/WindowsDisplay.java
new file mode 100644
index 0000000..694cc28
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsDisplay.java
@@ -0,0 +1,976 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is the Display implementation interface. Display delegates
+ * to implementors of this interface. There is one DisplayImplementation
+ * for each supported platform.
+ * @author elias_naur
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.awt.Canvas;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.input.Cursor;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+
+final class WindowsDisplay implements DisplayImplementation {
+ private final static int GAMMA_LENGTH = 256;
+
+ private final static int WM_CANCELMODE = 0x001F;
+ private final static int WM_MOUSEMOVE = 0x0200;
+ private final static int WM_LBUTTONDOWN = 0x0201;
+ private final static int WM_LBUTTONUP = 0x0202;
+ private final static int WM_LBUTTONDBLCLK = 0x0203;
+ private final static int WM_RBUTTONDOWN = 0x0204;
+ private final static int WM_RBUTTONUP = 0x0205;
+ private final static int WM_RBUTTONDBLCLK = 0x0206;
+ private final static int WM_MBUTTONDOWN = 0x0207;
+ private final static int WM_MBUTTONUP = 0x0208;
+ private final static int WM_MBUTTONDBLCLK = 0x0209;
+ private final static int WM_MOUSEWHEEL = 0x020A;
+ private final static int WM_CAPTURECHANGED = 0x0215;
+ private final static int WM_MOUSELEAVE = 0x02A3;
+ private final static int WM_KEYDOWN = 256;
+ private final static int WM_KEYUP = 257;
+ private final static int WM_SYSKEYUP = 261;
+ private final static int WM_SYSKEYDOWN = 260;
+ private final static int WM_SYSCHAR = 262;
+ private final static int WM_CHAR = 258;
+ private final static int WM_SETICON = 0x0080;
+
+ private final static int WM_QUIT = 0x0012;
+ private final static int WM_SYSCOMMAND = 0x0112;
+ private final static int WM_PAINT = 0x000F;
+ private final static int WM_KILLFOCUS = 8;
+ private final static int WM_SETFOCUS = 7;
+
+ private final static int SC_SIZE = 0xF000;
+ private final static int SC_MOVE = 0xF010;
+ private final static int SC_MINIMIZE = 0xF020;
+ private final static int SC_MAXIMIZE = 0xF030;
+ private final static int SC_NEXTWINDOW = 0xF040;
+ private final static int SC_PREVWINDOW = 0xF050;
+ private final static int SC_CLOSE = 0xF060;
+ private final static int SC_VSCROLL = 0xF070;
+ private final static int SC_HSCROLL = 0xF080;
+ private final static int SC_MOUSEMENU = 0xF090;
+ private final static int SC_KEYMENU = 0xF100;
+ private final static int SC_ARRANGE = 0xF110;
+ private final static int SC_RESTORE = 0xF120;
+ private final static int SC_TASKLIST = 0xF130;
+ private final static int SC_SCREENSAVE = 0xF140;
+ private final static int SC_HOTKEY = 0xF150;
+ private final static int SC_DEFAULT = 0xF160;
+ private final static int SC_MONITORPOWER = 0xF170;
+ private final static int SC_CONTEXTHELP = 0xF180;
+ private final static int SC_SEPARATOR = 0xF00F;
+
+ final static int SM_CXCURSOR = 13;
+ final static int SM_CYCURSOR = 14;
+ final static int SM_CMOUSEBUTTONS = 43;
+ final static int SM_MOUSEWHEELPRESENT = 75;
+
+ private final static int SIZE_RESTORED = 0;
+ private final static int SIZE_MINIMIZED = 1;
+ private final static int SIZE_MAXIMIZED = 2;
+ private final static int WM_SIZE = 0x0005;
+ private final static int WM_ACTIVATE = 0x0006;
+ private final static int WA_INACTIVE = 0;
+ private final static int WA_ACTIVE = 1;
+ private final static int WA_CLICKACTIVE = 2;
+ private final static int SW_SHOWMINNOACTIVE = 7;
+ private final static int SW_SHOWDEFAULT = 10;
+ private final static int SW_RESTORE = 9;
+
+ private final static int ICON_SMALL = 0;
+ private final static int ICON_BIG = 1;
+
+ private final static IntBuffer rect_buffer = BufferUtils.createIntBuffer(4);
+ private final static Rect rect = new Rect();
+ private final static Rect rect2 = new Rect();
+ private static WindowsDisplay current_display;
+
+ private static boolean cursor_clipped;
+ private WindowsDisplayPeerInfo peer_info;
+ private Object current_cursor;
+ private Canvas parent;
+ private static boolean hasParent = false;
+
+ private WindowsKeyboard keyboard;
+ private WindowsMouse mouse;
+
+ private boolean close_requested;
+ private boolean is_dirty;
+
+ private ByteBuffer current_gamma;
+ private ByteBuffer saved_gamma;
+ private DisplayMode current_mode;
+
+ private boolean mode_set;
+ private boolean isMinimized;
+ private boolean isFocused;
+ private boolean did_maximize;
+ private boolean inAppActivate;
+
+ private long hwnd;
+ private long hdc;
+
+ private long small_icon;
+ private long large_icon;
+
+ private int captureMouse = -1;
+ private boolean trackingMouse = false;
+ private boolean mouseInside = false;
+
+ WindowsDisplay() {
+ current_display = this;
+ }
+
+ public void createWindow(DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
+ close_requested = false;
+ is_dirty = false;
+ isMinimized = false;
+ isFocused = false;
+ did_maximize = false;
+ this.parent = parent;
+ hasParent = parent != null;
+ long parent_hwnd = parent != null ? getHwnd(parent) : 0;
+ this.hwnd = nCreateWindow(x, y, mode.getWidth(), mode.getHeight(), Display.isFullscreen() || isUndecorated(), parent != null, parent_hwnd);
+ if (hwnd == 0) {
+ throw new LWJGLException("Failed to create window");
+ }
+ this.hdc = getDC(hwnd);
+ if (hdc == 0) {
+ nDestroyWindow(hwnd);
+ throw new LWJGLException("Failed to get dc");
+ }
+ try {
+ int format = WindowsPeerInfo.choosePixelFormat(getHdc(), 0, 0, peer_info.getPixelFormat(), null, true, true, false, true);
+ WindowsPeerInfo.setPixelFormat(getHdc(), format);
+ peer_info.initDC(getHwnd(), getHdc());
+ showWindow(getHwnd(), SW_SHOWDEFAULT);
+ if (parent == null) {
+ setForegroundWindow(getHwnd());
+ setFocus(getHwnd());
+ }
+ } catch (LWJGLException e) {
+ nReleaseDC(hwnd, hdc);
+ nDestroyWindow(hwnd);
+ throw e;
+ }
+ }
+ private static native long nCreateWindow(int x, int y, int width, int height, boolean undecorated, boolean child_window, long parent_hwnd) throws LWJGLException;
+
+ private static boolean isUndecorated() {
+ return Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated");
+ }
+
+ private static long getHwnd(Canvas parent) throws LWJGLException {
+ AWTCanvasImplementation awt_impl = AWTGLCanvas.createImplementation();
+ WindowsPeerInfo parent_peer_info = (WindowsPeerInfo)awt_impl.createPeerInfo(parent, null);
+ ByteBuffer parent_peer_info_handle = parent_peer_info.lockAndGetHandle();
+ try {
+ return parent_peer_info.getHwnd();
+ } finally {
+ parent_peer_info.unlock();
+ }
+ }
+
+ public void destroyWindow() {
+ nReleaseDC(hwnd, hdc);
+ nDestroyWindow(hwnd);
+ freeLargeIcon();
+ freeSmallIcon();
+ resetCursorClipping();
+ }
+ private static native void nReleaseDC(long hwnd, long hdc);
+ private static native void nDestroyWindow(long hwnd);
+ static void resetCursorClipping() {
+ if (cursor_clipped) {
+ try {
+ clipCursor(null);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to reset cursor clipping: " + e);
+ }
+ cursor_clipped = false;
+ }
+ }
+
+ private static void getGlobalClientRect(long hwnd, Rect rect) {
+ rect_buffer.put(0, 0).put(1, 0);
+ clientToScreen(hwnd, rect_buffer);
+ int offset_x = rect_buffer.get(0);
+ int offset_y = rect_buffer.get(1);
+ getClientRect(hwnd, rect_buffer);
+ rect.copyFromBuffer(rect_buffer);
+ rect.offset(offset_x, offset_y);
+ }
+
+ static void setupCursorClipping(long hwnd) throws LWJGLException {
+ cursor_clipped = true;
+ getGlobalClientRect(hwnd, rect);
+ rect.copyToBuffer(rect_buffer);
+ clipCursor(rect_buffer);
+ }
+ private static native void clipCursor(IntBuffer rect) throws LWJGLException;
+
+ public void switchDisplayMode(DisplayMode mode) throws LWJGLException {
+ nSwitchDisplayMode(mode);
+ current_mode = mode;
+ mode_set = true;
+ }
+ private static native void nSwitchDisplayMode(DisplayMode mode) throws LWJGLException;
+
+ /*
+ * Called when the application is alt-tabbed to or from
+ */
+ private void appActivate(boolean active) {
+ if (inAppActivate) {
+ return;
+ }
+ inAppActivate = true;
+ isFocused = active;
+ if (active) {
+ if (Display.isFullscreen()) {
+ restoreDisplayMode();
+ }
+ if (parent == null) {
+ showWindow(getHwnd(), SW_RESTORE);
+ setForegroundWindow(getHwnd());
+ setFocus(getHwnd());
+ }
+ did_maximize = true;
+ if (Display.isFullscreen())
+ updateClipping();
+ } else if (Display.isFullscreen()) {
+ showWindow(getHwnd(), SW_SHOWMINNOACTIVE);
+ resetDisplayMode();
+ } else
+ updateClipping();
+ updateCursor();
+ inAppActivate = false;
+ }
+ private static native void showWindow(long hwnd, int mode);
+ private static native void setForegroundWindow(long hwnd);
+ private static native void setFocus(long hwnd);
+
+ private void restoreDisplayMode() {
+ try {
+ doSetGammaRamp(current_gamma);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to restore gamma: " + e.getMessage());
+ }
+
+ if (!mode_set) {
+ mode_set = true;
+ try {
+ nSwitchDisplayMode(current_mode);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to restore display mode: " + e.getMessage());
+ }
+ }
+ }
+
+ public void resetDisplayMode() {
+ try {
+ doSetGammaRamp(saved_gamma);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to reset gamma ramp: " + e.getMessage());
+ }
+ current_gamma = saved_gamma;
+ if (mode_set) {
+ mode_set = false;
+ nResetDisplayMode();
+ }
+ resetCursorClipping();
+ }
+ private static native void nResetDisplayMode();
+
+ public int getGammaRampLength() {
+ return GAMMA_LENGTH;
+ }
+
+ public void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException {
+ doSetGammaRamp(convertToNativeRamp(gammaRamp));
+ }
+ private static native ByteBuffer convertToNativeRamp(FloatBuffer gamma_ramp) throws LWJGLException;
+ private static native ByteBuffer getCurrentGammaRamp() throws LWJGLException;
+
+ private void doSetGammaRamp(ByteBuffer native_gamma) throws LWJGLException {
+ nSetGammaRamp(native_gamma);
+ current_gamma = native_gamma;
+ }
+ private static native void nSetGammaRamp(ByteBuffer native_ramp) throws LWJGLException;
+
+ public String getAdapter() {
+ try {
+ String maxObjNo = WindowsRegistry.queryRegistrationKey(
+ WindowsRegistry.HKEY_LOCAL_MACHINE,
+ "HARDWARE\\DeviceMap\\Video",
+ "MaxObjectNumber");
+ int maxObjectNumber = maxObjNo.charAt(0);
+ String vga_driver_value = "";
+ for(int i=0;i0) {
+ WindowsFileVersion version = nGetVersion(drivers[0] + ".dll");
+ if (version != null)
+ return version.toString();
+ }
+ }
+ return null;
+ }
+ private native WindowsFileVersion nGetVersion(String driver);
+
+ public DisplayMode init() throws LWJGLException {
+ current_gamma = saved_gamma = getCurrentGammaRamp();
+ return current_mode = getCurrentDisplayMode();
+ }
+ private static native DisplayMode getCurrentDisplayMode() throws LWJGLException;
+
+ public void setTitle(String title) {
+ nSetTitle(hwnd, title);
+ }
+ private static native void nSetTitle(long hwnd, String title);
+
+ public boolean isCloseRequested() {
+ boolean saved = close_requested;
+ close_requested = false;
+ return saved;
+ }
+
+ public boolean isVisible() {
+ return !isMinimized;
+ }
+
+ public boolean isActive() {
+ return isFocused;
+ }
+
+ public boolean isDirty() {
+ boolean saved = is_dirty;
+ is_dirty = false;
+ return saved;
+ }
+
+ public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException {
+ peer_info = new WindowsDisplayPeerInfo(pixel_format);
+ return peer_info;
+ }
+
+ public void update() {
+ nUpdate();
+ if (parent != null && parent.isFocusOwner()) {
+ setFocus(getHwnd());
+ }
+ if (did_maximize) {
+ did_maximize = false;
+ /**
+ * WORKAROUND:
+ * Making the context current (redundantly) when the window
+ * is maximized helps some gfx cards recover from fullscreen
+ */
+ try {
+ if (Display.getDrawable().getContext() != null && Display.getDrawable().getContext().isCurrent())
+ Display.getDrawable().getContext().makeCurrent();
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while trying to make context current: " + e);
+ }
+ }
+ }
+ private static native void nUpdate();
+
+ public void reshape(int x, int y, int width, int height) {
+ nReshape(getHwnd(), x, y, width, height, Display.isFullscreen() || isUndecorated(), parent != null);
+ }
+ private static native void nReshape(long hwnd, int x, int y, int width, int height, boolean undecorated, boolean child);
+ public native DisplayMode[] getAvailableDisplayModes() throws LWJGLException;
+
+ /* Mouse */
+ public boolean hasWheel() {
+ return mouse.hasWheel();
+ }
+
+ public int getButtonCount() {
+ return mouse.getButtonCount();
+ }
+
+ public void createMouse() throws LWJGLException {
+ mouse = new WindowsMouse(getHwnd());
+ }
+
+ public void destroyMouse() {
+ if (mouse != null)
+ mouse.destroy();
+ mouse = null;
+ }
+
+ public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons) {
+ mouse.poll(coord_buffer, buttons);
+ }
+
+ public void readMouse(ByteBuffer buffer) {
+ mouse.read(buffer);
+ }
+
+ public void grabMouse(boolean grab) {
+ mouse.grab(grab, shouldGrab());
+ updateCursor();
+ }
+
+ public int getNativeCursorCapabilities() {
+ return Cursor.CURSOR_ONE_BIT_TRANSPARENCY;
+ }
+
+ public void setCursorPosition(int x, int y) {
+ getGlobalClientRect(getHwnd(), rect);
+ int transformed_x = rect.left + x;
+ int transformed_y = rect.bottom - 1 - y;
+ nSetCursorPosition(transformed_x, transformed_y);
+ setMousePosition(x, y);
+ }
+ private static native void nSetCursorPosition(int x, int y);
+
+ public void setNativeCursor(Object handle) throws LWJGLException {
+ current_cursor = handle;
+ updateCursor();
+ }
+
+ private void updateCursor() {
+ try {
+ if (mouse != null && shouldGrab())
+ nSetNativeCursor(getHwnd(), mouse.getBlankCursor());
+ else
+ nSetNativeCursor(getHwnd(), current_cursor);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to update cursor: " + e);
+ }
+ }
+ static native void nSetNativeCursor(long hwnd, Object handle) throws LWJGLException;
+
+ public int getMinCursorSize() {
+ return getSystemMetrics(SM_CXCURSOR);
+ }
+
+ public int getMaxCursorSize() {
+ return getSystemMetrics(SM_CXCURSOR);
+ }
+
+ static native int getSystemMetrics(int index);
+
+ private static native long getDllInstance();
+
+ private long getHwnd() {
+ return hwnd;
+ }
+
+ private long getHdc() {
+ return hdc;
+ }
+
+ private static native long getDC(long hwnd);
+ private static native long getDesktopWindow();
+ private static native long getForegroundWindow();
+
+ static void centerCursor(long hwnd) {
+ if (getForegroundWindow() != hwnd && !hasParent)
+ return;
+ getGlobalClientRect(hwnd, rect);
+ int local_offset_x = rect.left;
+ int local_offset_y = rect.top;
+ /* -- This is wrong on multi-monitor setups
+ getGlobalClientRect(getDesktopWindow(), rect2);
+ Rect.intersect(rect, rect2, rect);
+ */
+ int center_x = (rect.left + rect.right)/2;
+ int center_y = (rect.top + rect.bottom)/2;
+ nSetCursorPosition(center_x, center_y);
+ int local_x = center_x - local_offset_x;
+ int local_y = center_y - local_offset_y;
+ if (current_display != null)
+ current_display.setMousePosition(local_x, transformY(hwnd, local_y));
+ }
+
+ private void setMousePosition(int x, int y) {
+ if (mouse != null)
+ mouse.setPosition(x, y);
+ }
+
+ /* Keyboard */
+ public void createKeyboard() throws LWJGLException {
+ keyboard = new WindowsKeyboard(getHwnd());
+ }
+
+ public void destroyKeyboard() {
+ keyboard.destroy();
+ keyboard = null;
+ }
+
+ public void pollKeyboard(ByteBuffer keyDownBuffer) {
+ keyboard.poll(keyDownBuffer);
+ }
+
+ public void readKeyboard(ByteBuffer buffer) {
+ keyboard.read(buffer);
+ }
+
+// public native int isStateKeySet(int key);
+
+ public static native ByteBuffer nCreateCursor(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 {
+ return doCreateCursor(width, height, xHotspot, yHotspot, numImages, images, delays);
+ }
+
+ static Object doCreateCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
+ return nCreateCursor(width, height, xHotspot, yHotspot, numImages, images, images.position(), delays, delays != null ? delays.position() : -1);
+ }
+
+ public void destroyCursor(Object cursorHandle) {
+ doDestroyCursor(cursorHandle);
+ }
+ static native void doDestroyCursor(Object cursorHandle);
+
+ public int getPbufferCapabilities() {
+ try {
+ // Return the capabilities of a minimum pixel format
+ return nGetPbufferCapabilities(new PixelFormat(0, 0, 0, 0, 0, 0, 0, 0, false));
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while determining pbuffer capabilities: " + e);
+ return 0;
+ }
+ }
+ private native int nGetPbufferCapabilities(PixelFormat format) throws LWJGLException;
+
+ public boolean isBufferLost(PeerInfo handle) {
+ return ((WindowsPbufferPeerInfo)handle).isBufferLost();
+ }
+
+ public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format,
+ IntBuffer pixelFormatCaps,
+ IntBuffer pBufferAttribs) throws LWJGLException {
+ return new WindowsPbufferPeerInfo(width, height, pixel_format, pixelFormatCaps, pBufferAttribs);
+ }
+
+ public void setPbufferAttrib(PeerInfo handle, int attrib, int value) {
+ ((WindowsPbufferPeerInfo)handle).setPbufferAttrib(attrib, value);
+ }
+
+ public void bindTexImageToPbuffer(PeerInfo handle, int buffer) {
+ ((WindowsPbufferPeerInfo)handle).bindTexImageToPbuffer(buffer);
+ }
+
+ public void releaseTexImageFromPbuffer(PeerInfo handle, int buffer) {
+ ((WindowsPbufferPeerInfo)handle).releaseTexImageFromPbuffer(buffer);
+ }
+
+ private void freeSmallIcon() {
+ if (small_icon != 0) {
+ destroyIcon(small_icon);
+ small_icon = 0;
+ }
+ }
+
+ private void freeLargeIcon() {
+ if (large_icon != 0) {
+ destroyIcon(large_icon);
+ large_icon = 0;
+ }
+ }
+
+ /**
+ * Sets one or more icons for the Display.
+ *
+ * - On Windows you should supply at least one 16x16 icon and one 32x32.
+ * - Linux (and similar platforms) expect one 32x32 icon.
+ * - Mac OS X should be supplied one 128x128 icon
+ *
+ * The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions nescesarry for the specific platform.
+ *
+ * @param icons Array of icons in RGBA mode
+ * @return number of icons used.
+ */
+ public int setIcon(ByteBuffer[] icons) {
+ boolean done_small = false;
+ boolean done_large = false;
+ int used = 0;
+
+ int small_icon_size = 16;
+ int large_icon_size = 32;
+ for (int i=0;i>> 30) & 0x1);
+ byte state = (byte)(1 - ((lParam >>> 31) & 0x1));
+ boolean repeat = state == previous_state;
+ if (keyboard != null)
+ keyboard.handleChar((int)(wParam & 0xFF), millis, repeat);
+ }
+
+ private void handleKeyButton(long wParam, long lParam, long millis) {
+ byte previous_state = (byte)((lParam >>> 30) & 0x1);
+ byte state = (byte)(1 - ((lParam >>> 31) & 0x1));
+ boolean repeat = state == previous_state; // Repeat message
+ byte extended = (byte)((lParam >>> 24) & 0x1);
+ int scan_code = (int)((lParam >>> 16) & 0xFF);
+ if (keyboard != null) {
+ keyboard.handleKey((int)wParam, scan_code, extended != 0, state, millis, repeat);
+
+ if(captureMouse != -1 && keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
+ nReleaseCapture();
+ captureMouse = -1;
+ }
+ }
+ }
+
+ private static int transformY(long hwnd, int y) {
+ getClientRect(hwnd, rect_buffer);
+ rect.copyFromBuffer(rect_buffer);
+ return (rect.bottom - rect.top) - 1 - y;
+ }
+
+ private static native void clientToScreen(long hwnd, IntBuffer point);
+
+ private static int handleMessage(long hwnd, int msg, long wParam, long lParam, long millis) {
+ if (current_display != null)
+ return current_display.doHandleMessage(hwnd, msg, wParam, lParam, millis);
+ else
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ }
+
+ private static native int defWindowProc(long hwnd, int msg, long wParam, long lParam);
+
+ private void checkCursorState() {
+ updateClipping();
+ }
+
+ private void updateClipping() {
+ if ((Display.isFullscreen() || (mouse != null && mouse.isGrabbed())) && !isMinimized && isFocused && (getForegroundWindow() == getHwnd() || hasParent)) {
+ try {
+ setupCursorClipping(getHwnd());
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("setupCursorClipping failed: " + e.getMessage());
+ }
+ } else {
+ resetCursorClipping();
+ }
+ }
+
+ private void setMinimized(boolean m) {
+ isMinimized = m;
+ checkCursorState();
+ }
+
+ private int doHandleMessage(long hwnd, int msg, long wParam, long lParam, long millis) {
+ switch (msg) {
+ // disable screen saver and monitor power down messages which wreak havoc
+ case WM_ACTIVATE:
+ switch ((int)wParam) {
+ case WA_ACTIVE:
+ case WA_CLICKACTIVE:
+ appActivate(true);
+ break;
+ case WA_INACTIVE:
+ appActivate(false);
+ break;
+ }
+ return 0;
+ case WM_SIZE:
+ switch ((int)wParam) {
+ case SIZE_RESTORED:
+ case SIZE_MAXIMIZED:
+ setMinimized(false);
+ break;
+ case SIZE_MINIMIZED:
+ setMinimized(true);
+ break;
+ }
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ case WM_KILLFOCUS:
+ appActivate(false);
+ return 0;
+ case WM_SETFOCUS:
+ appActivate(true);
+ return 0;
+ case WM_MOUSEMOVE:
+ int xPos = (int)(short)(lParam & 0xFFFF);
+ int yPos = transformY(getHwnd(), (int)(short)((lParam >> 16) & 0xFFFF));
+ handleMouseMoved(xPos, yPos, millis);
+ checkCursorState();
+ mouseInside = true;
+ if(!trackingMouse) {
+ trackingMouse = nTrackMouseEvent(hwnd);
+ }
+ return 0;
+ case WM_MOUSEWHEEL:
+ int dwheel = (int)(short)((wParam >> 16) & 0xFFFF);
+ handleMouseScrolled(dwheel, millis);
+ return 0;
+ case WM_LBUTTONDOWN:
+ handleMouseButton(0, 1, millis);
+ return 0;
+ case WM_LBUTTONUP:
+ handleMouseButton(0, 0, millis);
+ return 0;
+ case WM_RBUTTONDOWN:
+ handleMouseButton(1, 1, millis);
+ return 0;
+ case WM_RBUTTONUP:
+ handleMouseButton(1, 0, millis);
+ return 0;
+ case WM_MBUTTONDOWN:
+ handleMouseButton(2, 1, millis);
+ return 0;
+ case WM_MBUTTONUP:
+ handleMouseButton(2, 0, millis);
+ return 0;
+ case WM_SYSCHAR:
+ case WM_CHAR:
+ handleChar(wParam, lParam, millis);
+ return 0;
+ case WM_SYSKEYUP:
+ /* Fall through */
+ case WM_KEYUP:
+ // SysRq apparently only generates WM_KEYUP, so we'll fake a WM_KEYDOWN
+ if (wParam == WindowsKeycodes.VK_SNAPSHOT && keyboard != null &&
+ !keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_SYSRQ)) {
+ // Set key state to pressed
+ long fake_lparam = lParam & ~(1 << 31);
+ // Set key previous state to released
+ fake_lparam = fake_lparam & ~(1 << 30);
+ handleKeyButton(wParam, fake_lparam, millis);
+ }
+ /* Fall through */
+ case WM_SYSKEYDOWN:
+ /* Fall through */
+ case WM_KEYDOWN:
+ handleKeyButton(wParam, lParam, millis);
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ case WM_QUIT:
+ close_requested = true;
+ return 0;
+ case WM_SYSCOMMAND:
+ switch ((int)(wParam & 0xfff0)) {
+ case SC_KEYMENU:
+ case SC_MOUSEMENU:
+ case SC_SCREENSAVE:
+ case SC_MONITORPOWER:
+ return 0;
+ case SC_CLOSE:
+ close_requested = true;
+ return 0;
+ default:
+ break;
+ }
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ case WM_PAINT:
+ is_dirty = true;
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ case WM_MOUSELEAVE:
+ mouseInside = false;
+ trackingMouse = false;
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ case WM_CANCELMODE:
+ nReleaseCapture();
+ /* fall through */
+ case WM_CAPTURECHANGED:
+ if(captureMouse != -1) {
+ handleMouseButton(captureMouse, 0, millis);
+ captureMouse = -1;
+ }
+ return 0;
+ default:
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ }
+ }
+
+ public int getWidth() {
+ return Display.getDisplayMode().getWidth();
+ }
+
+ public int getHeight() {
+ return Display.getDisplayMode().getHeight();
+ }
+
+ private int firstMouseButtonDown() {
+ for(int i=0; i
+ * @version $Revision: 3116 $
+ * $Id: WindowsDisplayPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class WindowsDisplayPeerInfo extends WindowsPeerInfo {
+ private final PixelFormat pixel_format;
+
+ WindowsDisplayPeerInfo(PixelFormat pixel_format) throws LWJGLException {
+ this.pixel_format = pixel_format;
+ GLContext.loadOpenGLLibrary();
+ }
+
+ PixelFormat getPixelFormat() {
+ return pixel_format;
+ }
+
+ void initDC(long hwnd, long hdc) throws LWJGLException {
+ nInitDC(getHandle(), hwnd, hdc);
+ }
+ private static native void nInitDC(ByteBuffer peer_info_handle, long hwnd, long hdc);
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ // NO-OP
+ }
+
+ protected void doUnlock() throws LWJGLException {
+ // NO-OP
+ }
+
+ public void destroy() {
+ super.destroy();
+ GLContext.unloadOpenGLLibrary();
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsFileVersion.java b/src/java/org/lwjgl/opengl/WindowsFileVersion.java
new file mode 100644
index 0000000..8ed5cc4
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsFileVersion.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * @author elias_naur
+ */
+
+final class WindowsFileVersion {
+ private final int product_version_ms;
+ private final int product_version_ls;
+
+ WindowsFileVersion(int product_version_ms, int product_version_ls) {
+ this.product_version_ms = product_version_ms;
+ this.product_version_ls = product_version_ls;
+ }
+
+ public String toString() {
+ int f1 = (product_version_ms >> 16) & 0xFFFF;
+ int f2 = product_version_ms & 0xFFFF;
+ int f3 = (product_version_ls >> 16) & 0xFFFF;
+ int f4 = product_version_ls & 0xFFFF;
+ return f1 + "." + f2 + "." + f3 + "." + f4;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsKeyboard.java b/src/java/org/lwjgl/opengl/WindowsKeyboard.java
new file mode 100644
index 0000000..6820f91
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsKeyboard.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is the Windows implementation of the Keyboard.
+ * @author elias_naur
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Keyboard;
+
+final class WindowsKeyboard {
+ private final static int MAPVK_VK_TO_VSC = 0;
+
+ private final static int BUFFER_SIZE = 50;
+
+ private final long hwnd;
+ private final ByteBuffer keyboard_state;
+ private final byte[] key_down_buffer = new byte[Keyboard.KEYBOARD_SIZE];
+ private final EventQueue event_queue = new EventQueue(Keyboard.EVENT_SIZE);
+ private final ByteBuffer tmp_event = ByteBuffer.allocate(Keyboard.EVENT_SIZE);
+
+ private boolean grabbed;
+
+ private boolean has_retained_event; // Indicates if we're waiting for a WM_CHAR
+ private int retained_key_code;
+ private byte retained_state;
+ private int retained_char;
+ private long retained_millis;
+ private boolean retained_repeat;
+
+ WindowsKeyboard(long hwnd) throws LWJGLException {
+ this.hwnd = hwnd;
+ keyboard_state = BufferUtils.createByteBuffer(256);
+ }
+ private static native boolean isWindowsNT();
+
+ public void destroy() {
+ }
+
+ boolean isKeyDown(int lwjgl_keycode) {
+ return key_down_buffer[lwjgl_keycode] == 1;
+ }
+
+ public void grab(boolean grab) {
+ if(grab) {
+ if (!grabbed) {
+ grabbed = true;
+ }
+ } else {
+ if (grabbed) {
+ grabbed = false;
+ }
+ }
+ }
+
+ public void poll(ByteBuffer keyDownBuffer) {
+ int old_position = keyDownBuffer.position();
+ keyDownBuffer.put(key_down_buffer);
+ keyDownBuffer.position(old_position);
+ }
+
+ private static native int MapVirtualKey(int uCode, int uMapType);
+ private static native int ToUnicode(int wVirtKey, int wScanCode, ByteBuffer lpKeyState, CharBuffer pwszBuff, int cchBuff, int flags);
+ private static native int ToAscii(int wVirtKey, int wScanCode, ByteBuffer lpKeyState, ByteBuffer lpChar, int flags);
+ private static native int GetKeyboardState(ByteBuffer lpKeyState);
+ private static native int GetKeyState(int virt_key);
+
+ private void putEvent(int keycode, byte state, int ch, long millis, boolean repeat) {
+ tmp_event.clear();
+ tmp_event.putInt(keycode).put(state).putInt(ch).putLong(millis*1000000).put(repeat ? (byte)1 : (byte)0);
+ tmp_event.flip();
+ event_queue.putEvent(tmp_event);
+ }
+
+ private boolean checkShiftKey(int virt_key, byte state) {
+ int key_state = (GetKeyState(virt_key) >>> 15) & 0x1;
+ int lwjgl_code = WindowsKeycodes.mapVirtualKeyToLWJGLCode(virt_key);
+ return (key_down_buffer[lwjgl_code] == 1 - state) && (key_state == state);
+ }
+
+ private int translateShift(int scan_code, byte state) {
+ if (checkShiftKey(WindowsKeycodes.VK_LSHIFT, state)) {
+ return WindowsKeycodes.VK_LSHIFT;
+ } else if (checkShiftKey(WindowsKeycodes.VK_RSHIFT, state)) {
+ return WindowsKeycodes.VK_RSHIFT;
+ } else {
+ if (scan_code== 0x2A)
+ return WindowsKeycodes.VK_LSHIFT;
+ else {
+ if (scan_code == 0x36)
+ return WindowsKeycodes.VK_RSHIFT;
+ else
+ return WindowsKeycodes.VK_LSHIFT;
+ }
+ }
+ }
+
+ private int translateExtended(int virt_key, int scan_code, byte state, boolean extended) {
+ switch (virt_key) {
+ case WindowsKeycodes.VK_SHIFT:
+ return translateShift(scan_code, state);
+ case WindowsKeycodes.VK_CONTROL:
+ return extended ? WindowsKeycodes.VK_RCONTROL : WindowsKeycodes.VK_LCONTROL;
+ case WindowsKeycodes.VK_MENU:
+ return extended ? WindowsKeycodes.VK_RMENU : WindowsKeycodes.VK_LMENU;
+ default:
+ return virt_key;
+ }
+ }
+
+ private void flushRetained() {
+ if (has_retained_event) {
+ has_retained_event = false;
+ putEvent(retained_key_code, retained_state, retained_char, retained_millis, retained_repeat);
+ }
+ }
+
+ public void handleKey(int virt_key, int scan_code, boolean extended, byte event_state, long millis, boolean repeat) {
+ virt_key = translateExtended(virt_key, scan_code, event_state, extended);
+ flushRetained();
+ has_retained_event = true;
+ int keycode = WindowsKeycodes.mapVirtualKeyToLWJGLCode(virt_key);
+ if (keycode < key_down_buffer.length)
+ key_down_buffer[keycode] = event_state;
+ retained_key_code = keycode;
+ retained_state = event_state;
+ retained_millis = millis;
+ retained_char = 0;
+ retained_repeat = repeat;
+ }
+
+ public void handleChar(int event_char, long millis, boolean repeat) {
+ if (has_retained_event && retained_char != 0)
+ flushRetained();
+ if (!has_retained_event) {
+ putEvent(0, (byte)0, event_char, millis, repeat);
+ } else
+ retained_char = event_char;
+ }
+
+ public void read(ByteBuffer buffer) {
+ flushRetained();
+ event_queue.copyEvents(buffer);
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsKeycodes.java b/src/java/org/lwjgl/opengl/WindowsKeycodes.java
new file mode 100644
index 0000000..fb4f057
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsKeycodes.java
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * @author elias_naur
+ */
+
+import org.lwjgl.input.Keyboard;
+
+final class WindowsKeycodes {
+ public final static int VK_LBUTTON = 0x01;
+ public final static int VK_RBUTTON = 0x02;
+ public final static int VK_CANCEL = 0x03;
+ public final static int VK_MBUTTON = 0x04; /* NOT contiguous with L & RBUTTON */
+
+ public final static int VK_XBUTTON1 = 0x05; /* NOT contiguous with L & RBUTTON */
+ public final static int VK_XBUTTON2 = 0x06; /* NOT contiguous with L & RBUTTON */
+
+/*
+ * 0x07 : unassigned
+ */
+
+ public final static int VK_BACK = 0x08;
+ public final static int VK_TAB = 0x09;
+
+/*
+ * 0x0A - 0x0B : reserved
+ */
+
+ public final static int VK_CLEAR = 0x0C;
+ public final static int VK_RETURN = 0x0D;
+
+ public final static int VK_SHIFT = 0x10;
+ public final static int VK_CONTROL = 0x11;
+ public final static int VK_MENU = 0x12;
+ public final static int VK_PAUSE = 0x13;
+ public final static int VK_CAPITAL = 0x14;
+
+ public final static int VK_KANA = 0x15;
+ public final static int VK_HANGEUL = 0x15; /* old name - should be here for compatibility */
+ public final static int VK_HANGUL = 0x15;
+ public final static int VK_JUNJA = 0x17;
+ public final static int VK_FINAL = 0x18;
+ public final static int VK_HANJA = 0x19;
+ public final static int VK_KANJI = 0x19;
+
+ public final static int VK_ESCAPE = 0x1B;
+
+ public final static int VK_CONVERT = 0x1C;
+ public final static int VK_NONCONVERT = 0x1D;
+ public final static int VK_ACCEPT = 0x1E;
+ public final static int VK_MODECHANGE = 0x1F;
+
+ public final static int VK_SPACE = 0x20;
+ public final static int VK_PRIOR = 0x21;
+ public final static int VK_NEXT = 0x22;
+ public final static int VK_END = 0x23;
+ public final static int VK_HOME = 0x24;
+ public final static int VK_LEFT = 0x25;
+ public final static int VK_UP = 0x26;
+ public final static int VK_RIGHT = 0x27;
+ public final static int VK_DOWN = 0x28;
+ public final static int VK_SELECT = 0x29;
+ public final static int VK_PRINT = 0x2A;
+ public final static int VK_EXECUTE = 0x2B;
+ public final static int VK_SNAPSHOT = 0x2C;
+ public final static int VK_INSERT = 0x2D;
+ public final static int VK_DELETE = 0x2E;
+ public final static int VK_HELP = 0x2F;
+/*
+ * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
+ * 0x40 : unassigned
+ * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
+ */
+ public final static int VK_0 = 0x30;
+ public final static int VK_1 = 0x31;
+ public final static int VK_2 = 0x32;
+ public final static int VK_3 = 0x33;
+ public final static int VK_4 = 0x34;
+ public final static int VK_5 = 0x35;
+ public final static int VK_6 = 0x36;
+ public final static int VK_7 = 0x37;
+ public final static int VK_8 = 0x38;
+ public final static int VK_9 = 0x39;
+
+ public final static int VK_A = 0x41;
+ public final static int VK_B = 0x42;
+ public final static int VK_C = 0x43;
+ public final static int VK_D = 0x44;
+ public final static int VK_E = 0x45;
+ public final static int VK_F = 0x46;
+ public final static int VK_G = 0x47;
+ public final static int VK_H = 0x48;
+ public final static int VK_I = 0x49;
+ public final static int VK_J = 0x4A;
+ public final static int VK_K = 0x4B;
+ public final static int VK_L = 0x4C;
+ public final static int VK_M = 0x4D;
+ public final static int VK_N = 0x4E;
+ public final static int VK_O = 0x4F;
+ public final static int VK_P = 0x50;
+ public final static int VK_Q = 0x51;
+ public final static int VK_R = 0x52;
+ public final static int VK_S = 0x53;
+ public final static int VK_T = 0x54;
+ public final static int VK_U = 0x55;
+ public final static int VK_V = 0x56;
+ public final static int VK_W = 0x57;
+ public final static int VK_X = 0x58;
+ public final static int VK_Y = 0x59;
+ public final static int VK_Z = 0x5A;
+
+ public final static int VK_LWIN = 0x5B;
+ public final static int VK_RWIN = 0x5C;
+ public final static int VK_APPS = 0x5D;
+/*
+ * 0x5E : reserved;
+ */
+
+ public final static int VK_SLEEP = 0x5F;
+
+ public final static int VK_NUMPAD0 = 0x60;
+ public final static int VK_NUMPAD1 = 0x61;
+ public final static int VK_NUMPAD2 = 0x62;
+ public final static int VK_NUMPAD3 = 0x63;
+ public final static int VK_NUMPAD4 = 0x64;
+ public final static int VK_NUMPAD5 = 0x65;
+ public final static int VK_NUMPAD6 = 0x66;
+ public final static int VK_NUMPAD7 = 0x67;
+ public final static int VK_NUMPAD8 = 0x68;
+ public final static int VK_NUMPAD9 = 0x69;
+ public final static int VK_MULTIPLY = 0x6A;
+ public final static int VK_ADD = 0x6B;
+ public final static int VK_SEPARATOR = 0x6C;
+ public final static int VK_SUBTRACT = 0x6D;
+ public final static int VK_DECIMAL = 0x6E;
+ public final static int VK_DIVIDE = 0x6F;
+ public final static int VK_F1 = 0x70;
+ public final static int VK_F2 = 0x71;
+ public final static int VK_F3 = 0x72;
+ public final static int VK_F4 = 0x73;
+ public final static int VK_F5 = 0x74;
+ public final static int VK_F6 = 0x75;
+ public final static int VK_F7 = 0x76;
+ public final static int VK_F8 = 0x77;
+ public final static int VK_F9 = 0x78;
+ public final static int VK_F10 = 0x79;
+ public final static int VK_F11 = 0x7A;
+ public final static int VK_F12 = 0x7B;
+ public final static int VK_F13 = 0x7C;
+ public final static int VK_F14 = 0x7D;
+ public final static int VK_F15 = 0x7E;
+ public final static int VK_F16 = 0x7F;
+ public final static int VK_F17 = 0x80;
+ public final static int VK_F18 = 0x81;
+ public final static int VK_F19 = 0x82;
+ public final static int VK_F20 = 0x83;
+ public final static int VK_F21 = 0x84;
+ public final static int VK_F22 = 0x85;
+ public final static int VK_F23 = 0x86;
+ public final static int VK_F24 = 0x87;
+
+/*
+ * 0x88 - 0x8F : unassigned;
+ */
+
+ public final static int VK_NUMLOCK = 0x90;
+ public final static int VK_SCROLL = 0x91;
+
+/*
+ * NEC PC-9800 kbd definitions
+ */
+ public final static int VK_OEM_NEC_EQUAL = 0x92; // '=' key on numpad
+/*
+ * Fujitsu/OASYS kbd definitions
+ */
+ public final static int VK_OEM_FJ_JISHO = 0x92; // 'Dictionary' key
+ public final static int VK_OEM_FJ_MASSHOU = 0x93; // 'Unregister word' key
+ public final static int VK_OEM_FJ_TOUROKU = 0x94; // 'Register word' key
+ public final static int VK_OEM_FJ_LOYA = 0x95; // 'Left OYAYUBI' key
+ public final static int VK_OEM_FJ_ROYA = 0x96; // 'Right OYAYUBI' key
+
+/*
+ * 0x97 - 0x9F : unassigned
+ */
+
+/*
+ * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
+ * Used only as parameters to GetAsyncKeyState() and GetKeyState().
+ * No other API or message will distinguish left and right keys in this way.
+ */
+ public final static int VK_LSHIFT = 0xA0;
+ public final static int VK_RSHIFT = 0xA1;
+ public final static int VK_LCONTROL = 0xA2;
+ public final static int VK_RCONTROL = 0xA3;
+ public final static int VK_LMENU = 0xA4;
+ public final static int VK_RMENU = 0xA5;
+
+ public final static int VK_BROWSER_BACK = 0xA6;
+ public final static int VK_BROWSER_FORWARD = 0xA7;
+ public final static int VK_BROWSER_REFRESH = 0xA8;
+ public final static int VK_BROWSER_STOP = 0xA9;
+ public final static int VK_BROWSER_SEARCH = 0xAA;
+ public final static int VK_BROWSER_FAVORITES = 0xAB;
+ public final static int VK_BROWSER_HOME = 0xAC;
+
+ public final static int VK_VOLUME_MUTE = 0xAD;
+ public final static int VK_VOLUME_DOWN = 0xAE;
+ public final static int VK_VOLUME_UP = 0xAF;
+ public final static int VK_MEDIA_NEXT_TRACK = 0xB0;
+ public final static int VK_MEDIA_PREV_TRACK = 0xB1;
+ public final static int VK_MEDIA_STOP = 0xB2;
+ public final static int VK_MEDIA_PLAY_PAUSE = 0xB3;
+ public final static int VK_LAUNCH_MAIL = 0xB4;
+ public final static int VK_LAUNCH_MEDIA_SELECT = 0xB5;
+ public final static int VK_LAUNCH_APP1 = 0xB6;
+ public final static int VK_LAUNCH_APP2 = 0xB7;
+
+/*
+ * 0xB8 - 0xB9 : reserved
+ */
+
+ public final static int VK_OEM_1 = 0xBA; // ';:' for US
+ public final static int VK_OEM_PLUS = 0xBB; // '+' any country
+ public final static int VK_OEM_COMMA = 0xBC; // ',' any country
+ public final static int VK_OEM_MINUS = 0xBD; // '-' any country
+ public final static int VK_OEM_PERIOD = 0xBE; // '.' any country
+ public final static int VK_OEM_2 = 0xBF; // '/?' for US
+ public final static int VK_OEM_3 = 0xC0; // '`~' for US
+
+/*
+ * 0xC1 - 0xD7 : reserved
+ */
+
+/*
+ * 0xD8 - 0xDA : unassigned
+ */
+
+ public final static int VK_OEM_4 = 0xDB; // '[{' for US
+ public final static int VK_OEM_5 = 0xDC; // '\|' for US
+ public final static int VK_OEM_6 = 0xDD; // ']}' for US
+ public final static int VK_OEM_7 = 0xDE; // ''"' for US
+ public final static int VK_OEM_8 = 0xDF;
+
+/*
+ * 0xE0 : reserved
+ */
+
+/*
+ * Various extended or enhanced keyboards
+ */
+ public final static int VK_OEM_AX = 0xE1; // 'AX' key on Japanese AX kbd
+ public final static int VK_OEM_102 = 0xE2; // "<>" or "\|" on RT 102-key kbd.
+ public final static int VK_ICO_HELP = 0xE3; // Help key on ICO
+ public final static int VK_ICO_00 = 0xE4; // 00 key on ICO
+
+ public final static int VK_PROCESSKEY = 0xE5;
+
+ public final static int VK_ICO_CLEAR = 0xE6;
+
+
+ public final static int VK_PACKET = 0xE7;
+
+/*
+ * 0xE8 : unassigned
+ */
+
+/*
+ * Nokia/Ericsson definitions
+ */
+ public final static int VK_OEM_RESET = 0xE9;
+ public final static int VK_OEM_JUMP = 0xEA;
+ public final static int VK_OEM_PA1 = 0xEB;
+ public final static int VK_OEM_PA2 = 0xEC;
+ public final static int VK_OEM_PA3 = 0xED;
+ public final static int VK_OEM_WSCTRL = 0xEE;
+ public final static int VK_OEM_CUSEL = 0xEF;
+ public final static int VK_OEM_ATTN = 0xF0;
+ public final static int VK_OEM_FINISH = 0xF1;
+ public final static int VK_OEM_COPY = 0xF2;
+ public final static int VK_OEM_AUTO = 0xF3;
+ public final static int VK_OEM_ENLW = 0xF4;
+ public final static int VK_OEM_BACKTAB = 0xF5;
+
+ public final static int VK_ATTN = 0xF6;
+ public final static int VK_CRSEL = 0xF7;
+ public final static int VK_EXSEL = 0xF8;
+ public final static int VK_EREOF = 0xF9;
+ public final static int VK_PLAY = 0xFA;
+ public final static int VK_ZOOM = 0xFB;
+ public final static int VK_NONAME = 0xFC;
+ public final static int VK_PA1 = 0xFD;
+ public final static int VK_OEM_CLEAR = 0xFE;
+
+ public static int mapVirtualKeyToLWJGLCode(int virt_key) {
+ switch (virt_key) {
+ case VK_ESCAPE:
+ return Keyboard.KEY_ESCAPE;
+ case VK_1:
+ return Keyboard.KEY_1;
+ case VK_2:
+ return Keyboard.KEY_2;
+ case VK_3:
+ return Keyboard.KEY_3;
+ case VK_4:
+ return Keyboard.KEY_4;
+ case VK_5:
+ return Keyboard.KEY_5;
+ case VK_6:
+ return Keyboard.KEY_6;
+ case VK_7:
+ return Keyboard.KEY_7;
+ case VK_8:
+ return Keyboard.KEY_8;
+ case VK_9:
+ return Keyboard.KEY_9;
+ case VK_0:
+ return Keyboard.KEY_0;
+ case VK_OEM_MINUS:
+ return Keyboard.KEY_MINUS;
+ case VK_OEM_PLUS:
+ return Keyboard.KEY_EQUALS;
+ case VK_BACK:
+ return Keyboard.KEY_BACK;
+ case VK_TAB:
+ return Keyboard.KEY_TAB;
+ case VK_Q:
+ return Keyboard.KEY_Q;
+ case VK_W:
+ return Keyboard.KEY_W;
+ case VK_E:
+ return Keyboard.KEY_E;
+ case VK_R:
+ return Keyboard.KEY_R;
+ case VK_T:
+ return Keyboard.KEY_T;
+ case VK_Y:
+ return Keyboard.KEY_Y;
+ case VK_U:
+ return Keyboard.KEY_U;
+ case VK_I:
+ return Keyboard.KEY_I;
+ case VK_O:
+ return Keyboard.KEY_O;
+ case VK_P:
+ return Keyboard.KEY_P;
+ case VK_OEM_4:
+ return Keyboard.KEY_LBRACKET;
+ case VK_OEM_6:
+ return Keyboard.KEY_RBRACKET;
+ case VK_RETURN:
+ return Keyboard.KEY_RETURN;
+ case VK_LCONTROL:
+ return Keyboard.KEY_LCONTROL;
+ case VK_A:
+ return Keyboard.KEY_A;
+ case VK_S:
+ return Keyboard.KEY_S;
+ case VK_D:
+ return Keyboard.KEY_D;
+ case VK_F:
+ return Keyboard.KEY_F;
+ case VK_G:
+ return Keyboard.KEY_G;
+ case VK_H:
+ return Keyboard.KEY_H;
+ case VK_J:
+ return Keyboard.KEY_J;
+ case VK_K:
+ return Keyboard.KEY_K;
+ case VK_L:
+ return Keyboard.KEY_L;
+ case VK_OEM_1:
+ return Keyboard.KEY_SEMICOLON;
+ case VK_OEM_7:
+ return Keyboard.KEY_APOSTROPHE;
+ case VK_OEM_3:
+ case VK_OEM_8:
+ return Keyboard.KEY_GRAVE;
+ case VK_LSHIFT:
+ return Keyboard.KEY_LSHIFT;
+ case VK_OEM_5:
+ return Keyboard.KEY_BACKSLASH;
+ case VK_Z:
+ return Keyboard.KEY_Z;
+ case VK_X:
+ return Keyboard.KEY_X;
+ case VK_C:
+ return Keyboard.KEY_C;
+ case VK_V:
+ return Keyboard.KEY_V;
+ case VK_B:
+ return Keyboard.KEY_B;
+ case VK_N:
+ return Keyboard.KEY_N;
+ case VK_M:
+ return Keyboard.KEY_M;
+ case VK_OEM_COMMA:
+ return Keyboard.KEY_COMMA;
+ case VK_OEM_PERIOD:
+ return Keyboard.KEY_PERIOD;
+ case VK_OEM_2:
+ return Keyboard.KEY_SLASH;
+ case VK_RSHIFT:
+ return Keyboard.KEY_RSHIFT;
+ case VK_MULTIPLY:
+ return Keyboard.KEY_MULTIPLY;
+ case VK_LMENU:
+ return Keyboard.KEY_LMENU;
+ case VK_SPACE:
+ return Keyboard.KEY_SPACE;
+ case VK_CAPITAL:
+ return Keyboard.KEY_CAPITAL;
+ case VK_F1:
+ return Keyboard.KEY_F1;
+ case VK_F2:
+ return Keyboard.KEY_F2;
+ case VK_F3:
+ return Keyboard.KEY_F3;
+ case VK_F4:
+ return Keyboard.KEY_F4;
+ case VK_F5:
+ return Keyboard.KEY_F5;
+ case VK_F6:
+ return Keyboard.KEY_F6;
+ case VK_F7:
+ return Keyboard.KEY_F7;
+ case VK_F8:
+ return Keyboard.KEY_F8;
+ case VK_F9:
+ return Keyboard.KEY_F9;
+ case VK_F10:
+ return Keyboard.KEY_F10;
+ case VK_NUMLOCK:
+ return Keyboard.KEY_NUMLOCK;
+ case VK_SCROLL:
+ return Keyboard.KEY_SCROLL;
+ case VK_NUMPAD7:
+ return Keyboard.KEY_NUMPAD7;
+ case VK_NUMPAD8:
+ return Keyboard.KEY_NUMPAD8;
+ case VK_NUMPAD9:
+ return Keyboard.KEY_NUMPAD9;
+ case VK_SUBTRACT:
+ return Keyboard.KEY_SUBTRACT;
+ case VK_NUMPAD4:
+ return Keyboard.KEY_NUMPAD4;
+ case VK_NUMPAD5:
+ return Keyboard.KEY_NUMPAD5;
+ case VK_NUMPAD6:
+ return Keyboard.KEY_NUMPAD6;
+ case VK_ADD:
+ return Keyboard.KEY_ADD;
+ case VK_NUMPAD1:
+ return Keyboard.KEY_NUMPAD1;
+ case VK_NUMPAD2:
+ return Keyboard.KEY_NUMPAD2;
+ case VK_NUMPAD3:
+ return Keyboard.KEY_NUMPAD3;
+ case VK_NUMPAD0:
+ return Keyboard.KEY_NUMPAD0;
+ case VK_DECIMAL:
+ return Keyboard.KEY_DECIMAL;
+ case VK_F11:
+ return Keyboard.KEY_F11;
+ case VK_F12:
+ return Keyboard.KEY_F12;
+ case VK_F13:
+ return Keyboard.KEY_F13;
+ case VK_F14:
+ return Keyboard.KEY_F14;
+ case VK_F15:
+ return Keyboard.KEY_F15;
+ case VK_KANA:
+ return Keyboard.KEY_KANA;
+ case VK_CONVERT:
+ return Keyboard.KEY_CONVERT;
+ case VK_NONCONVERT:
+ return Keyboard.KEY_NOCONVERT;
+/* case VK_YEN:
+ return Keyboard.KEY_YEN;
+ case VK_NUMPADEQUALS:
+ return Keyboard.KEY_NUMPADEQUALS;
+ case VK_CIRCUMFLEX:
+ return Keyboard.KEY_CIRCUMFLEX;
+ case VK_AT:
+ return Keyboard.KEY_AT;
+ case VK_COLON:
+ return Keyboard.KEY_COLON;
+ case VK_UNDERLINE:
+ return Keyboard.KEY_UNDERLINE;*/
+ case VK_KANJI:
+ return Keyboard.KEY_KANJI;
+/* case VK_STOP:
+ return Keyboard.KEY_STOP;
+ case VK_AX:
+ return Keyboard.KEY_AX;
+ case VK_UNLABELED:
+ return Keyboard.KEY_UNLABELED;
+ case VK_NUMPADENTER:
+ return Keyboard.KEY_NUMPADENTER;*/
+ case VK_RCONTROL:
+ return Keyboard.KEY_RCONTROL;
+ case VK_SEPARATOR:
+ return Keyboard.KEY_NUMPADCOMMA;
+ case VK_DIVIDE:
+ return Keyboard.KEY_DIVIDE;
+ case VK_SNAPSHOT:
+ return Keyboard.KEY_SYSRQ;
+ case VK_RMENU:
+ return Keyboard.KEY_RMENU;
+ case VK_PAUSE:
+ return Keyboard.KEY_PAUSE;
+ case VK_HOME:
+ return Keyboard.KEY_HOME;
+ case VK_UP:
+ return Keyboard.KEY_UP;
+ case VK_PRIOR:
+ return Keyboard.KEY_PRIOR;
+ case VK_LEFT:
+ return Keyboard.KEY_LEFT;
+ case VK_RIGHT:
+ return Keyboard.KEY_RIGHT;
+ case VK_END:
+ return Keyboard.KEY_END;
+ case VK_DOWN:
+ return Keyboard.KEY_DOWN;
+ case VK_NEXT:
+ return Keyboard.KEY_NEXT;
+ case VK_INSERT:
+ return Keyboard.KEY_INSERT;
+ case VK_DELETE:
+ return Keyboard.KEY_DELETE;
+ case VK_LWIN:
+ return Keyboard.KEY_LMETA;
+ case VK_RWIN:
+ return Keyboard.KEY_RMETA;
+ case VK_APPS:
+ return Keyboard.KEY_APPS;
+/* case VK_POWER:
+ return Keyboard.KEY_POWER;*/
+ case VK_SLEEP:
+ return Keyboard.KEY_SLEEP;
+ default:
+ return Keyboard.KEY_NONE;
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsMouse.java b/src/java/org/lwjgl/opengl/WindowsMouse.java
new file mode 100644
index 0000000..6aa3354
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsMouse.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is the Windows implementation of the Mouse.
+ * @author elias_naur
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.input.Mouse;
+
+final class WindowsMouse {
+ private final long hwnd;
+
+ private final int mouse_button_count;
+ private final boolean has_wheel;
+
+ private final EventQueue event_queue = new EventQueue(Mouse.EVENT_SIZE);
+
+ private final ByteBuffer mouse_event = ByteBuffer.allocate(Mouse.EVENT_SIZE);
+ private final Object blank_cursor;
+
+ private boolean mouse_grabbed;
+ private byte[] button_states;
+ private int accum_dx;
+ private int accum_dy;
+ private int accum_dwheel;
+ private int last_x;
+ private int last_y;
+
+ WindowsMouse(long hwnd) throws LWJGLException {
+ this.hwnd = hwnd;
+ this.mouse_button_count = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_CMOUSEBUTTONS);
+ this.has_wheel = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_MOUSEWHEELPRESENT) != 0;
+ this.blank_cursor = createBlankCursor();
+ this.button_states = new byte[mouse_button_count];
+ }
+
+ private Object createBlankCursor() throws LWJGLException {
+ int width = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_CXCURSOR);
+ int height = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_CYCURSOR);
+ IntBuffer pixels = BufferUtils.createIntBuffer(width*height);
+ return WindowsDisplay.doCreateCursor(width, height, 0, 0, 1, pixels, null);
+ }
+
+ public boolean isGrabbed() {
+ return mouse_grabbed;
+ }
+
+ public boolean hasWheel() {
+ return has_wheel;
+ }
+
+ public int getButtonCount() {
+ return mouse_button_count;
+ }
+
+ public void poll(IntBuffer coord_buffer, ByteBuffer buttons) {
+ for (int i = 0; i < coord_buffer.remaining(); i++)
+ coord_buffer.put(coord_buffer.position() + i, 0);
+ int num_buttons = mouse_button_count;
+ coord_buffer.put(coord_buffer.position() + 2, accum_dwheel);
+ if (num_buttons > button_states.length)
+ num_buttons = button_states.length;
+ for (int j = 0; j < num_buttons; j++) {
+ buttons.put(buttons.position() + j, button_states[j]);
+ }
+ if (isGrabbed()) {
+ coord_buffer.put(coord_buffer.position() + 0, accum_dx);
+ coord_buffer.put(coord_buffer.position() + 1, accum_dy);
+ } else {
+ coord_buffer.put(coord_buffer.position() + 0, last_x);
+ coord_buffer.put(coord_buffer.position() + 1, last_y);
+ }
+ accum_dx = accum_dy = accum_dwheel = 0;
+ }
+
+ private void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) {
+ mouse_event.clear();
+ mouse_event.put(button).put(state).putInt(coord1).putInt(coord2).putInt(dz).putLong(nanos);
+ mouse_event.flip();
+ event_queue.putEvent(mouse_event);
+ }
+
+ private void putMouseEvent(byte button, byte state, int dz, long nanos) {
+ if (mouse_grabbed)
+ putMouseEventWithCoords(button, state, 0, 0, dz, nanos);
+ else
+ putMouseEventWithCoords(button, state, last_x, last_y, dz, nanos);
+ }
+
+ public void read(ByteBuffer buffer) {
+ event_queue.copyEvents(buffer);
+ }
+
+ public Object getBlankCursor() {
+ return blank_cursor;
+ }
+
+ public void grab(boolean grab, boolean should_center) {
+ if (grab) {
+ if (!mouse_grabbed) {
+ mouse_grabbed = true;
+ if (should_center) {
+ try {
+ WindowsDisplay.setupCursorClipping(hwnd);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to setup cursor clipping: " + e);
+ }
+ centerCursor();
+ }
+ }
+ } else {
+ if (mouse_grabbed) {
+ mouse_grabbed = false;
+ WindowsDisplay.resetCursorClipping();
+ }
+ }
+ event_queue.clearEvents();
+ }
+
+ public void handleMouseScrolled(int event_dwheel, long millis) {
+ accum_dwheel += event_dwheel;
+ putMouseEvent((byte)-1, (byte)0, event_dwheel, millis*1000000);
+ }
+
+ private void centerCursor() {
+ WindowsDisplay.centerCursor(hwnd);
+ }
+
+ public void setPosition(int x, int y) {
+ this.last_x = x;
+ this.last_y = y;
+ }
+
+ public void destroy() {
+ WindowsDisplay.doDestroyCursor(blank_cursor);
+ }
+
+ public void handleMouseMoved(int x, int y, long millis, boolean should_center) {
+ int dx = x - last_x;
+ int dy = y - last_y;
+ if (dx != 0 || dy != 0) {
+ accum_dx += dx;
+ accum_dy += dy;
+ last_x = x;
+ last_y = y;
+ long nanos = millis*1000000;
+ if (mouse_grabbed) {
+ putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos);
+ if (should_center)
+ centerCursor();
+ } else {
+ putMouseEventWithCoords((byte)-1, (byte)0, x, y, 0, nanos);
+ }
+ }
+ }
+
+ public void handleMouseButton(byte button, byte state, long millis) {
+ putMouseEvent(button, state, 0, millis*1000000);
+ if (button < button_states.length)
+ button_states[button] = state != 0 ? (byte)1 : (byte)0;
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsPbufferPeerInfo.java b/src/java/org/lwjgl/opengl/WindowsPbufferPeerInfo.java
new file mode 100644
index 0000000..967dd84
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsPbufferPeerInfo.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2002-2008 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 java.nio.IntBuffer;
+
+import org.lwjgl.LWJGLException;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: WindowsPbufferPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+final class WindowsPbufferPeerInfo extends WindowsPeerInfo {
+ WindowsPbufferPeerInfo(int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs) throws LWJGLException {
+ nCreate(getHandle(), width, height, pixel_format, pixelFormatCaps, pBufferAttribs);
+ }
+ private static native void nCreate(ByteBuffer handle, int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs) throws LWJGLException;
+
+ public boolean isBufferLost() {
+ return nIsBufferLost(getHandle());
+ }
+ private static native boolean nIsBufferLost(ByteBuffer handle);
+
+ public void setPbufferAttrib(int attrib, int value) {
+ nSetPbufferAttrib(getHandle(), attrib, value);
+ }
+ private static native void nSetPbufferAttrib(ByteBuffer handle, int attrib, int value);
+
+ public void bindTexImageToPbuffer(int buffer) {
+ nBindTexImageToPbuffer(getHandle(), buffer);
+ }
+ private static native void nBindTexImageToPbuffer(ByteBuffer handle, int buffer);
+
+ public void releaseTexImageFromPbuffer(int buffer) {
+ nReleaseTexImageFromPbuffer(getHandle(), buffer);
+ }
+ private static native void nReleaseTexImageFromPbuffer(ByteBuffer handle, int buffer);
+
+ public void destroy() {
+ nDestroy(getHandle());
+ }
+ private static native void nDestroy(ByteBuffer handle);
+
+ protected void doLockAndInitHandle() throws LWJGLException {
+ // NO-OP
+ }
+
+ protected void doUnlock() throws LWJGLException {
+ // NO-OP
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsPeerInfo.java b/src/java/org/lwjgl/opengl/WindowsPeerInfo.java
new file mode 100644
index 0000000..d3533c5
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsPeerInfo.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2002-2008 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 java.nio.IntBuffer;
+
+import org.lwjgl.LWJGLException;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3116 $
+ * $Id: WindowsPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ */
+abstract class WindowsPeerInfo extends PeerInfo {
+ protected WindowsPeerInfo() {
+ super(createHandle());
+ }
+ private static native ByteBuffer createHandle();
+
+ protected static int choosePixelFormat(long hdc, int origin_x, int origin_y, PixelFormat pixel_format, IntBuffer pixel_format_caps, boolean use_hdc_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException {
+ return nChoosePixelFormat(hdc, origin_x, origin_y, pixel_format, pixel_format_caps, use_hdc_bpp, support_window, support_pbuffer, double_buffered);
+ }
+ private static native int nChoosePixelFormat(long hdc, int origin_x, int origin_y, PixelFormat pixel_format, IntBuffer pixel_format_caps, boolean use_hdc_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException;
+ protected static native void setPixelFormat(long hdc, int pixel_format) throws LWJGLException;
+
+ public final long getHdc() {
+ return nGetHdc(getHandle());
+ }
+ private static native long nGetHdc(ByteBuffer handle);
+
+ public final long getHwnd() {
+ return nGetHwnd(getHandle());
+ }
+ private static native long nGetHwnd(ByteBuffer handle);
+}
diff --git a/src/java/org/lwjgl/opengl/WindowsRegistry.java b/src/java/org/lwjgl/opengl/WindowsRegistry.java
new file mode 100644
index 0000000..f39c3a3
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsRegistry.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2002-2008 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;
+
+/**
+ * This is an interface to the windows registry
+ * @author elias_naur
+ */
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.Sys;
+
+final class WindowsRegistry {
+ final static int HKEY_CLASSES_ROOT = 1;
+ final static int HKEY_CURRENT_USER = 2;
+ final static int HKEY_LOCAL_MACHINE = 3;
+ final static int HKEY_USERS = 4;
+
+ static {
+ Sys.initialize();
+ }
+
+ /**
+ * Query the registry value specified by the root key, subkey, value tuple
+ */
+ static String queryRegistrationKey(int root_key, String subkey, String value) throws LWJGLException {
+ switch (root_key) {
+ case HKEY_CLASSES_ROOT:
+ case HKEY_CURRENT_USER:
+ case HKEY_LOCAL_MACHINE:
+ case HKEY_USERS:
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid enum: " + root_key);
+ }
+ return nQueryRegistrationKey(root_key, subkey, value);
+ }
+
+ private static native String nQueryRegistrationKey(int root_key, String subkey, String value) throws LWJGLException;
+}
diff --git a/src/java/org/lwjgl/opengl/XRandR.java b/src/java/org/lwjgl/opengl/XRandR.java
new file mode 100644
index 0000000..d9876b9
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/XRandR.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2002-2010 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.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Utility for working with the xrandr commmand-line utility. Assumes
+ * xrandr v1.2 or higher.
+ *
+ * @author ryanm
+ */
+public class XRandR {
+
+ private static Screen[] current;
+
+ private static Map /* */screens;
+
+ private static void populate() {
+ if (screens == null) {
+ screens = new HashMap/* */();
+
+ // ProcessBuilder pb = new ProcessBuilder( "xrandr", "-q" );
+ // pb.redirectErrorStream();
+ try {
+ // Process p= pb.start();
+ Process p = Runtime.getRuntime().exec(new String[] { "xrandr", "-q"});
+
+ List/* */currentList = new ArrayList/* */();
+ List/* */possibles = new ArrayList/* */();
+ String name = null;
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+ String[] sa = line.split("\\s+");
+
+ if (sa[1].equals("connected")) {
+ // found a new screen block
+ if (name != null) {
+ screens.put(name, possibles.toArray(new Screen[possibles.size()]));
+ possibles.clear();
+ }
+ name = sa[0];
+
+ // record the current config
+ currentList.add(new Screen(name, sa[2]));
+ } else if (Pattern.matches("\\d*x\\d*", sa[0])) {
+ // found a new mode line
+ possibles.add(new Screen(name, sa[0]));
+ }
+ }
+
+ screens.put(name, possibles.toArray(new Screen[possibles.size()]));
+
+ current = (Screen[]) currentList.toArray(new Screen[currentList.size()]);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * @return The current screen configuration, or an empty array if
+ * xrandr is not supported
+ */
+ public static Screen[] getConfiguration() {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ populate();
+ return null;
+ }
+ });
+
+ return (Screen[]) current.clone();
+ }
+
+ /**
+ * @param screens
+ * The desired screen set, may not be null
+ */
+ public static void setConfiguration(Screen[]/* ... */screens) {
+ if (screens.length == 0) {
+ throw new IllegalArgumentException("Must specify at least one screen");
+ }
+
+ List/* */cmd = new ArrayList/* */();
+ cmd.add("xrandr");
+
+ // switch off those in the current set not in the new set
+ for (int i = 0; i < current.length; i++) {
+ boolean found = false;
+ for (int j = 0; j < screens.length; j++) {
+ if (screens[j].name.equals(current[i].name)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ cmd.add("--output");
+ cmd.add(current[i].name);
+ cmd.add("--off");
+ }
+ }
+
+ // set up new set
+ for (int i = 0; i < screens.length; i++) {
+ screens[i].getArgs(cmd);
+ }
+
+ try {
+ // ProcessBuilder pb = new ProcessBuilder( cmd );
+ // pb.redirectErrorStream();
+ // Process p = pb.start();
+ Process p = Runtime.getRuntime().exec((String[]) cmd.toArray(new String[cmd.size()]));
+ // no output is expected, but check anyway
+ BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ current = screens;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * @return the name of connected screens, or an empty array if
+ * xrandr is not supported
+ */
+ public static String[] getScreenNames() {
+ populate();
+ return (String[]) screens.keySet().toArray(new String[screens.size()]);
+ }
+
+ /**
+ * @param name
+ * @return the possible resolutions of the named screen, or
+ * null
if there is no such screen
+ */
+ public static Screen[] getResolutions(String name) {
+ populate();
+ // clone the array to prevent held copies being altered
+ return (Screen[]) ((Screen[]) screens.get(name)).clone();
+ }
+
+ /**
+ * Encapsulates the configuration of a monitor. Resolution is
+ * fixed, position is mutable
+ *
+ * @author ryanm
+ */
+ public static class Screen implements Cloneable {
+
+ /**
+ * Name for this output
+ */
+ public final String name;
+
+ /**
+ * Width in pixels
+ */
+ public final int width;
+
+ /**
+ * Height in pixels
+ */
+ public final int height;
+
+ /**
+ * Position on the x-axis, in pixels
+ */
+ public int xPos = 0;
+
+ /**
+ * Position on the y-axis, in pixels
+ */
+ public int yPos = 0;
+
+ /**
+ * @param name
+ * name of the screen
+ * @param conf
+ * config string, format either widthxheight or
+ * widthxheight+xPos+yPos
+ */
+ private Screen(String name, String conf) {
+ this.name = name;
+
+ String[] sa = conf.split("\\D");
+ width = Integer.parseInt(sa[0]);
+ height = Integer.parseInt(sa[1]);
+
+ if (sa.length > 2) {
+ xPos = Integer.parseInt(sa[2]);
+ yPos = Integer.parseInt(sa[3]);
+ }
+ }
+
+ private void getArgs(List/* */argList) {
+ argList.add("--output");
+ argList.add(name);
+ argList.add("--mode");
+ argList.add(width + "x" + height);
+ argList.add("--pos");
+ argList.add(xPos + "x" + yPos);
+ }
+
+ // @Override
+ public String toString() {
+ return name + " " + width + "x" + height + " @ " + xPos + "x" + yPos;
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/test/DisplayTest.java b/src/java/org/lwjgl/test/DisplayTest.java
new file mode 100644
index 0000000..7d6abf7
--- /dev/null
+++ b/src/java/org/lwjgl/test/DisplayTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2002-2008 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.test;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+
+/**
+ *
+ * Test class for Display & DisplayMode
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: DisplayTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class DisplayTest {
+
+ /**
+ * Creates a new DisplayTest
+ */
+ public DisplayTest() {
+ }
+
+ /**
+ * Runs the tests
+ */
+ public void executeTest() throws LWJGLException {
+ currentTest();
+ queryModesTest();
+ setDisplayModeTest();
+ setDisplayConfigurationTest();
+ }
+
+ /**
+ * Prints some info about the current mode
+ */
+ private void currentTest() {
+ System.out.println("==== Test Current ====");
+
+ System.out.println("Info about current:");
+ System.out.println("Graphics card: " + Display.getAdapter() + ", version: " + Display.getVersion());
+ System.out.println("Resolution: " +
+ Display.getDisplayMode().getWidth() + "x" +
+ Display.getDisplayMode().getHeight() + "x" +
+ Display.getDisplayMode().getBitsPerPixel() + "@" +
+ Display.getDisplayMode().getFrequency() + "Hz");
+ System.out.println("---- Test Current ----");
+ }
+
+ /**
+ * Tests querying for modes
+ */
+ private void queryModesTest() throws LWJGLException {
+ DisplayMode[] modes = null;
+
+ System.out.println("==== Test query ====");
+ System.out.println("Retrieving available displaymodes");
+ modes = Display.getAvailableDisplayModes();
+
+ // no modes check
+ if (modes == null) {
+ System.out.println("FATAL: unable to find any modes!");
+ System.exit(-1);
+ }
+
+ // write some info
+ System.out.println("Found " + modes.length + " modes");
+ System.out.println("The first 5 are:");
+ for(int i=0;i
+ * Simple test that just checks that the native library loads
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: SysTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class NativeTest {
+
+ public void invokeSys() {
+ Sys.getVersion();
+ }
+
+ /**
+ * Entry point for test
+ *
+ * @param args ignored
+ */
+ public static void main(String[] args) {
+ // try to "load" awt - work around for headless issue on linux
+ Toolkit.getDefaultToolkit();
+ new NativeTest().invokeSys();
+ System.out.println("OK");
+ }
+}
diff --git a/src/java/org/lwjgl/test/SysTest.java b/src/java/org/lwjgl/test/SysTest.java
new file mode 100644
index 0000000..97fe6a4
--- /dev/null
+++ b/src/java/org/lwjgl/test/SysTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2002-2008 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.test;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+import org.lwjgl.opengl.Display;
+
+/**
+ *
+ * Test class for Sys
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: SysTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class SysTest {
+
+ /**
+ * Creates a new SysTest
+ */
+ public SysTest() {
+ }
+
+ /**
+ * Runs the tests
+ */
+ public void executeTest() {
+ testAlert();
+ testDebug();
+ testTimer();
+ testUrl();
+ testClipboard();
+ }
+
+ /**
+ * Tests debug mode
+ */
+ private void testDebug() {
+ System.out.println("==== Test Debug ====");
+ if (LWJGLUtil.DEBUG) {
+ LWJGLUtil.log("Debug is enabled, you should now see output from LWJGL during the following tests.");
+ } else {
+ System.out.println("Debug is not enabled. Please set the org.lwjgl.Sys.debug property to true to enable debugging");
+ System.out.println("Example:\n java -Dorg.lwjgl.util.Debug=true ...");
+ System.out.println("You will not see any debug output in the following tests.");
+ }
+
+ // get some display modes, to force some debug info
+ try {
+ Display.getAvailableDisplayModes();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+
+ System.out.println("---- Test Debug ----\n");
+ }
+
+ /**
+ * Tests the timer
+ */
+ private void testTimer() {
+ long resolution = Sys.getTimerResolution();
+ long time = Sys.getTime();
+
+ System.out.println("==== Test Timer ====");
+ System.out.println("Resolution of timer (ticks per second): " + resolution);
+ System.out.println("Current time: " + time);
+ System.out.println("Sleeping for 2 seconds, using Thread.sleep()");
+
+ pause(2000);
+
+ long time2 = Sys.getTime();
+ System.out.println("Current time: " + time2);
+ System.out.println("Actually slept for: " + ((time2 - time) / (float) resolution) + " seconds");
+ System.out.println("---- Test Timer ----\n");
+ }
+
+ /**
+ * Tests the alert
+ */
+ private void testAlert() {
+ System.out.println("==== Test Alert ====");
+
+ System.out.println("Opening native alert window");
+ Sys.alert("SysTest", "Hello World!");
+
+ System.out.println("---- Test Alert ----\n");
+ }
+
+ /**
+ * Tests the openUrl
+ */
+ private void testUrl() {
+ System.out.println("==== Test URL ====");
+
+ System.out.println("Opening a browser window to http://www.lwjgl.org");
+ Sys.openURL("http://www.lwjgl.org");
+
+ System.out.println("---- Test URL ----\n");
+ }
+
+ /**
+ * Busy waits for a specified number of seconds
+ *
+ * @param priority Priority to busy wait in
+ * @param seconds Number of seconds to busy wait
+ * @param message Message to print to user
+ */
+ private void busyWait(int priority, int seconds, String message) {
+ long future = Sys.getTime() + (Sys.getTimerResolution() * seconds);
+
+ System.out.print(message);
+
+ // waste some cycles
+ while (Sys.getTime() < future) {
+ }
+
+ System.out.println("done");
+ }
+
+ /**
+ * Pause current thread for a specified time
+ *
+ * @param time milliseconds to sleep
+ */
+ private void pause(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException inte) {
+ }
+ }
+
+ /**
+ * Tests the clipboard. Helps to have something in it first...
+ */
+ private void testClipboard() {
+ System.out.println("Contents of clipboard: '"+Sys.getClipboard()+"'");
+ }
+
+ /**
+ * Tests the Sys class, and serves as basic usage test
+ *
+ * @param args ignored
+ */
+ public static void main(String[] args) {
+ new SysTest().executeTest();
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/WaveDataTest.java b/src/java/org/lwjgl/test/WaveDataTest.java
new file mode 100644
index 0000000..43abc99
--- /dev/null
+++ b/src/java/org/lwjgl/test/WaveDataTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2002-2010 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.test;
+
+import java.io.File;
+
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.util.WaveData;
+
+/**
+ *
+ * Test class WaveDataTest
+ *
+ * @author Brian Matzon
+ */
+public class WaveDataTest {
+
+ String filePath = "Footsteps.wav";
+
+ /**
+ * Creates a new DisplayTest
+ */
+ public WaveDataTest() {
+ }
+
+ /**
+ * Runs the tests
+ */
+ public void executeTest() throws LWJGLException {
+ executeCreationTest();
+ executeBrokenCreationTest();
+ executeMidStreamCreationTest();
+ }
+
+
+ private void executeCreationTest() {
+ WaveData wd = WaveData.create(filePath);
+ if(wd != null) {
+ System.out.println("executeCreationTest::success");
+ }
+ }
+
+ private void executeBrokenCreationTest() {
+ WaveData wd = WaveData.create("");
+ if(wd == null) {
+ System.out.println("executeBrokenCreationTest::success");
+ }
+ }
+
+ private void executeStreamCreationTest() {
+ try {
+ AudioInputStream ais = AudioSystem.getAudioInputStream(new File(filePath));
+ WaveData wd = WaveData.create(ais);
+ if(wd == null) {
+ System.out.println("executeMidStreamCreationTest::success");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void executeMidStreamCreationTest() {
+ try {
+
+ AudioInputStream ais = AudioSystem.getAudioInputStream(WaveDataTest.class.getClassLoader().getResource(filePath));
+ int totalSize = ais.getFormat().getChannels() * (int) ais.getFrameLength() * ais.getFormat().getSampleSizeInBits() / 8;
+
+ // skip 1/4 of the stream
+ int skip = totalSize / 4;
+ long skipped = ais.skip(skip);
+
+ WaveData wd = WaveData.create(ais);
+ if(wd == null) {
+ System.out.println("executeMidStreamCreationTest::success");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Pause current thread for a specified time
+ *
+ * @param time milliseconds to sleep
+ */
+ private void pause(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException inte) {
+ /* ignored */
+ }
+ }
+
+ /**
+ * Tests the Sys class, and serves as basic usage test
+ *
+ * @param args ignored
+ */
+ public static void main(String[] args) throws LWJGLException {
+ new WaveDataTest().executeTest();
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/WindowCreationTest.java b/src/java/org/lwjgl/test/WindowCreationTest.java
new file mode 100644
index 0000000..7fb9a90
--- /dev/null
+++ b/src/java/org/lwjgl/test/WindowCreationTest.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2002-2008 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.test;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+
+/**
+ * Small class for testing that the Window is creatable
+ * If this class can't run, LWJGL wont work!
+ *
+ * @author Brian Matzon
+ */
+public class WindowCreationTest {
+
+ /** Locatable modes */
+ private DisplayMode[] located_modes;
+
+ /** Fixed selectable modes */
+ private DisplayMode[] fixed_modes = new DisplayMode[10];
+
+
+ /** Window position x */
+ private int window_x = 0;
+
+ /** Window position y */
+ private int window_y = 0;
+
+ /** Color being cleared to */
+ private float color = 0f;
+
+ /** Direction moving clearing color */
+ private int direction = 1;
+
+ /** Whether we're running */
+ private boolean running = false;
+
+ /** Whether we're in fullscreen mode */
+ private boolean fullscreen = false;
+
+ /**
+ * Initializes the test
+ * @return true if initialization was successfull
+ */
+ public boolean initialize() {
+ try {
+ // get available modes, and print out
+ located_modes = Display.getAvailableDisplayModes();
+ System.out.println("Found " + located_modes.length + " display modes");
+
+ // get 640x480, 800x600, 1024x768 modes
+ findFixedModes();
+
+ // create default windowed display 640*480 @ 100, 100
+ setDefaultDisplayMode();
+
+ window_x = window_y = 100;
+ Display.setLocation(window_x, window_y);
+
+ Display.create();
+ return true;
+ } catch (LWJGLException le) {
+ le.printStackTrace();
+ }
+ return false;
+ }
+
+ /** Locate fixed modes */
+ private void findFixedModes() {
+ // get 640*480 modes
+ fixed_modes[0] = getDisplayMode(640, 480, 16, -1);
+ fixed_modes[1] = getDisplayMode(640, 480, 24, -1);
+ fixed_modes[2] = getDisplayMode(640, 480, 32, -1);
+
+ // get 800*600*16*60
+ fixed_modes[3] = getDisplayMode(800, 600, 16, -1);
+ fixed_modes[4] = getDisplayMode(800, 600, 24, -1);
+ fixed_modes[5] = getDisplayMode(800, 600, 32, -1);
+
+ // get 1024*768*16*60
+ fixed_modes[6] = getDisplayMode(1024, 768, 16, -1);
+ fixed_modes[7] = getDisplayMode(1024, 768, 24, -1);
+ fixed_modes[8] = getDisplayMode(1024, 768, 32, -1);
+ }
+
+ /**
+ * Executes the test
+ */
+ private void execute() {
+ running = true;
+
+ // wait for user to close window
+ while (!Display.isCloseRequested() && running) {
+
+ // handle input accordingly
+ handleInput();
+
+ // render something
+ render();
+
+ // update display as needed
+ Display.update();
+
+ // no need to run at full speed
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Destroys any resources used while running test
+ */
+ public void destroy() {
+ // nuke window and get out
+ Display.destroy();
+ }
+
+ /**
+ * Handles the input
+ */
+ private void handleInput() {
+ while (Keyboard.next()) {
+
+ // we only want key down events
+ if (!Keyboard.getEventKeyState()) {
+ continue;
+ }
+
+ // check for exit
+ if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
+ running = false;
+ }
+
+ // check for listing of modes
+ if (Keyboard.getEventKey() == Keyboard.KEY_L) {
+ for(int i=0;i 1f) {
+ color = 1f;
+ direction = -1 * direction;
+ } else if (color < 0f) {
+ direction = -1 * direction;
+ color = 0f;
+ }
+ }
+
+ /**
+ * Main entry point
+ *
+ * @param args ignored params to app
+ */
+ public static void main(String[] args) throws LWJGLException {
+
+ System.out.println("The following keys are available:\n" +
+ "ESCAPE:\t\tExit test\n" +
+ "ARROW Keys:\tMove window when in non-fullscreen mode\n" +
+ "L:\t\tList selectable display modes\n" +
+ "0-8:\t\tSelection of display modes\n" +
+ "F:\t\tToggle fullscreen\n" +
+ "SHIFT-F:\tToggle fullscreen with Display.destroy()/create() cycle");
+
+ WindowCreationTest wct = new WindowCreationTest();
+ if (wct.initialize()) {
+ wct.execute();
+ wct.destroy();
+ }
+ System.exit(0);
+ }
+
+ /**
+ * Sets the display mode for fullscreen mode
+ */
+ protected boolean setDefaultDisplayMode() {
+ try {
+ // get modes
+ DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, -1, -1);
+
+ org.lwjgl.util.Display.setDisplayMode(dm, new String[] { "width=" + 640, "height=" + 480, "freq=" + 60,
+ "bpp=" + org.lwjgl.opengl.Display.getDisplayMode().getBitsPerPixel()});
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ /**
+ * Gets a specific display mode
+ */
+ private DisplayMode getDisplayMode(int width, int height, int bpp, int freq) {
+ DisplayMode[] dm = null;
+ try {
+ dm = org.lwjgl.util.Display.getAvailableDisplayModes(width, height, width, height, bpp, bpp, freq, freq);
+ if(dm == null || dm.length == 0) {
+ System.out.println("Problem retrieving mode with " + width + "x" + height + "x" + bpp + "@" + freq);
+ }
+ } catch (LWJGLException le) {
+ le.printStackTrace();
+ System.out.println("Problem retrieving mode with " + width + "x" + height + "x" + bpp + "@" + freq);
+ }
+ return (dm != null && dm.length != 0) ? dm[0] : null;
+ }
+}
diff --git a/src/java/org/lwjgl/test/applet/AppletLoaderTest.java b/src/java/org/lwjgl/test/applet/AppletLoaderTest.java
new file mode 100644
index 0000000..60b847b
--- /dev/null
+++ b/src/java/org/lwjgl/test/applet/AppletLoaderTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2002-2008 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.test.applet;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Canvas;
+
+public class AppletLoaderTest extends Applet {
+
+ Test test = null;
+
+ public void destroy() {
+ super.destroy();
+ System.out.println("*** destroy ***");
+ }
+
+ public void start() {
+ super.start();
+ System.out.println("*** start ***");
+ }
+
+ public void stop() {
+ super.stop();
+ System.out.println("*** stop ***");
+ test.stop();
+ }
+
+ public void init() {
+ System.out.println("*** init ***");
+
+ setLayout(new BorderLayout());
+ try {
+ test = (Test) Class.forName(getParameter("test")).newInstance();
+ Canvas canvas = (Canvas) test;
+ canvas.setSize(getWidth(), getHeight());
+ add(canvas);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ test.start();
+ }
+}
diff --git a/src/java/org/lwjgl/test/applet/ControllersTest.java b/src/java/org/lwjgl/test/applet/ControllersTest.java
new file mode 100644
index 0000000..7f39ad6
--- /dev/null
+++ b/src/java/org/lwjgl/test/applet/ControllersTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2002-2008 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.test.applet;
+
+import java.awt.Canvas;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Controllers;
+
+public class ControllersTest extends Canvas implements Test {
+ public void start() {
+ try {
+ Controllers.create();
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ return;
+ }
+ System.out.println("Controllers.getControllerCount() = " + Controllers.getControllerCount());
+ }
+
+ public void stop() {
+ }
+}
diff --git a/src/java/org/lwjgl/test/applet/GearsApplet.java b/src/java/org/lwjgl/test/applet/GearsApplet.java
new file mode 100644
index 0000000..95fb7d3
--- /dev/null
+++ b/src/java/org/lwjgl/test/applet/GearsApplet.java
@@ -0,0 +1,401 @@
+package org.lwjgl.test.applet;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Canvas;
+import java.nio.FloatBuffer;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.ARBTransposeMatrix;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GLContext;
+
+public class GearsApplet extends Applet {
+
+ /** The Canvas where the LWJGL Display is added */
+ Canvas display_parent;
+
+ /** Thread which runs the main game loop */
+ Thread gameThread;
+
+ /** is the game loop running */
+ boolean running = false;
+
+ /** variables used to rotate the view */
+ private float view_rotx = 20.0f;
+ private float view_roty = 30.0f;
+ private float view_rotz = 0.0f;
+
+ private int gear1;
+ private int gear2;
+ private int gear3;
+ private float angle;
+
+ boolean keyDown = false;
+
+ private int prevMouseX, prevMouseY;
+ private boolean mouseButtonDown = false;
+
+
+ /**
+ * Once the Canvas is created its add notify method will call this method to
+ * start the LWJGL Display and game loop in another thread.
+ */
+ public void startLWJGL() {
+ gameThread = new Thread() {
+ public void run() {
+ running = true;
+ try {
+ Display.setParent(display_parent);
+ //Display.setVSyncEnabled(true);
+ Display.create();
+ initGL();
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ }
+ gameLoop();
+ }
+ };
+ gameThread.start();
+ }
+
+
+ /**
+ * Tell game loop to stop running, after which the LWJGL Display will be destoryed.
+ * The main thread will wait for the Display.destroy() to complete
+ */
+ private void stopLWJGL() {
+ running = false;
+ try {
+ gameThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void start() {
+
+ }
+
+ public void stop() {
+
+ }
+
+ /**
+ * Applet Destroy method will remove the canvas, before canvas is destroyed it will notify
+ * stopLWJGL() to stop main game loop and to destroy the Display
+ */
+ public void destroy() {
+ remove(display_parent);
+ super.destroy();
+ System.out.println("Clear up");
+ }
+
+ /**
+ * initialise applet by adding a canvas to it, this canvas will start the LWJGL Display and game loop
+ * in another thread. It will also stop the game loop and destroy the display on canvas removal when
+ * applet is destroyed.
+ */
+ public void init() {
+ setLayout(new BorderLayout());
+ try {
+ display_parent = new Canvas() {
+ public final void addNotify() {
+ super.addNotify();
+ startLWJGL();
+ }
+ public final void removeNotify() {
+ stopLWJGL();
+ super.removeNotify();
+ }
+ };
+ display_parent.setSize(getWidth(),getHeight());
+ add(display_parent);
+ display_parent.setFocusable(true);
+ display_parent.requestFocus();
+ display_parent.setIgnoreRepaint(true);
+ //setResizable(true);
+ setVisible(true);
+ } catch (Exception e) {
+ System.err.println(e);
+ throw new RuntimeException("Unable to create display");
+ }
+ }
+
+ public void gameLoop() {
+ long startTime = System.currentTimeMillis() + 5000;
+ long fps = 0;
+
+ while(running) {
+ angle += 2.0f;
+
+ // draw the gears
+ drawLoop();
+
+ Display.update();
+
+ if (startTime > System.currentTimeMillis()) {
+ fps++;
+ } else {
+ long timeUsed = 5000 + (startTime - System.currentTimeMillis());
+ startTime = System.currentTimeMillis() + 5000;
+ System.out.println(fps + " frames 2 in " + (float) (timeUsed / 1000f) + " seconds = "
+ + (fps / (timeUsed / 1000f)));
+ fps = 0;
+ }
+
+ if (Mouse.isButtonDown(0)) {
+ if (!mouseButtonDown) {
+ prevMouseX = Mouse.getX();
+ prevMouseY= Mouse.getY();
+ }
+ mouseButtonDown = true;
+ }
+ else {
+ mouseButtonDown = false;
+ }
+
+ if (mouseButtonDown) {
+ int x = Mouse.getX();
+ int y = Mouse.getY();
+
+ float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)display_parent.getWidth());
+ float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)display_parent.getHeight());
+
+ prevMouseX = x;
+ prevMouseY = y;
+
+ view_rotx += thetaX;
+ view_roty += thetaY;
+ }
+
+ // F Key Pressed (i.e. released)
+ if (keyDown && !Keyboard.isKeyDown(Keyboard.KEY_F)) {
+ keyDown = false;
+
+ try {
+ if (Display.isFullscreen()) {
+ Display.setFullscreen(false);
+ }
+ else {
+ Display.setFullscreen(true);
+ }
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ Display.destroy();
+ }
+
+ public void drawLoop() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+
+ GL11.glPushMatrix();
+
+ GL11.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
+ GL11.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
+ GL11.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(-3.0f, -2.0f, 0.0f);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear1);
+ GL11.glPopMatrix();
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(3.1f, -2.0f, 0.0f);
+ GL11.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear2);
+ GL11.glPopMatrix();
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(-3.1f, 4.2f, 0.0f);
+ GL11.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear3);
+ GL11.glPopMatrix();
+
+ GL11.glPopMatrix();
+ }
+
+ protected void initGL() {
+ try {
+ // setup ogl
+ FloatBuffer pos = BufferUtils.createFloatBuffer(4).put(new float[] { 5.0f, 5.0f, 10.0f, 0.0f});
+ FloatBuffer red = BufferUtils.createFloatBuffer(4).put(new float[] { 0.8f, 0.1f, 0.0f, 1.0f});
+ FloatBuffer green = BufferUtils.createFloatBuffer(4).put(new float[] { 0.0f, 0.8f, 0.2f, 1.0f});
+ FloatBuffer blue = BufferUtils.createFloatBuffer(4).put(new float[] { 0.2f, 0.2f, 1.0f, 1.0f});
+
+ pos.flip();
+ red.flip();
+ green.flip();
+ blue.flip();
+
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, pos);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_LIGHTING);
+ GL11.glEnable(GL11.GL_LIGHT0);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = GL11.glGenLists(1);
+ GL11.glNewList(gear1, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0f, 4.0f, 1.0f, 20, 0.7f);
+ GL11.glEndList();
+
+ gear2 = GL11.glGenLists(1);
+ GL11.glNewList(gear2, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5f, 2.0f, 2.0f, 10, 0.7f);
+ GL11.glEndList();
+
+ gear3 = GL11.glGenLists(1);
+ GL11.glNewList(gear3, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3f, 2.0f, 0.5f, 10, 0.7f);
+ GL11.glEndList();
+ GL11.glEnable(GL11.GL_NORMALIZE);
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+
+ System.err.println("GL_VENDOR: " + GL11.glGetString(GL11.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + GL11.glGetString(GL11.GL_RENDERER));
+ System.err.println("GL_VERSION: " + GL11.glGetString(GL11.GL_VERSION));
+ System.err.println();
+ System.err.println("glLoadTransposeMatrixfARB() supported: " + GLContext.getCapabilities().GL_ARB_transpose_matrix);
+
+ if (!GLContext.getCapabilities().GL_ARB_transpose_matrix) {
+ // --- not using extensions
+ GL11.glLoadIdentity();
+ } else {
+ // --- using extensions
+ final FloatBuffer identityTranspose = BufferUtils.createFloatBuffer(16).put(
+ new float[] { 1, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1});
+ identityTranspose.flip();
+ ARBTransposeMatrix.glLoadTransposeMatrixARB(identityTranspose);
+ }
+ float h = (float) display_parent.getHeight() / (float) display_parent.getWidth();
+ GL11.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glTranslatef(0.0f, 0.0f, -40.0f);
+ } catch (Exception e) {
+ System.err.println(e);
+ running = false;
+ }
+ }
+
+ /**
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * @param inner_radius radius of hole at center
+ * @param outer_radius radius at center of teeth
+ * @param width width of gear
+ * @param teeth number of teeth
+ * @param tooth_depth depth of tooth
+ */
+ private void gear(float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) {
+ int i;
+ float r0, r1, r2;
+ float angle, da;
+ float u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0f;
+ r2 = outer_radius + tooth_depth / 2.0f;
+ da = 2.0f * (float) Math.PI / teeth / 4.0f;
+ GL11.glShadeModel(GL11.GL_FLAT);
+ GL11.glNormal3f(0.0f, 0.0f, 1.0f);
+ /* draw front face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ if (i < teeth) {
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da),
+ width * 0.5f);
+ }
+ }
+ GL11.glEnd();
+
+ /* draw front sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw outward faces of teeth */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle);
+ v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle);
+ len = (float) Math.sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da);
+ v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da);
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ }
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f);
+ GL11.glEnd();
+
+ GL11.glShadeModel(GL11.GL_SMOOTH);
+ /* draw inside radius cylinder */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ }
+ GL11.glEnd();
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/applet/OpenAL.java b/src/java/org/lwjgl/test/applet/OpenAL.java
new file mode 100644
index 0000000..778900c
--- /dev/null
+++ b/src/java/org/lwjgl/test/applet/OpenAL.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2002-2008 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.test.applet;
+
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.opengl.AWTGLCanvas;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.WaveData;
+
+public class OpenAL extends AWTGLCanvas implements Test {
+
+ float angle = 0;
+
+ // create 1 buffer and 1 source
+ IntBuffer buffers = BufferUtils.createIntBuffer(1);
+ IntBuffer sources = BufferUtils.createIntBuffer(1);
+
+ public OpenAL() throws LWJGLException {
+
+ try {
+ AL.create();
+ } catch (Exception e) {
+ System.out.println("Unable to create OpenAL.\nPlease make sure that OpenAL is available on this system. Exception: " + e);
+ return;
+ }
+
+ Thread t = new Thread() {
+
+ public void run() {
+ while (true) {
+ if (isVisible())
+ repaint();
+ Display.sync(60);
+ }
+ }
+ };
+ t.setDaemon(true);
+ t.start();
+ }
+
+ private void playOpenAL() {
+ int lastError;
+
+ // al generate buffers and sources
+ buffers.position(0).limit(1);
+ AL10.alGenBuffers(buffers);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ sources.position(0).limit(1);
+ AL10.alGenSources(sources);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ // load wave data from buffer
+ WaveData wavefile = WaveData.create(getClass().getClassLoader().getResourceAsStream("Footsteps.wav"));
+
+ //copy to buffers
+ AL10.alBufferData(buffers.get(0), wavefile.format, wavefile.data, wavefile.samplerate);
+
+ //unload file again
+ wavefile.dispose();
+
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //set up source input
+ AL10.alSourcei(sources.get(0), AL10.AL_BUFFER, buffers.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //lets loop the sound
+ AL10.alSourcei(sources.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //play source 0
+ AL10.alSourcePlay(sources.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+ }
+
+ private void exit(int error) {
+ System.out.println("OpenAL Error: " + AL10.alGetString(error));
+ }
+
+ public void paintGL() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ GL11.glMatrixMode(GL11.GL_PROJECTION_MATRIX);
+ GL11.glLoadIdentity();
+ GL11.glOrtho(0, 640, 0, 480, 1, -1);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW_MATRIX);
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(320, 240, 0.0f);
+ GL11.glRotatef(angle, 0, 0, 1.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ GL11.glVertex2i(-50, -50);
+ GL11.glVertex2i(50, -50);
+ GL11.glVertex2i(50, 50);
+ GL11.glVertex2i(-50, 50);
+ GL11.glEnd();
+ GL11.glPopMatrix();
+
+ angle += 1;
+
+ try {
+ swapBuffers();
+ } catch (Exception e) {/*OK*/
+ }
+ }
+
+ public void start() {
+ playOpenAL();
+ }
+
+ public void stop() {
+ int lastError;
+
+ //stop source 0
+ AL10.alSourceStop(sources.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //delete buffers and sources
+ sources.position(0).limit(1);
+ AL10.alDeleteSources(sources);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ buffers.position(0).limit(1);
+ AL10.alDeleteBuffers(buffers);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ AL.destroy();
+ }
+}
diff --git a/src/java/org/lwjgl/test/applet/OpenGL.java b/src/java/org/lwjgl/test/applet/OpenGL.java
new file mode 100644
index 0000000..88284c2
--- /dev/null
+++ b/src/java/org/lwjgl/test/applet/OpenGL.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2002-2008 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.test.applet;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.AWTGLCanvas;
+import org.lwjgl.opengl.GL11;
+
+public class OpenGL extends AWTGLCanvas implements Test {
+
+ float angle = 0;
+ float x;
+ float y;
+
+ public OpenGL() throws LWJGLException {
+ }
+
+ public void initGL() {
+ GL11.glMatrixMode(GL11.GL_PROJECTION_MATRIX);
+ GL11.glLoadIdentity();
+ GL11.glOrtho(0, 640, 0, 480, 1, -1);
+ x = 320;
+ y = 240;
+ GL11.glMatrixMode(GL11.GL_MODELVIEW_MATRIX);
+ setVSyncEnabled(true);
+ }
+
+ public void paintGL() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(x, y, 0.0f);
+ GL11.glRotatef(angle, 0, 0, 1.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ GL11.glVertex2i(-50, -50);
+ GL11.glVertex2i(50, -50);
+ GL11.glVertex2i(50, 50);
+ GL11.glVertex2i(-50, 50);
+ GL11.glEnd();
+ GL11.glPopMatrix();
+
+ angle += 1;
+
+ if (Mouse.isCreated()) {
+ Mouse.poll();
+ while (Mouse.next()) {
+ x += Mouse.getEventDX();
+ y += Mouse.getEventDY();
+ }
+ }
+ if (Keyboard.isCreated()) {
+ Keyboard.poll();
+ }
+ while (Keyboard.isCreated() && Keyboard.next()) {
+ if (Keyboard.getEventKey() != Keyboard.KEY_NONE) {
+ String key_name = Keyboard.getKeyName(Keyboard.getEventKey());
+ if (Keyboard.getEventKeyState()) {
+ switch (Keyboard.getEventKey()) {
+ case Keyboard.KEY_G:
+ Mouse.setGrabbed(!Mouse.isGrabbed());
+ break;
+ default:
+ break;
+ }
+ System.out.println("Pressed: " + key_name);
+ } else
+ System.out.println("Released: " + key_name);
+ }
+ if (Keyboard.getEventCharacter() != Keyboard.CHAR_NONE)
+ System.out.println("Typed: " + Keyboard.getEventCharacter());
+ }
+ if (Keyboard.isCreated()) {
+ if (Keyboard.isKeyDown(Keyboard.KEY_UP))
+ y += 5;
+ else if (Keyboard.isKeyDown(Keyboard.KEY_DOWN))
+ y -= 5;
+ if (Keyboard.isKeyDown(Keyboard.KEY_LEFT))
+ x -= 5;
+ else if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT))
+ x += 5;
+ }
+ try {
+ swapBuffers();
+ if (isVisible()) {
+ Thread.yield(); // Helps input responsiveness on linux
+ repaint();
+ }
+ } catch (Exception e) {/*OK*/
+ }
+ }
+
+ public void start() {
+ }
+
+ public void stop() {
+ }
+}
diff --git a/src/java/org/lwjgl/test/applet/Speed.java b/src/java/org/lwjgl/test/applet/Speed.java
new file mode 100644
index 0000000..3c42ed7
--- /dev/null
+++ b/src/java/org/lwjgl/test/applet/Speed.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002-2008 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.test.applet;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.AWTGLCanvas;
+import org.lwjgl.opengl.GL11;
+
+public class Speed extends AWTGLCanvas implements Test {
+
+ private float angle = 0;
+ private long startTime = System.currentTimeMillis() + 5000;
+ private long fps = 0;
+
+ public Speed() throws LWJGLException {
+ }
+
+ public void paintGL() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ GL11.glMatrixMode(GL11.GL_PROJECTION_MATRIX);
+ GL11.glLoadIdentity();
+ GL11.glOrtho(0, 640, 0, 480, 1, -1);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW_MATRIX);
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(320, 240, 0.0f);
+ GL11.glRotatef(angle, 0, 0, 1.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ GL11.glVertex2i(-50, -50);
+ GL11.glVertex2i(50, -50);
+ GL11.glVertex2i(50, 50);
+ GL11.glVertex2i(-50, 50);
+ GL11.glEnd();
+ GL11.glPopMatrix();
+
+ angle += 1;
+
+ try {
+ swapBuffers();
+ if (isVisible()) {
+ Thread.yield(); // Helps input responsiveness on linux
+ repaint();
+ }
+ } catch (Exception e) {/*OK*/
+ }
+ if (startTime > System.currentTimeMillis()) {
+ fps++;
+ } else {
+ long timeUsed = 5000 + (startTime - System.currentTimeMillis());
+ startTime = System.currentTimeMillis() + 5000;
+ System.out.println(fps + " frames in " + (float) (timeUsed / 1000f) + " seconds = "
+ + (fps / (timeUsed / 1000f)));
+ fps = 0;
+ }
+ }
+
+ public void start() {
+ }
+
+ public void stop() {
+ }
+}
diff --git a/src/java/org/lwjgl/test/applet/Test.java b/src/java/org/lwjgl/test/applet/Test.java
new file mode 100644
index 0000000..35a79f1
--- /dev/null
+++ b/src/java/org/lwjgl/test/applet/Test.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2002-2008 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.test.applet;
+
+
+public interface Test {
+ public void start();
+ public void stop();
+}
diff --git a/src/java/org/lwjgl/test/glu/tessellation/TessCallback.java b/src/java/org/lwjgl/test/glu/tessellation/TessCallback.java
new file mode 100644
index 0000000..15253d3
--- /dev/null
+++ b/src/java/org/lwjgl/test/glu/tessellation/TessCallback.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2002-2008 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.test.glu.tessellation;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.GLUtessellatorCallbackAdapter;
+
+public class TessCallback extends GLUtessellatorCallbackAdapter {
+
+ public void begin(int type) {
+ GL11.glBegin(type);
+ }
+
+ public void combine(double[] coords, Object[] data, float[] weight, Object[] outData) {
+ for (int i=0;i
+ * @version $Revision: 2983 $
+ * $Id: HWCursorTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class HWCursorTest {
+
+ /** The native cursor */
+ private static Cursor[] cursor = null;
+
+ /** The mouse cursor position */
+ private static int mouse_x;
+ private static int mouse_y;
+ private static int mouse_btn = 0;
+
+ /**
+ * Executes the test
+ */
+ public void execute() {
+ initialize();
+
+ mainLoop();
+
+ cleanup();
+ }
+
+ /**
+ * Sets the display mode for fullscreen mode
+ */
+ protected boolean setDisplayMode() {
+ 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,
+ "freq=" + 60,
+ "bpp=" + org.lwjgl.opengl.Display.getDisplayMode().getBitsPerPixel()
+ });
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return false;
+ }
+
+ /**
+ * Initializes the test
+ */
+ private void initialize() {
+ try {
+ // start of in windowed mode
+ setDisplayMode();
+ Display.create();
+
+ glInit();
+
+ initNativeCursors();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ private static void initNativeCursors() throws Exception {
+ if ((Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) == 0) {
+ System.out.println("No HW cursor support!");
+ System.exit(0);
+ }
+
+ cursor = new Cursor[3];
+
+ int cursorImageCount = 1;
+ int cursorWidth = Math.min(64, Cursor.getMaxCursorSize());
+ int cursorHeight = cursorWidth;
+ IntBuffer cursorImages;
+ IntBuffer cursorDelays;
+
+
+ // Create a single cursor
+ // ==================================
+ cursorImages = ByteBuffer.allocateDirect(cursorWidth*cursorHeight*cursorImageCount*4).order(ByteOrder.nativeOrder()).asIntBuffer();
+ cursorDelays = null;
+ for(int j=0; j= centerLeft && j < centerRight && l >= centerLeft && l < centerRight) {
+ cursorImages.put(offColor);
+ } else {
+ cursorImages.put(onColor);
+ }
+ }
+ }
+ }
+ cursorDelays.put(2000).put(2000).put(2000);
+ cursorDelays.flip();
+ cursorImages.flip();
+
+ cursor[1] = new Cursor(cursorWidth, cursorHeight, cursorWidth/2, cursorHeight/2, cursorImageCount, cursorImages, cursorDelays);
+ // ----------------------------------
+
+
+ // Create a 20 piece animation
+ // ==================================
+ cursorImageCount = 20;
+ cursorImages = ByteBuffer.allocateDirect(cursorWidth*cursorHeight*cursorImageCount*4).order(ByteOrder.nativeOrder()).asIntBuffer();
+ cursorDelays = ByteBuffer.allocateDirect(cursorImageCount*4).order(ByteOrder.nativeOrder()).asIntBuffer();
+ cursorDelays.put(
+ new int[] {
+ 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100
+ });
+
+ float step = 0xffffffff / 20.0f;
+ for(int i=0; i= 0 && button < 3 && Mouse.getEventButtonState()) {
+ mouse_btn = Mouse.getEventButton();
+ switchCursor();
+ }
+ }
+ }
+
+ /**
+ * Processes keyboard input
+ */
+ private void processKeyboard() {
+ //check for fullscreen key
+ if (Keyboard.isKeyDown(Keyboard.KEY_F)) {
+
+ try {
+ try {
+ Mouse.setNativeCursor(null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ for(int i=0; i
+ * Keyboard test
+ *
+ * @author Brian Matzon
+ * @version $Revision: 3042 $
+ * $Id: KeyboardTest.java 3042 2008-04-22 21:26:39Z elias_naur $
+ */
+public class KeyboardTest {
+
+ /** position of quad to draw */
+ private Vector2f position = new Vector2f(320.0f, 240.0f);
+
+ /** Display mode selected */
+ private DisplayMode displayMode;
+
+ /** Creates a new instance of MouseTest */
+ public KeyboardTest() {
+ }
+
+ private void initialize() {
+ // create display and opengl
+ setupDisplay(false);
+
+ try {
+ Keyboard.create();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * Sets the display mode for fullscreen mode
+ */
+ protected boolean setDisplayMode() {
+ 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,
+ "freq=" + 60,
+ "bpp=" + org.lwjgl.opengl.Display.getDisplayMode().getBitsPerPixel()
+ });
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return false;
+ }
+
+ private void setupDisplay(boolean fullscreen) {
+ try {
+ setDisplayMode();
+ Display.create();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+
+ initializeOpenGL();
+ }
+
+ private void initializeOpenGL() {
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluOrtho2D(0, Display.getDisplayMode().getWidth(), 0, Display.getDisplayMode().getHeight());
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
+ GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ public void executeTest() {
+ initialize();
+
+ createKeyboard();
+
+ wiggleKeyboard();
+
+ Keyboard.destroy();
+ Display.destroy();
+ }
+
+ private void createKeyboard() {
+ try {
+ Keyboard.create();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ private void wiggleKeyboard() {
+
+ while (!Display.isCloseRequested()) {
+ Display.update();
+
+ if (!Display.isVisible()) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException inte) {
+ inte.printStackTrace();
+ }
+ continue;
+ }
+
+ //check keys, buffered
+ Keyboard.poll();
+
+ int count = Keyboard.getNumKeyboardEvents();
+ while (Keyboard.next()) {
+ int character_code = ((int)Keyboard.getEventCharacter()) & 0xffff;
+ System.out.println("Checking key:" + Keyboard.getKeyName(Keyboard.getEventKey()));
+ System.out.println("Pressed:" + Keyboard.getEventKeyState());
+ System.out.println("Key character code: 0x" + Integer.toHexString(character_code));
+ System.out.println("Key character: " + Keyboard.getEventCharacter());
+ System.out.println("Repeat event: " + Keyboard.isRepeatEvent());
+
+ if (Keyboard.getEventKey() == Keyboard.KEY_R && Keyboard.getEventKeyState()) {
+ Keyboard.enableRepeatEvents(!Keyboard.areRepeatEventsEnabled());
+ }
+ if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
+ return;
+ }
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
+ position.x += 1;
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
+ position.x -= 1;
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
+ position.y += 1;
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
+ position.y -= 1;
+ }
+
+ if (count > 0) {
+ System.out.println();
+ }
+
+ if (position.x < 0) {
+ position.x = 0;
+ } else if (position.x > 640 - 60) {
+ position.x = 640 - 60;
+ }
+
+ if (position.y < 0) {
+ position.y = 0;
+ } else if (position.y > 480 - 30) {
+ position.y = 480 - 30;
+ }
+
+ render();
+
+ try {
+ Thread.sleep(0);
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ private void render() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+
+ GL11.glBegin(GL11.GL_POLYGON);
+ {
+ float color = 1.0f;
+ GL11.glColor3f(color, color, color);
+
+ GL11.glVertex2f(position.x + 0.0f, position.y + 0.0f);
+ GL11.glVertex2f(position.x + 0.0f, position.y + 30.0f);
+ GL11.glVertex2f(position.x + 40.0f, position.y + 30.0f);
+ GL11.glVertex2f(position.x + 60.0f, position.y + 15.f);
+ GL11.glVertex2f(position.x + 40.0f, position.y + 0.0f);
+ }
+ GL11.glEnd();
+ }
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ KeyboardTest kt = new KeyboardTest();
+ kt.executeTest();
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/input/MouseCreationTest.java b/src/java/org/lwjgl/test/input/MouseCreationTest.java
new file mode 100644
index 0000000..8e3553b
--- /dev/null
+++ b/src/java/org/lwjgl/test/input/MouseCreationTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2002-2008 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.test.input;
+
+import org.lwjgl.Sys;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.vector.Vector2f;
+
+/**
+ *
+ * Mouse test
+ *
+ * @author Brian Matzon
+ * @version $Revision: 3108 $
+ * $Id: MouseCreationTest.java 3108 2008-07-02 20:00:49Z matzon $
+ */
+public class MouseCreationTest {
+ /** position of quad to draw */
+ private Vector2f position = new Vector2f(320.0f, 240.0f);
+
+ /** Creates a new instance of MouseTest */
+ public MouseCreationTest() {
+ }
+
+ private void initialize(boolean fullscreen) {
+ try {
+ setDisplayMode();
+ Display.setFullscreen(fullscreen);
+ Display.create();
+ Mouse.setGrabbed(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+
+ initializeOpenGL();
+ }
+
+ /**
+ * Sets the display mode for fullscreen mode
+ */
+ protected boolean setDisplayMode() {
+ 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,
+ "freq=" + 60,
+ "bpp=" + org.lwjgl.opengl.Display.getDisplayMode().getBitsPerPixel()
+ });
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return false;
+ }
+
+ private void initializeOpenGL() {
+ GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ // Put the window into orthographic projection mode with 1:1 pixel ratio.
+ // We haven't used GLU here to do this to avoid an unnecessary dependency.
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GL11.glOrtho(0.0, Display.getDisplayMode().getWidth(), 0.0, Display.getDisplayMode().getHeight(), -1.0, 1.0);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
+ }
+
+ public void executeTest() {
+ initialize(false);
+
+ System.out.println("Test ready:\n");
+
+ // windowed mode
+ System.out.println("=========== WINDOWED MODE ==============");
+ for(int i=0; i<2; i++) {
+ System.out.println("Test " + (i+1) + ":");
+ wiggleMouse();
+ System.out.println("");
+ }
+
+ // recreate display in fullscreen mode
+ System.out.print("Destroying display...");
+
+ System.out.println("success");
+
+ System.out.print("Entering fullscreen mode...");
+ try {
+ Display.destroy();
+ initialize(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ System.out.println("success");
+
+
+ // fullscreen mode
+ System.out.println("=========== FULLSCREEN MODE ==============");
+ for(int i=0; i<2; i++) {
+ System.out.println("Test " + (i+3) + ":");
+ wiggleMouse();
+ System.out.println("");
+ }
+
+ System.out.println("Test completed successfully!");
+ System.out.print("Shutting down...");
+ Display.destroy();
+ System.out.println("shutdown complete");
+ }
+
+ private void wiggleMouse() {
+ System.out.print("Please move the mouse around");
+
+ long statustime = Sys.getTime();
+ long endtime = Sys.getTime() + Sys.getTimerResolution() * 5;
+
+ while (Sys.getTime() < endtime) {
+ Display.update();
+
+ // empty mouse buffer
+ while(Mouse.next());
+
+ position.x += Mouse.getDX();
+ position.y += Mouse.getDY();
+
+ if(position.x<0) {
+ position.x = 0;
+ } else if (position.x>640-60) {
+ position.x = 640-60;
+ }
+
+ if(position.y < 0) {
+ position.y = 0;
+ } else if (position.y>480-30) {
+ position.y = 480-30;
+ }
+
+ render();
+
+ if (Sys.getTime() - statustime > Sys.getTimerResolution()) {
+ System.out.print(".");
+ statustime = Sys.getTime();
+ }
+ }
+ System.out.println("thank you");
+ }
+
+ private void render() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+
+ GL11.glBegin(GL11.GL_POLYGON);
+ {
+ float color = 1.0f;
+ int buttonDown = 0;
+
+ for(int i=0;i
+ * Mouse test
+ *
+ * @author Brian Matzon
+ * @version $Revision: 3240 $
+ * $Id: MouseTest.java 3240 2009-09-12 22:15:21Z matzon $
+ */
+public class MouseTest {
+ /** Direction mouse has moved */
+ private int direction;
+
+ /** Last button pressed */
+ private int lastButton = 0;
+
+ /** Last direction we scrolled in */
+ private int lastScrollDirection = -1;
+
+ /** Width of window */
+ private static int WINDOW_WIDTH = 640;
+
+ /** Height of window */
+ private static int WINDOW_HEIGHT = 640;
+
+ /** Triangle size */
+ private Vector2f triangleSize = new Vector2f(120, 100);
+
+ /** Triangle color */
+ private Vector3f triangleColor[] = new Vector3f[] {
+ new Vector3f(1,1,1),
+ new Vector3f(1,0,0),
+ new Vector3f(0,1,0),
+ new Vector3f(0,0,1)
+ };
+
+ private Vector3f quadColor[] = new Vector3f[] {
+ new Vector3f(1,1,1),
+ new Vector3f(1,0,0),
+ new Vector3f(0,1,0),
+ new Vector3f(0,0,1)
+ };
+
+ /** Triangles to paint */
+ private Vector2f[] triangles = {
+ new Vector2f(WINDOW_WIDTH/2, WINDOW_HEIGHT - triangleSize.y),
+ new Vector2f(triangleSize.y, WINDOW_HEIGHT/2),
+ new Vector2f(WINDOW_WIDTH/2, triangleSize.y),
+ new Vector2f(WINDOW_WIDTH-triangleSize.y, WINDOW_HEIGHT/2)
+ };
+
+ /** Whether the test is closing */
+ private boolean closing = false;
+
+ /** Fullscreen or not */
+ public static final boolean FULLSCREEN = false;
+
+ /** Creates a new instance of MouseTest */
+ public MouseTest() {
+ }
+
+ private void initialize() {
+ // create display and opengl
+ setupDisplay();
+
+ setupMouse();
+ setupKeyboard();
+ }
+
+ /**
+ * Setup display
+ */
+ private void setupDisplay() {
+ try {
+ setDisplayMode();
+ Display.setFullscreen(FULLSCREEN);
+ Display.setVSyncEnabled(true);
+ Display.create();
+ Mouse.setGrabbed(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+
+ initializeOpenGL();
+ }
+
+ /**
+ * Sets the display mode for fullscreen mode
+ */
+ protected boolean setDisplayMode() {
+ // get modes
+ DisplayMode dm = new DisplayMode(WINDOW_WIDTH, WINDOW_HEIGHT);
+
+ try {
+ Display.setDisplayMode(dm);
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return false;
+ }
+
+ /**
+ * Initializes OpenGL
+ *
+ */
+ private void initializeOpenGL() {
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluOrtho2D(0, Display.getDisplayMode().getWidth(), 0, Display.getDisplayMode().getHeight());
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
+ GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ /**
+ * Executes the actual test
+ */
+ public void executeTest() {
+ initialize();
+
+ runTest();
+
+ Display.destroy();
+ }
+
+ /**
+ * Creates the mouse
+ */
+ private void setupMouse() {
+ }
+
+ /**
+ * Creates the keyboard
+ */
+ private void setupKeyboard() {
+ }
+
+ /**
+ * Runs the test
+ */
+ private void runTest() {
+ // while not exiting
+ while (!closing) {
+ handleWindow();
+
+ // secondary check
+ if(!closing) {
+
+ // poll and check keyboard and mouse
+ handleKeyboard();
+ handleMouse();
+
+ // pause and continue if minimized
+ if(!Display.isVisible()) {
+ if(Display.isDirty()) {
+ render();
+ }
+ pause(100);
+ continue;
+ }
+
+ // render and flip
+ logic();
+ render();
+ }
+ Thread.yield();
+ }
+ }
+
+ /**
+ * Pauses the current thread for a specified time
+ *
+ * @param time milliseconds to pause
+ */
+ private void pause(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException inte) {
+ inte.printStackTrace();
+ }
+ }
+
+ /**
+ * Handles the window
+ */
+ private void handleWindow() {
+ Display.update();
+ closing = Display.isCloseRequested();
+ }
+
+ /**
+ * handles the mouse
+ */
+ private void handleMouse() {
+ readBufferedMouse();
+
+ Display.setTitle("x: " + Mouse.getX() + ", y: " + Mouse.getY() + ", [0]: " + Mouse.isButtonDown(0) + ", [1]: " + Mouse.isButtonDown(1) + ", [2]: " + Mouse.isButtonDown(2) + ", inside: " + Mouse.isInsideWindow());
+ }
+
+ /**
+ * reads a mouse in buffered mode
+ */
+ private void readBufferedMouse() {
+ // iterate all events, use the last button down
+ while(Mouse.next()) {
+ if(Mouse.getEventButton() != -1 && Mouse.getEventButtonState()) {
+ lastButton = Mouse.getEventButton();
+ }
+ }
+
+ updateState();
+ }
+
+ /**
+ * Updates our "model"
+ *
+ */
+ private void updateState() {
+ direction = -1;
+
+ int dx = Mouse.getDX();
+ int dy = Mouse.getDY();
+ int dw = Mouse.getDWheel();
+
+
+ // get out if no movement
+ if (dx == dy && dx == 0 && dw == 0) {
+ return;
+ }
+
+ // determine direction moved
+ // ============================
+ if(dx > 0) {
+ direction = 3;
+ }
+
+ if(dx < 0) {
+ direction = 1;
+ }
+
+ if(dy > 0) {
+ direction = 0;
+ }
+
+ if(dy < 0) {
+ direction = 2;
+ }
+
+ // ----------------------------
+ if(direction > -1) {
+
+ // based on which button was last pushed, update model
+ switch(lastButton) {
+ case -1:
+ break;
+ case 1:
+ triangleColor[direction].y = 1;
+ break;
+ case 2:
+ triangleColor[direction].z = 1;
+ break;
+ case 3:
+ triangleColor[direction].x = 1;
+ triangleColor[direction].y = 1;
+ triangleColor[direction].z = 1;
+ break;
+ case 0: // fall through
+ default:
+ triangleColor[direction].x = 1;
+ break;
+ }
+ }
+
+ // get direction to update in
+ if (dw > 0) {
+ lastScrollDirection++;
+ } else if (dw < 0) {
+ lastScrollDirection--;
+ } else if (dw == 0) {
+ return;
+ }
+
+ // over/underflow
+ if(lastScrollDirection < 0) {
+ lastScrollDirection = 3;
+ }
+ if(lastScrollDirection > 3) {
+ lastScrollDirection = 0;
+ }
+
+ // update colors
+ quadColor[lastScrollDirection].x = (float) Math.random();
+ quadColor[lastScrollDirection].y = (float) Math.random();
+ quadColor[lastScrollDirection].z = (float) Math.random();
+ }
+
+ /**
+ * Handles the keyboard
+ */
+ private void handleKeyboard() {
+
+ while(Keyboard.next()) {
+ // closing on ESCAPE
+ if(Keyboard.getEventKey() == Keyboard.KEY_ESCAPE && Keyboard.getEventKeyState()) {
+ closing = true;
+ }
+
+ if(Keyboard.getEventKey() == Keyboard.KEY_SPACE && Keyboard.getEventKeyState()) {
+ Mouse.setGrabbed(!Mouse.isGrabbed());
+ }
+ }
+ }
+
+ /**
+ * Does the "model logic"
+ */
+ private void logic() {
+ // "we fade to black"
+ // ===========================================
+ for(int i=0; i
+ * @version $Revision: 2286 $
+ * $Id: ALCTest.java 2286 2006-03-23 19:32:21Z matzon $
+ */
+public class ALCCaptureTest extends BasicTest {
+
+ /**
+ * Creates an instance of ALCTest
+ */
+ public ALCCaptureTest() {
+ super();
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ int lastError = ALC10.ALC_NO_ERROR;
+ IntBuffer sampleCount = BufferUtils.createIntBuffer(1);
+
+ int state = AL10.AL_PLAYING;
+ int FMT = AL10.AL_FORMAT_MONO16;
+ int FMTSIZE = 16/8;
+ int FREQ = 44100;
+ int TIME = 5;
+ int SAMPS = (FREQ * TIME);
+ ByteBuffer buf = BufferUtils.createByteBuffer(SAMPS * FMTSIZE);
+
+ // check that capture is available
+ if(!ALC10.alcIsExtensionPresent(AL.getDevice(), "ALC_EXT_CAPTURE")) {
+ throw new OpenALException("ALC_EXT_CAPTURE extension not available");
+ }
+
+ // get list of devices
+ String[] captureDevices = ALC10.alcGetString(null, ALC11.ALC_CAPTURE_DEVICE_SPECIFIER).split("\0");
+ System.out.println("Available Capture Devices: ");
+ for(int i=0; i
+ * @version $Revision: 2983 $
+ * $Id: ALCTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class ALCTest extends BasicTest {
+
+ /**
+ * Creates an instance of ALCTest
+ */
+ public ALCTest() {
+ super();
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ //error stuff
+ int lastError = ALC10.ALC_NO_ERROR;
+
+ //create attribute list for context creation
+ IntBuffer buffer = BufferUtils.createIntBuffer(7);
+
+ if ((lastError = ALC10.alcGetError(AL.getDevice())) != ALC10.ALC_NO_ERROR) {
+ System.out.println("ALC Error: " + ALC10.alcGetString(AL.getDevice(), lastError));
+ System.exit(-1);
+ }
+
+ //query
+ System.out.println(
+ "DEFAULT_DEVICE_SPECIFIER: "
+ + ALC10.alcGetString(AL.getDevice(), ALC10.ALC_DEFAULT_DEVICE_SPECIFIER));
+ System.out.println(
+ "DEVICE_SPECIFIER: " + ALC10.alcGetString(AL.getDevice(), ALC10.ALC_DEVICE_SPECIFIER));
+ System.out.println("EXTENSIONS: " + ALC10.alcGetString(AL.getDevice(), ALC10.ALC_EXTENSIONS));
+
+ //mo query
+ buffer.rewind();
+ buffer.position(0);
+ ALC10.alcGetInteger(AL.getDevice(), ALC10.ALC_MAJOR_VERSION, buffer);
+ ALC10.alcGetInteger(AL.getDevice(), ALC10.ALC_MINOR_VERSION, (IntBuffer) buffer.position(1));
+
+ System.out.println("ALC_MAJOR_VERSION: " + buffer.get(0));
+ System.out.println("ALC_MINOR_VERSION: " + buffer.get(1));
+
+ //no check for ALC_ALL_ATTRIBUTES / ALC_ATTRIBUTES_SIZE since it
+ //is buggy on win32 - my dev platform
+
+ //get an enumerstion value
+ System.out.println(
+ "Value of ALC_MAJOR_VERSION: "
+ + ALC10.alcGetEnumValue(AL.getDevice(), "ALC_MAJOR_VERSION"));
+
+ alExit();
+ }
+
+ /**
+ * main entry point
+ *
+ * @param args String array containing arguments
+ */
+ public static void main(String[] args) {
+ ALCTest alcTest = new ALCTest();
+ alcTest.execute(args);
+ System.exit(0);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/openal/BasicTest.java b/src/java/org/lwjgl/test/openal/BasicTest.java
new file mode 100644
index 0000000..8ca68de
--- /dev/null
+++ b/src/java/org/lwjgl/test/openal/BasicTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2002-2008 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.test.openal;
+
+import java.nio.FloatBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.openal.ALC10;
+import org.lwjgl.opengl.DisplayMode;
+
+/**
+ *
+ * This is a basic test, which contains the most used stuff
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: BasicTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public abstract class BasicTest {
+
+ /**
+ * Creates an instance of PlayTest
+ */
+ public BasicTest() {
+ try {
+ AL.create();
+
+ System.out.println("Default device: " + ALC10.alcGetString(null, ALC10.ALC_DEFAULT_DEVICE_SPECIFIER));
+
+ if(ALC10.alcIsExtensionPresent(null, "ALC_ENUMERATION_EXT")) {
+ String[] devices = ALC10.alcGetString(null, ALC10.ALC_DEVICE_SPECIFIER).split("\0");
+ System.out.println("Available devices: ");
+ for(int i=0; i
+ * @version $Revision: 2983 $
+ * $Id: MovingSoundTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class MovingSoundTest extends BasicTest {
+
+ public static float MOVEMENT = 50.00f;
+
+ /**
+ * Creates an instance of MovingSoundTest
+ */
+ public MovingSoundTest() {
+ super();
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ if (args.length < 1) {
+ System.out.println("no argument supplied, assuming Footsteps.wav");
+ args = new String[] {"Footsteps.wav"};
+ }
+
+ try {
+ setDisplayMode();
+ Display.create();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ int lastError;
+ Vector3f sourcePosition = new Vector3f();
+ Vector3f listenerPosition = new Vector3f();
+
+ //initialize keyboard
+ try {
+ Keyboard.create();
+ } catch (Exception e) {
+ e.printStackTrace();
+ exit(-1);
+ }
+
+ //create 1 buffer and 1 source
+ IntBuffer buffers = BufferUtils.createIntBuffer(1);
+ IntBuffer sources = BufferUtils.createIntBuffer(1);
+
+ // al generate buffers and sources
+ buffers.position(0).limit(1);
+ AL10.alGenBuffers(buffers);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ sources.position(0).limit(1);
+ AL10.alGenSources(sources);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //load wave data
+ WaveData wavefile = WaveData.create(args[0]);
+
+ //copy to buffers
+ AL10.alBufferData(
+ buffers.get(0),
+ wavefile.format,
+ wavefile.data,
+ wavefile.samplerate);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //unload file again
+ wavefile.dispose();
+
+ //set up source input
+ AL10.alSourcei(sources.get(0), AL10.AL_BUFFER, buffers.get(0));
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ AL10.alSourcef(sources.get(0), AL10.AL_REFERENCE_DISTANCE, 1024.0f);
+ AL10.alSourcef(sources.get(0), AL10.AL_ROLLOFF_FACTOR, 0.5f);
+
+ //lets loop the sound
+ AL10.alSourcei(sources.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //play source 0
+ AL10.alSourcePlay(sources.get(0));
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ System.out.println("Move source with arrow keys\nMove listener with right shift and arrowkeys\nExit with ESC");
+
+ while(!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
+ Display.update();
+
+ Keyboard.poll();
+ if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
+ if(Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
+ listenerPosition.x -= MOVEMENT;
+ AL10.alListener3f(AL10.AL_POSITION, listenerPosition.x, listenerPosition.y, listenerPosition.z);
+ System.out.println("listenerx: " + listenerPosition.x);
+ } else {
+ sourcePosition.x -= MOVEMENT;
+ AL10.alSource3f(sources.get(0), AL10.AL_POSITION, sourcePosition.x, sourcePosition.y, sourcePosition.z);
+ System.out.println("sourcex: " + sourcePosition.x);
+ }
+ }
+ if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
+ if(Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
+ listenerPosition.x += MOVEMENT;
+ AL10.alListener3f(AL10.AL_POSITION, listenerPosition.x, listenerPosition.y, listenerPosition.z);
+ System.out.println("listenerx: " + listenerPosition.x);
+ } else {
+ sourcePosition.x += MOVEMENT;
+ AL10.alSource3f(sources.get(0), AL10.AL_POSITION, sourcePosition.x, sourcePosition.y, sourcePosition.z);
+ System.out.println("sourcex: " + sourcePosition.x);
+ }
+ }
+
+ if(Display.isCloseRequested()) {
+ break;
+ }
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException inte) {
+ }
+ }
+
+ //stop source 0
+ AL10.alSourceStop(sources.get(0));
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //delete buffers and sources
+ sources.position(0).limit(1);
+ AL10.alDeleteSources(sources);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ buffers.position(0).limit(1);
+ AL10.alDeleteBuffers(buffers);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //shutdown
+ alExit();
+ }
+
+ /**
+ * main entry point
+ *
+ * @param args String array containing arguments
+ */
+ public static void main(String[] args) {
+ MovingSoundTest movingSoundTest = new MovingSoundTest();
+ movingSoundTest.execute(args);
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/openal/OpenALCreationTest.java b/src/java/org/lwjgl/test/openal/OpenALCreationTest.java
new file mode 100644
index 0000000..959a78e
--- /dev/null
+++ b/src/java/org/lwjgl/test/openal/OpenALCreationTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2002-2008 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.test.openal;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.util.WaveData;
+
+/**
+ *
+ * Performs a creation test, by creating and destroying OpenAL twice.
+ * We cannot inherit from BasicTest since it follows another structure.
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: OpenALCreationTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class OpenALCreationTest {
+
+ /**
+ * Creates an instance of OpenALCreationTest
+ */
+ public OpenALCreationTest() {
+ }
+
+ public void alInitialize() {
+ try {
+ AL.create();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+ }
+
+ public void alExit() {
+ AL.destroy();
+ }
+
+ /**
+ * Creates an integer buffer to hold specified ints
+ * - strictly a utility method
+ *
+ * @param size how many int to contain
+ * @return created IntBuffer
+ */
+ protected IntBuffer createIntBuffer(int size) {
+ ByteBuffer temp = ByteBuffer.allocateDirect(4 * size);
+ temp.order(ByteOrder.nativeOrder());
+
+ return temp.asIntBuffer();
+ }
+
+ /**
+ * Exits the test NOW, printing errorcode to stdout
+ *
+ * @param error Error code causing exit
+ */
+ protected void exit(int error) {
+ System.out.println("OpenAL Error: " + AL10.alGetString(error));
+ alExit();
+ System.exit(-1);
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ int lastError;
+
+ //initialize AL, using ALC
+ System.out.print("initialize...");
+ alInitialize();
+ System.out.println("success");
+
+ //do some audio
+ executeAudioTest();
+
+ //shutdown
+ System.out.print("shutdown...");
+ alExit();
+ System.out.println("success");
+
+ //initialize AL, using ALC
+ System.out.print("initialize...");
+ alInitialize();
+ System.out.println("success");
+
+ //do some audio
+ executeAudioTest();
+
+ //shutdown
+ System.out.print("shutdown...");
+ alExit();
+ System.out.println("success");
+ }
+
+ /**
+ * Executes the audio test, which just plays some sound
+ */
+ private void executeAudioTest() {
+ int lastError;
+
+ //create 1 buffer and 1 source
+ IntBuffer buffers = createIntBuffer(1);
+ IntBuffer sources = createIntBuffer(1);
+
+ // al generate buffers and sources
+ buffers.position(0).limit(1);
+ AL10.alGenBuffers(buffers);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ sources.position(0).limit(1);
+ AL10.alGenSources(sources);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //load wave data
+ WaveData wavefile = WaveData.create("Footsteps.wav");
+
+ //copy to buffers
+ AL10.alBufferData(
+ buffers.get(0),
+ wavefile.format,
+ wavefile.data,
+ wavefile.samplerate);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //unload file again
+ wavefile.dispose();
+
+ //set up source input
+ AL10.alSourcei(sources.get(0), AL10.AL_BUFFER, buffers.get(0));
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //lets loop the sound
+ AL10.alSourcei(sources.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //play source 0
+ AL10.alSourcePlay(sources.get(0));
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //wait 5 secs
+ try {
+ System.out.print("Playing 'Footsteps.wav' for 2 seconds...");
+ Thread.sleep(2000);
+ } catch (InterruptedException inte) {
+ }
+ System.out.println("done");
+
+ //stop source 0
+ AL10.alSourceStop(sources.get(0));
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //delete buffers and sources
+ sources.position(0).limit(1);
+ AL10.alDeleteSources(sources);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ buffers.position(0).limit(1);
+ AL10.alDeleteBuffers(buffers);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+ }
+
+ /**
+ * main entry point
+ *
+ * @param args String array containing arguments
+ */
+ public static void main(String[] args) {
+ OpenALCreationTest oalCreationTest = new OpenALCreationTest();
+ oalCreationTest.execute(args);
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/openal/OpenALInfo.java b/src/java/org/lwjgl/test/openal/OpenALInfo.java
new file mode 100644
index 0000000..8ef5f2c
--- /dev/null
+++ b/src/java/org/lwjgl/test/openal/OpenALInfo.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2002-2008 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.test.openal;
+
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.openal.ALC10;
+import org.lwjgl.openal.ALC11;
+import org.lwjgl.openal.ALCdevice;
+
+/**
+ *
+ * idea from openal-info
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id$
+ */
+public class OpenALInfo {
+
+ /**
+ * Creates an instance of OpenALInfo
+ */
+ public OpenALInfo() {
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ try {
+ AL.create(null, -1, 60, false);
+ checkForErrors();
+ } catch (LWJGLException le) {
+ die("Init", le.getMessage());
+ }
+
+ printALCInfo();
+ printALInfo();
+
+ checkForErrors();
+
+ AL.destroy();
+ }
+
+ private void printALCInfo() {
+ IntBuffer version = BufferUtils.createIntBuffer(2);
+ ALCdevice device;
+
+ if(ALC10.alcIsExtensionPresent(null, "ALC_ENUMERATION_EXT")) {
+ if(ALC10.alcIsExtensionPresent(null, "ALC_ENUMERATE_ALL_EXT")) {
+ printDevices(ALC11.ALC_ALL_DEVICES_SPECIFIER, "playback");
+ } else {
+ printDevices(ALC10.ALC_DEVICE_SPECIFIER, "playback");
+ }
+ printDevices(ALC11.ALC_CAPTURE_DEVICE_SPECIFIER, "capture");
+ } else {
+ System.out.println("No device enumeration available");
+ }
+
+ device = ALC10.alcGetContextsDevice(ALC10.alcGetCurrentContext());
+ checkForErrors();
+
+ System.out.println("Default device: " + ALC10.alcGetString(device, ALC10.ALC_DEFAULT_DEVICE_SPECIFIER));
+
+ System.out.println("Default capture device: " + ALC10.alcGetString(device, ALC11.ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
+
+ ALC10.alcGetInteger(AL.getDevice(), ALC10.ALC_MAJOR_VERSION, version);
+ ALC10.alcGetInteger(AL.getDevice(), ALC10.ALC_MINOR_VERSION, (IntBuffer) version.position(1));
+ checkForErrors();
+
+ System.out.println("ALC version: " + (int)version.get(0) + "." + (int)version.get(1));
+
+ System.out.println("ALC extensions:");
+ String[] extensions = ALC10.alcGetString(device, ALC10.ALC_EXTENSIONS).split(" ");
+ for(int i=0; i
+ * @version $Revision: 2983 $
+ * $Id: PlayTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class PlayTest extends BasicTest {
+
+ private boolean usingVorbis;
+
+ /**
+ * Creates an instance of PlayTest
+ */
+ public PlayTest() {
+ super();
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ if(args.length < 1) {
+ System.out.println("no argument supplied, assuming Footsteps.wav");
+ args = new String[] {"Footsteps.wav"};
+ }
+
+ if(args[0].endsWith(".ogg")) {
+ System.out.print("Attempting to load Ogg Vorbis file, checking for extension...");
+ if(AL10.alIsExtensionPresent("AL_EXT_vorbis")) {
+ System.out.println("found");
+ usingVorbis = true;
+ } else {
+ System.out.println("not supported");
+ alExit();
+ System.exit(-1);
+ }
+ }
+
+ int lastError;
+
+ //create 1 buffer and 1 source
+ IntBuffer buffers = BufferUtils.createIntBuffer(1);
+ IntBuffer sources = BufferUtils.createIntBuffer(1);
+
+ // al generate buffers and sources
+ buffers.position(0).limit(1);
+ AL10.alGenBuffers(buffers);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ sources.position(0).limit(1);
+ AL10.alGenSources(sources);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ if(usingVorbis) {
+ ByteBuffer filebuffer = getData(args[0]);
+
+ // pass directly to buffer data
+ AL10.alBufferData(buffers.get(0), AL10.AL_FORMAT_VORBIS_EXT, filebuffer, -1);
+ filebuffer.clear();
+ } else {
+ // load wave data from buffer
+ WaveData wavefile = WaveData.create(args[0]);
+
+ //copy to buffers
+ AL10.alBufferData(buffers.get(0), wavefile.format, wavefile.data, wavefile.samplerate);
+
+ //unload file again
+ wavefile.dispose();
+ }
+
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //set up source input
+ AL10.alSourcei(sources.get(0), AL10.AL_BUFFER, buffers.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //lets loop the sound
+ AL10.alSourcei(sources.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //play source 0
+ AL10.alSourcePlay(sources.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //wait 5 secs
+ try {
+ System.out.println("Waiting 5 seconds for sound to complete");
+ Thread.sleep(5000);
+ } catch (InterruptedException inte) {
+ }
+
+ //stop source 0
+ AL10.alSourceStop(sources.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //delete buffers and sources
+ sources.position(0).limit(1);
+ AL10.alDeleteSources(sources);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ buffers.position(0).limit(1);
+ AL10.alDeleteBuffers(buffers);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //no errorchecking from now on, since our context is gone.
+ //shutdown
+ alExit();
+ }
+
+ /**
+ * Reads the file into a ByteBuffer
+ *
+ * @param filename Name of file to load
+ * @return ByteBuffer containing file data
+ */
+ protected ByteBuffer getData(String filename) {
+ ByteBuffer buffer = null;
+
+ System.out.println("Attempting to load: " + filename);
+
+ try {
+ BufferedInputStream bis = new BufferedInputStream(WaveData.class.getClassLoader().getResourceAsStream(filename));
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ int bufferLength = 4096;
+ byte[] readBuffer = new byte[bufferLength];
+ int read = -1;
+
+ while((read = bis.read(readBuffer, 0, bufferLength)) != -1) {
+ baos.write(readBuffer, 0, read);
+ }
+
+ //done reading, close
+ bis.close();
+
+ // if ogg vorbis data, we need to pass it unmodified to alBufferData
+ buffer = ByteBuffer.allocateDirect(baos.size());
+ buffer.order(ByteOrder.nativeOrder());
+ buffer.put(baos.toByteArray());
+ buffer.rewind();
+ } catch (Exception ioe) {
+ ioe.printStackTrace();
+ }
+ return buffer;
+ }
+
+ /**
+ * main entry point
+ *
+ * @param args String array containing arguments
+ */
+ public static void main(String[] args) {
+ PlayTest playTest = new PlayTest();
+ playTest.execute(args);
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/openal/PlayTestMemory.java b/src/java/org/lwjgl/test/openal/PlayTestMemory.java
new file mode 100644
index 0000000..aedc4c4
--- /dev/null
+++ b/src/java/org/lwjgl/test/openal/PlayTestMemory.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2002-2008 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.test.openal;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.util.WaveData;
+
+/**
+ *
+ * This is a basic play test
+ * Yes, over zealous use of getError ;)
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: PlayTestMemory.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class PlayTestMemory extends BasicTest {
+
+ private boolean usingVorbis;
+
+ /**
+ * Creates an instance of PlayTestMemory
+ */
+ public PlayTestMemory() {
+ super();
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ if(args.length < 1) {
+ System.out.println("no argument supplied, assuming Footsteps.wav");
+ args = new String[] {"Footsteps.wav"};
+ }
+
+ if(args[0].endsWith(".ogg")) {
+ System.out.print("Attempting to load Ogg Vorbis file, checking for extension...");
+ if(AL10.alIsExtensionPresent("AL_EXT_vorbis")) {
+ System.out.println("found");
+ usingVorbis = true;
+ } else {
+ System.out.println("not supported");
+ alExit();
+ System.exit(-1);
+ }
+ }
+
+ int lastError;
+
+ //create 1 buffer and 1 source
+ IntBuffer buffers = BufferUtils.createIntBuffer(1);
+ IntBuffer sources = BufferUtils.createIntBuffer(1);
+
+ // al generate buffers and sources
+ buffers.position(0).limit(1);
+ AL10.alGenBuffers(buffers);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ sources.position(0).limit(1);
+ AL10.alGenSources(sources);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //load wave data
+ ByteBuffer filebuffer = getData(args[0]);
+ if(filebuffer == null) {
+ System.out.println("Error loading file: " + args[0]);
+ System.exit(-1);
+ }
+
+ System.out.println("loaded " + filebuffer.capacity());
+
+ //ALUTLoadWAVData file = alut.loadWAVMemory(Sys.getDirectBufferAddress(filebuffer));
+ if(usingVorbis) {
+ // pass directly to buffer data
+ AL10.alBufferData(buffers.get(0), AL10.AL_FORMAT_VORBIS_EXT, filebuffer, -1);
+ filebuffer.clear();
+ } else {
+ // load wave data from buffer
+ WaveData wavefile = WaveData.create(filebuffer.array());
+
+ //copy to buffers
+ AL10.alBufferData(buffers.get(0), wavefile.format, wavefile.data, wavefile.samplerate);
+
+ //unload file again
+ wavefile.dispose();
+ }
+
+ // check for errors
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+
+ //set up source input
+ AL10.alSourcei(sources.get(0), AL10.AL_BUFFER, buffers.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //lets loop the sound
+ AL10.alSourcei(sources.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //play source 0
+ AL10.alSourcePlay(sources.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //wait 5 secs
+ try {
+ System.out.println("Waiting 5 seconds for sound to complete");
+ Thread.sleep(5000);
+ } catch (InterruptedException inte) {
+ }
+
+ //stop source 0
+ AL10.alSourceStop(sources.get(0));
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //delete buffers and sources
+ sources.position(0).limit(1);
+ AL10.alDeleteSources(sources);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ buffers.position(0).limit(1);
+ AL10.alDeleteBuffers(buffers);
+ if((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ exit(lastError);
+ }
+
+ //no errorchecking from now on, since our context is gone.
+ alExit();
+ }
+
+ /**
+ * Reads the file into a ByteBuffer
+ *
+ * @param filename Name of file to load
+ * @return ByteBuffer containing file data
+ */
+ protected ByteBuffer getData(String filename) {
+ ByteBuffer buffer = null;
+
+ System.out.println("Attempting to load: " + filename);
+
+ try {
+ BufferedInputStream bis = new BufferedInputStream(WaveData.class.getClassLoader().getResourceAsStream(filename));
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ int bufferLength = 4096;
+ byte[] readBuffer = new byte[bufferLength];
+ int read = -1;
+
+ while((read = bis.read(readBuffer, 0, bufferLength)) != -1) {
+ baos.write(readBuffer, 0, read);
+ }
+
+ //done reading, close
+ bis.close();
+
+ // if ogg vorbis data, we need to pass it unmodified to alBufferData
+ if(usingVorbis) {
+ buffer = ByteBuffer.allocateDirect(baos.size());
+ } else {
+ buffer = ByteBuffer.allocate(baos.size());
+ }
+ buffer.order(ByteOrder.nativeOrder());
+ buffer.put(baos.toByteArray());
+ buffer.rewind();
+ } catch (Exception ioe) {
+ ioe.printStackTrace();
+ }
+ return buffer;
+ }
+
+ /**
+ * main entry point
+ *
+ * @param args String array containing arguments
+ */
+ public static void main(String[] args) {
+ PlayTestMemory playTestMemory = new PlayTestMemory();
+ playTestMemory.execute(args);
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/openal/PositionTest.java b/src/java/org/lwjgl/test/openal/PositionTest.java
new file mode 100644
index 0000000..18feffa
--- /dev/null
+++ b/src/java/org/lwjgl/test/openal/PositionTest.java
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2002-2008 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.test.openal;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.GLU;
+import org.lwjgl.util.WaveData;
+
+/**
+ *
+ * This test demonstrates OpenAL positioning Based on the example by Chad Armstrong
+ * (http://www.edenwaith.com/products/pige/tutorials/openal.php)
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: PositionTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class PositionTest extends BasicTest {
+
+ /** *Small* glut implementation :) */
+ private GLUT glut;
+
+ /** Width of window */
+ public static final int WINDOW_WIDTH = 640;
+
+ /** Height of window */
+ public static final int WINDOW_HEIGHT = 480;
+
+ /** LEFT enumeration */
+ public static final int LEFT = 0;
+
+ /** CENTER enumeration */
+ public static final int CENTER = 1;
+
+ /** RIGHT enumeration */
+ public static final int RIGHT = 2;
+
+ /** Whether the demo is done */
+ private boolean finished = false;
+
+ /** Whether in pause mode */
+ private boolean pauseMode = false;
+
+ // OpenAL stuff
+ // ===================================================
+
+ /** OpenAL buffers */
+ private IntBuffer soundBuffers = BufferUtils.createIntBuffer(3);
+
+ /** OpenAL sources */
+ private IntBuffer soundSources = BufferUtils.createIntBuffer(3);
+
+ /** Position of listener */
+ private FloatBuffer listenerPosition = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f });
+
+ /** Velocity of listener */
+ private FloatBuffer listenerVelocity = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f });
+
+ /** Orientation of listener */
+ private FloatBuffer listenerOrientation =
+ createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f });
+
+ /** Position of left sound */
+ private FloatBuffer leftPosition = createFloatBuffer(new float[] { -2.0f, 0.0f, 0.0f });
+
+ /** Velocity of left sound */
+ private FloatBuffer leftVelocity = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f });
+
+ /** Position of center sound */
+ private FloatBuffer centerPosition = createFloatBuffer(new float[] { 0.0f, 0.0f, -4.0f });
+
+ /** Velocity of center sound */
+ private FloatBuffer centerVelocity = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f });
+
+ /** Position of right sound */
+ private FloatBuffer rightPosition = createFloatBuffer(new float[] { 2.0f, 0.0f, 0.0f });
+
+ /** Velocity of right sound */
+ private FloatBuffer rightVelocity = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f });
+ // ---------------------------------------------------
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ // Setup needed stuff
+ try {
+ setup();
+ } catch (Exception e) {
+ System.out.println("Error setting up demonstration: ");
+ e.printStackTrace();
+ System.exit(-1);
+ }
+
+ // run the actual demonstration
+ run();
+
+ // shutdown
+ shutdown();
+ }
+
+ /**
+ * Performs setup of demonstration
+ */
+ private void setup() throws Exception {
+
+ // Setup Window
+ // =====================================================
+ LWJGLUtil.log("Setting up window");
+
+ // calc center
+ int centerX = (Display.getDisplayMode().getWidth() - WINDOW_WIDTH) / 2;
+ int centerY = (Display.getDisplayMode().getHeight() - WINDOW_HEIGHT) / 2;
+
+ // setup window
+ setDisplayMode();
+ Display.create();
+ // -----------------------------------------------------
+
+ // Setup OpenGL
+ // =====================================================
+ LWJGLUtil.log("Setting up OpenGL");
+
+ GL11.glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluPerspective(50.0f, (float) WINDOW_WIDTH / WINDOW_HEIGHT, 0.0f, 50.0f);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glTranslatef(0.0f, 0.0f, -6.6f);
+ GL11.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glut = this.new GLUT();
+
+ Display.setVSyncEnabled(true);
+ // -----------------------------------------------------
+
+ // Setup OpenAL
+ // =====================================================
+ LWJGLUtil.log("Setting up OpenAL");
+
+ AL10.alListener(AL10.AL_POSITION, listenerPosition);
+ AL10.alListener(AL10.AL_VELOCITY, listenerVelocity);
+ AL10.alListener(AL10.AL_ORIENTATION, listenerOrientation);
+
+ // creating buffers
+ LWJGLUtil.log("Creating buffers");
+ AL10.alGenBuffers(soundBuffers);
+ soundBuffers.rewind();
+
+ // creating sources
+ AL10.alGenSources(soundSources);
+ soundSources.rewind();
+
+ // load sound files (left, center, right).wav
+ LWJGLUtil.log("Loading soundfiles...");
+
+ LWJGLUtil.log("Loading left.wav");
+ WaveData left = WaveData.create("left.wav");
+ AL10.alBufferData(soundBuffers.get(LEFT), left.format, left.data, left.samplerate);
+ AL10.alSourcef(soundSources.get(LEFT), AL10.AL_PITCH, 1.0f);
+ AL10.alSourcef(soundSources.get(LEFT), AL10.AL_GAIN, 1.0f);
+ AL10.alSource(soundSources.get(LEFT), AL10.AL_POSITION, leftPosition);
+ AL10.alSource(soundSources.get(LEFT), AL10.AL_VELOCITY, leftVelocity);
+ AL10.alSourcei(soundSources.get(LEFT), AL10.AL_BUFFER, soundBuffers.get(LEFT));
+ AL10.alSourcei(soundSources.get(LEFT), AL10.AL_LOOPING, AL10.AL_TRUE);
+
+ LWJGLUtil.log("Loading center.wav");
+ WaveData center = WaveData.create("center.wav");
+ AL10.alBufferData(soundBuffers.get(CENTER), center.format, center.data, center.samplerate);
+ AL10.alSourcef(soundSources.get(CENTER), AL10.AL_PITCH, 1.0f);
+ AL10.alSourcef(soundSources.get(CENTER), AL10.AL_GAIN, 1.0f);
+ AL10.alSource(soundSources.get(CENTER), AL10.AL_POSITION, centerPosition);
+ AL10.alSource(soundSources.get(CENTER), AL10.AL_VELOCITY, centerVelocity);
+ AL10.alSourcei(soundSources.get(CENTER), AL10.AL_BUFFER, soundBuffers.get(CENTER));
+ AL10.alSourcei(soundSources.get(CENTER), AL10.AL_LOOPING, AL10.AL_TRUE);
+
+ LWJGLUtil.log("Loading right.wav");
+ WaveData right = WaveData.create("right.wav");
+ AL10.alBufferData(soundBuffers.get(RIGHT), right.format, right.data, right.samplerate);
+ AL10.alSourcef(soundSources.get(RIGHT), AL10.AL_PITCH, 1.0f);
+ AL10.alSourcef(soundSources.get(RIGHT), AL10.AL_GAIN, 1.0f);
+ AL10.alSource(soundSources.get(RIGHT), AL10.AL_POSITION, rightPosition);
+ AL10.alSource(soundSources.get(RIGHT), AL10.AL_VELOCITY, rightVelocity);
+ AL10.alSourcei(soundSources.get(RIGHT), AL10.AL_BUFFER, soundBuffers.get(RIGHT));
+ AL10.alSourcei(soundSources.get(RIGHT), AL10.AL_LOOPING, AL10.AL_TRUE);
+
+ LWJGLUtil.log("Soundfiles loaded successfully");
+ // -----------------------------------------------------
+
+ Mouse.setGrabbed(true);
+ }
+
+ /**
+ * Runs the actual demonstration
+ */
+ private void run() {
+ boolean firstRun = true;
+
+ System.out.println("Press 1/4 (left), 2/5 (center) or 3/6 (right) to toggle sound");
+ System.out.println("Press LEFT/RIGHT to move along x axis");
+ System.out.println("Press SHIFT and either UP/DOWN to move along y axis");
+ System.out.println("Press UP/DOWN to move along z axis");
+ System.out.println("Move along the x and y axis with the mouse");
+ System.out.println("Press LEFT or RIGHT mouse button to move along z axis");
+ System.out.println("Press ESC to exit demo");
+
+ LWJGLUtil.log(
+ "Listener position: "
+ + listenerPosition.get(0)
+ + ", "
+ + listenerPosition.get(1)
+ + ", "
+ + listenerPosition.get(2));
+ LWJGLUtil.log("Left position: " + leftPosition.get(0) + ", " + leftPosition.get(1) + ", " + leftPosition.get(2));
+ LWJGLUtil.log("Center position: " + centerPosition.get(0) + ", " + centerPosition.get(1) + ", " + centerPosition.get(2));
+ LWJGLUtil.log("Right position: " + rightPosition.get(0) + ", " + rightPosition.get(1) + ", " + rightPosition.get(2));
+
+ while (!finished) {
+ // handle any input
+ handleInput();
+
+ // allow window to process internal messages
+ Display.update();
+
+ // render and paint if !minimized and not dirty
+ if(Display.isVisible()) {
+ render();
+ } else {
+ // sleeeeeep
+ pause(100);
+ }
+
+ // act on pause mode
+ paused(!(Display.isVisible() || Display.isActive()));
+
+ // start sound after first paint, since we don't want
+ // the delay before something is painted on the screen
+ if (firstRun && !pauseMode) {
+ firstRun = false;
+
+ // start sounds with delays
+ startSounds();
+ }
+ }
+ }
+
+ /**
+ * Starts playing the sounds at different times
+ */
+ private void startSounds() {
+ AL10.alSourcePlay(soundSources.get(LEFT));
+ pause(300);
+ AL10.alSourcePlay(soundSources.get(CENTER));
+ pause(500);
+ AL10.alSourcePlay(soundSources.get(RIGHT));
+ }
+
+ /**
+ * Handles any changes in pause mode
+ *
+ * @param paused Which pause mode to enter
+ */
+ private void paused(boolean paused) {
+ // if requesting pause, and not paused - pause and stop sound
+ if(paused && !pauseMode) {
+ pauseMode = true;
+ AL10.alSourcePause(soundSources);
+ System.out.println("pauseMode = true");
+ }
+
+ // else go out of pause mode and start sounds
+ else if(!paused && pauseMode) {
+ pauseMode = false;
+ startSounds();
+ System.out.println("pauseMode = false");
+ }
+ }
+
+ /**
+ * Handles any input
+ */
+ private void handleInput() {
+ // User wants to exit?
+ finished = Display.isCloseRequested() || Keyboard.isKeyDown(Keyboard.KEY_ESCAPE);
+ if (finished) {
+ return;
+ }
+
+ boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
+
+ // Test for play
+ // ============================================
+ if (Keyboard.isKeyDown(Keyboard.KEY_1)) {
+ AL10.alSourcePlay(soundSources.get(LEFT));
+ LWJGLUtil.log("Playing left.wav");
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_2)) {
+ AL10.alSourcePlay(soundSources.get(CENTER));
+ LWJGLUtil.log("Playing center.wav");
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_3)) {
+ AL10.alSourcePlay(soundSources.get(RIGHT));
+ LWJGLUtil.log("Playing right.wav");
+ }
+ // --------------------------------------------
+
+ // Test for stop
+ // ============================================
+ if (Keyboard.isKeyDown(Keyboard.KEY_4)) {
+ AL10.alSourceStop(soundSources.get(LEFT));
+ LWJGLUtil.log("Stopped left.wav");
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_5)) {
+ AL10.alSourceStop(soundSources.get(CENTER));
+ LWJGLUtil.log("Stopped center.wav");
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_6)) {
+ AL10.alSourceStop(soundSources.get(RIGHT));
+ LWJGLUtil.log("Stopped right.wav");
+ }
+ // --------------------------------------------
+
+ // Test for movement with keyboard
+ // ============================================
+ if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
+ listenerPosition.put(0, listenerPosition.get(0) - 0.1f);
+ AL10.alListener(AL10.AL_POSITION, listenerPosition);
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
+ listenerPosition.put(0, listenerPosition.get(0) + 0.1f);
+ AL10.alListener(AL10.AL_POSITION, listenerPosition);
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
+ if (shift) {
+ listenerPosition.put(1, listenerPosition.get(1) + 0.1f);
+ } else {
+ listenerPosition.put(2, listenerPosition.get(2) - 0.1f);
+ }
+ AL10.alListener(AL10.AL_POSITION, listenerPosition);
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
+ if (shift) {
+ listenerPosition.put(1, listenerPosition.get(1) - 0.1f);
+ } else {
+ listenerPosition.put(2, listenerPosition.get(2) + 0.1f);
+ }
+ AL10.alListener(AL10.AL_POSITION, listenerPosition);
+ }
+ // --------------------------------------------
+
+ // Test for movement with Mouse
+ // ============================================
+ listenerPosition.put(0, listenerPosition.get(0) + (0.01f * Mouse.getDX()));
+ listenerPosition.put(1, listenerPosition.get(1) + (0.01f * Mouse.getDY()));
+ if (Mouse.isButtonDown(0)) {
+ listenerPosition.put(2, listenerPosition.get(2) - 0.1f);
+ }
+ if (Mouse.isButtonDown(1)) {
+ listenerPosition.put(2, listenerPosition.get(2) + 0.1f);
+ }
+
+ AL10.alListener(AL10.AL_POSITION, listenerPosition);
+
+ // empty mouse buffer
+ while(Mouse.next());
+ }
+
+ /**
+ * Render the scene
+ */
+ private void render() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+ GL11.glPushMatrix();
+ {
+ GL11.glRotatef(20.0f, 1.0f, 1.0f, 0.0f);
+
+ // left
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(leftPosition.get(0), leftPosition.get(1), leftPosition.get(2));
+ GL11.glColor3f(1.0f, 0.0f, 0.0f);
+ glut.glutWireCube(0.5f);
+ }
+ GL11.glPopMatrix();
+
+ // center
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(centerPosition.get(0), centerPosition.get(1), centerPosition.get(2));
+ GL11.glColor3f(0.0f, 0.0f, 1.0f);
+ glut.glutWireCube(0.5f);
+ }
+ GL11.glPopMatrix();
+
+ // right
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(rightPosition.get(0), rightPosition.get(1), rightPosition.get(2));
+ GL11.glColor3f(0.0f, 1.0f, 0.0f);
+ glut.glutWireCube(0.5f);
+ }
+ GL11.glPopMatrix();
+
+ // listener
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(listenerPosition.get(0), listenerPosition.get(1), listenerPosition.get(2));
+ GL11.glColor3f(1.0f, 1.0f, 1.0f);
+ glut.glutSolidCube(0.5f);
+ }
+ GL11.glPopMatrix();
+ }
+ GL11.glPopMatrix();
+ }
+
+ /**
+ * Shutdown of demonstration
+ */
+ private void shutdown() {
+ LWJGLUtil.log("Shutting down OpenAL");
+ AL10.alSourceStop(soundSources);
+ AL10.alDeleteSources(soundSources);
+ AL10.alDeleteBuffers(soundBuffers);
+ AL.destroy();
+
+ LWJGLUtil.log("Shutting down Window");
+ Display.destroy();
+ }
+
+ /**
+ * main entry point
+ *
+ * @param args
+ * String array containing arguments
+ */
+ public static void main(String[] args) {
+ PositionTest positionTest = new PositionTest();
+ positionTest.execute(args);
+ System.exit(0);
+ }
+
+ /**
+ * Minute implementation of GLUT:
COPYRIGHT:
+ *
+ * The OpenGL Utility Toolkit distribution for Win32 (Windows NT & Windows
+ * 95) contains source code modified from the original source code for GLUT
+ * version 3.3 which was developed by Mark J. Kilgard. The original source
+ * code for GLUT is Copyright 1997 by Mark J. Kilgard. GLUT for Win32 is
+ * Copyright 1997 by Nate Robins and is not in the public domain, but it is
+ * freely distributable without licensing fees. It is provided without
+ * guarantee or warrantee expressed or implied. It was ported with the
+ * permission of Mark J. Kilgard by Nate Robins.
+ *
+ * THIS SOURCE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OR MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ */
+ class GLUT {
+
+ float n[][] = new float[][] { { -1.0f, 0.0f, 0.0f }, {
+ 0.0f, 1.0f, 0.0f }, {
+ 1.0f, 0.0f, 0.0f }, {
+ 0.0f, -1.0f, 0.0f }, {
+ 0.0f, 0.0f, 1.0f }, {
+ 0.0f, 0.0f, -1.0f }
+ };
+
+ int faces[][] = new int[][] { { 0, 1, 2, 3 }, {
+ 3, 2, 6, 7 }, {
+ 7, 6, 5, 4 }, {
+ 4, 5, 1, 0 }, {
+ 5, 6, 2, 1 }, {
+ 7, 4, 0, 3 }
+ };
+ float v[][] = new float[8][3];
+
+ public void glutWireCube(float size) {
+ drawBox(size, GL11.GL_LINE_LOOP);
+ }
+
+ public void glutSolidCube(float size) {
+ drawBox(size, GL11.GL_QUADS);
+ }
+
+ private void drawBox(float size, int type) {
+
+ v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
+ v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
+ v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
+ v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
+ v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
+ v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
+
+ for (int i = 5; i >= 0; i--) {
+ GL11.glBegin(type);
+ GL11.glNormal3f(n[i][0], n[i][1], n[i][2]);
+ GL11.glVertex3f(v[faces[i][0]][0], v[faces[i][0]][1], v[faces[i][0]][2]);
+ GL11.glVertex3f(v[faces[i][1]][0], v[faces[i][1]][1], v[faces[i][1]][2]);
+ GL11.glVertex3f(v[faces[i][2]][0], v[faces[i][2]][1], v[faces[i][2]][2]);
+ GL11.glVertex3f(v[faces[i][3]][0], v[faces[i][3]][1], v[faces[i][3]][2]);
+ GL11.glEnd();
+ }
+
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/test/openal/SourceLimitTest.java b/src/java/org/lwjgl/test/openal/SourceLimitTest.java
new file mode 100644
index 0000000..98e7a1b
--- /dev/null
+++ b/src/java/org/lwjgl/test/openal/SourceLimitTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2002-2008 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.test.openal;
+
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.openal.OpenALException;
+
+/**
+ *
+ * Simple test for testing the number of available sources
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: SourceLimitTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class SourceLimitTest extends BasicTest {
+
+ /** Sources to create */
+ protected int sourcesToCreate = 64;
+
+ /**
+ * Creates an instance of SourceLimitTest
+ */
+ public SourceLimitTest() {
+ super();
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+ //parse 1st arg to sourcecount
+ if (args.length > 0) {
+ try {
+ sourcesToCreate = Integer.parseInt(args[0]);
+ } catch (NumberFormatException nfe) {
+ System.out.println(
+ "Unable to parse parameter to integer. Defaulting to 64 sources.");
+ }
+ }
+
+ System.out.print("Creating " + sourcesToCreate + " in one go...");
+ try {
+ CreateAllSources();
+ } catch(OpenALException oale) {
+ oale.printStackTrace();
+ }
+
+
+ System.out.print("Creating " + sourcesToCreate + " one at a time...");
+ try {
+ CreateSourcesStep();
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ //shutdown
+ alExit();
+ }
+
+ /**
+ * Tests the creation of n sources in on go
+ */
+ protected void CreateAllSources() {
+ int lastError;
+
+ //make bytbuffer that can hold sourcesToCreate sources
+ IntBuffer sources = BufferUtils.createIntBuffer(sourcesToCreate);
+
+ //Create sourcesToCreate sources in one fell swoop
+ try {
+ sources.position(0).limit(sourcesToCreate);
+ AL10.alGenSources(sources);
+
+ //delete sources
+ sources.position(0).limit(sourcesToCreate);
+ AL10.alDeleteSources(sources);
+
+ System.out.println("created " + sourcesToCreate + " sources successfully!");
+ } catch (OpenALException oale) {
+ System.out.println("Unable to create " + sourcesToCreate + " sources");
+ }
+ }
+
+ /**
+ * Tests if n sources can be created one at a time
+ */
+ protected void CreateSourcesStep() {
+ int lastError;
+ int sourcesCreated = 0;
+
+ //make bytbuffer that can hold sourcesToCreate sources
+ IntBuffer[] sources = new IntBuffer[sourcesToCreate];
+
+ //create the sources
+ try {
+ for (int i = 0; i < sourcesToCreate; i++) {
+ sources[i] = BufferUtils.createIntBuffer(1);
+ sources[i].position(0).limit(1);
+ AL10.alGenSources(sources[i]);
+ if ((lastError = AL10.alGetError()) != AL10.AL_NO_ERROR) {
+ break;
+ }
+ sourcesCreated++;
+ }
+ } catch (OpenALException oale) {
+ System.out.println("failed to create source: " + (sourcesCreated + 1));
+ }
+
+ //delete allocated sources
+ for (int i = 0; i < sourcesCreated; i++) {
+ //delete buffers and sources
+ sources[i].position(0).limit(1);
+ AL10.alDeleteSources(sources[i]);
+ }
+
+ if(sourcesCreated != sourcesToCreate) {
+ System.out.println("created " + sourcesCreated + " sources before failing");
+ } else {
+ System.out.println("created " + sourcesCreated + " sources successfully!");
+ }
+ }
+
+ /**
+ * main entry point
+ *
+ * @param args String array containing arguments
+ */
+ public static void main(String[] args) {
+ SourceLimitTest sourceLimitTest = new SourceLimitTest();
+ sourceLimitTest.execute(args);
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/openal/StressTest.java b/src/java/org/lwjgl/test/openal/StressTest.java
new file mode 100644
index 0000000..f67b7d8
--- /dev/null
+++ b/src/java/org/lwjgl/test/openal/StressTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2002-2008 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.test.openal;
+
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.util.WaveData;
+
+/**
+ *
+ * Simple test for stresstesting OpenAL playing random samples ad nausea
+ *
+ * @author Brian Matzon
+ * @version $Revision: 2983 $
+ * $Id: StressTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class StressTest extends BasicTest {
+
+ /** Buffer containing sources */
+ private IntBuffer sources;
+
+ /** Buffer containing buffers */
+ private IntBuffer buffers;
+
+ /**
+ * Creates an instance of StressTest
+ */
+ public StressTest() {
+ super();
+ }
+
+ /**
+ * Runs the actual test, using supplied arguments
+ */
+ protected void execute(String[] args) {
+
+ createSources();
+
+ createBuffers();
+
+ try {
+ loadSamples();
+ runTest();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ alExit();
+ }
+
+ private void createSources() {
+ sources = BufferUtils.createIntBuffer(4);
+ sources.position(0).limit(4);
+ AL10.alGenSources(sources);
+ if (AL10.alGetError() != AL10.AL_NO_ERROR) {
+ System.out.println("Unable to create 4 sources");
+ alExit();
+ }
+ }
+
+ private void createBuffers() {
+ buffers = BufferUtils.createIntBuffer(10);
+ buffers.position(0).limit(10);
+ AL10.alGenBuffers(buffers);
+ if (AL10.alGetError() != AL10.AL_NO_ERROR) {
+ System.out.println("Unable to create 10 buffers");
+ sources.position(0).limit(4);
+ AL10.alDeleteSources(sources);
+ alExit();
+ }
+ }
+
+ private void loadSamples() throws Exception {
+ AL10.alGetError();
+ WaveData data = WaveData.create("ding.wav");
+ for (int i = 1; i <= 10; i++) {
+ AL10.alBufferData(
+ buffers.get(i - 1),
+ data.format,
+ data.data,
+ data.samplerate);
+
+ if (AL10.alGetError() != AL10.AL_NO_ERROR) {
+ System.out.println("Failed to load " + i + ".wav into buffer");
+ sources.position(0).limit(4);
+ AL10.alDeleteSources(sources);
+ buffers.position(0).limit(10);
+ AL10.alDeleteBuffers(buffers);
+
+ alExit();
+ }
+ }
+ data.dispose();
+ }
+
+ public void runTest() {
+ int iterations = 0;
+ int randomBuffer;
+ int startSlot = 1;
+ int nextSlot = startSlot;
+ long startTime = System.currentTimeMillis();
+
+ //mark background source as looping
+ AL10.alSourcei(sources.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);
+
+ //play background
+ AL10.alSourcei(sources.get(0), AL10.AL_BUFFER, buffers.get(0));
+ AL10.alSourcePlay(sources.get(0));
+
+ while (System.currentTimeMillis() - startTime < (2000)) {
+
+ randomBuffer = getRandomBuffer();
+ System.out.println("random:" + randomBuffer);
+
+ //stop source at slot
+ AL10.alSourceStop(sources.get(nextSlot));
+ if (AL10.alGetError() != AL10.AL_NO_ERROR) {
+ System.out.println("Error stopping source.");
+ }
+ System.out.println("Stopped source: " + nextSlot);
+
+ //link source<->buffer
+ AL10.alSourcei(sources.get(nextSlot), AL10.AL_BUFFER, buffers.get(randomBuffer));
+ if (AL10.alGetError() != AL10.AL_NO_ERROR) {
+ System.out.println("Error linking buffer and source.");
+ }
+ System.out.println("linked source " + nextSlot + " with buffer " + randomBuffer);
+
+ //start playing
+ System.out.println("playing source " + nextSlot);
+ AL10.alSourcePlay(sources.get(nextSlot++));
+ if (nextSlot == 4) {
+ nextSlot = startSlot;
+ }
+
+ //pause
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException inte) {
+ }
+
+ //debug info
+ if ((++iterations % 10) == 0) {
+ System.out.println("========================");
+ System.out.println("MaxMemory: " + Runtime.getRuntime().maxMemory() / 1024);
+ System.out.println("FreeMemory: " + Runtime.getRuntime().freeMemory() / 1024);
+ System.out.println("TotalMemory: " + Runtime.getRuntime().totalMemory() / 1024);
+ System.out.println("========================");
+ }
+ }
+
+ //stop all sources
+ for (int i = 0; i < 4; i++) {
+ AL10.alSourceStop(sources.get(i));
+ System.out.println("Stopping source " + (i+1));
+ }
+
+ //test done - ask for user input
+ try {
+ System.out.println("Test completed");
+ System.out.println("========================");
+ System.out.println("MaxMemory: " + Runtime.getRuntime().maxMemory() / 1024);
+ System.out.println("FreeMemory: " + Runtime.getRuntime().freeMemory() / 1024);
+ System.out.println("TotalMemory: " + Runtime.getRuntime().totalMemory() / 1024);
+ System.out.println("========================");
+ System.out.println("Push any key to exit...");
+ System.in.read();
+ } catch (Exception e) {
+ }
+
+ sources.position(0).limit(4);
+ AL10.alDeleteSources(sources);
+ buffers.position(0).limit(10);
+ AL10.alDeleteBuffers(buffers);
+ }
+
+ private int getRandomBuffer() {
+ return (int) (Math.random() * 10.0);
+ }
+
+ /**
+ * main entry point
+ *
+ * @param args String array containing arguments
+ */
+ public static void main(String[] args) {
+ StressTest stressTest = new StressTest();
+ stressTest.execute(args);
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java b/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java
new file mode 100644
index 0000000..d749c8a
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.GLU;
+import org.lwjgl.util.vector.Vector2f;
+
+/**
+ *
+ * Tests switching between windowed and fullscreen
+ *
+ * @author Brian Matzon
+ * @version $Revision: 3172 $
+ * $Id: FullScreenWindowedTest.java 3172 2008-12-28 19:30:43Z elias_naur $
+ */
+public class FullScreenWindowedTest {
+ /** Intended deiplay mode */
+ private DisplayMode mode;
+ /** our quad moving around */
+ private Vector2f quadPosition;
+ /** our quadVelocity */
+ private Vector2f quadVelocity;
+ /** angle of quad */
+ private float angle;
+ /** degrees to rotate per frame */
+ private float angleRotation = 1.0f;
+ /** Max speed of all changable attributes */
+ private static final float MAX_SPEED = 20.0f;
+
+ /**
+ * Creates a FullScreenWindowedTest
+ */
+ public FullScreenWindowedTest() {
+ }
+ /**
+ * Executes the test
+ */
+ public void execute() {
+ initialize();
+ mainLoop();
+ cleanup();
+ }
+
+ private void switchMode() throws LWJGLException {
+ mode = findDisplayMode(800, 600, Display.getDisplayMode().getBitsPerPixel());
+ Display.setDisplayModeAndFullscreen(mode);
+ }
+
+ /**
+ * Initializes the test
+ */
+ private void initialize() {
+ try {
+ //find displaymode
+ switchMode();
+ // start of in windowed mode
+ Display.create();
+ glInit();
+ quadPosition = new Vector2f(100f, 100f);
+ quadVelocity = new Vector2f(1.0f, 1.0f);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ /**
+ * Runs the main loop of the "test"
+ */
+ private void mainLoop() {
+ while (!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) && !Display.isCloseRequested()) {
+ if (Display.isVisible()) {
+ // check keyboard input
+ processKeyboard();
+ // do "game" logic, and render it
+ logic();
+ render();
+ } else {
+ // no need to render/paint if nothing has changed (ie. window
+ // dragged over)
+ if (Display.isDirty()) {
+ render();
+ }
+ // don't waste cpu time, sleep more
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException inte) {
+ }
+ }
+ // Update window
+ Display.update();
+ }
+ }
+ /**
+ * Performs the logic
+ */
+ private void logic() {
+ angle += angleRotation;
+ if (angle > 90.0f) {
+ angle = 0.0f;
+ }
+ quadPosition.x += quadVelocity.x;
+ quadPosition.y += quadVelocity.y;
+ //check colision with vertical border border
+ if (quadPosition.x + 50 >= mode.getWidth() || quadPosition.x - 50 <= 0) {
+ quadVelocity.x *= -1;
+ }
+ //check collision with horizontal border
+ if (quadPosition.y + 50 >= mode.getHeight() || quadPosition.y - 50 <= 0) {
+ quadVelocity.y *= -1;
+ }
+ }
+ private void render() {
+ //clear background
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ // draw white quad
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(quadPosition.x, quadPosition.y, 0);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glColor3f(1.0f, 1.0f, 1.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ {
+ GL11.glVertex2i(-50, -50);
+ GL11.glVertex2i(50, -50);
+ GL11.glVertex2i(50, 50);
+ GL11.glVertex2i(-50, 50);
+ }
+ GL11.glEnd();
+ }
+ GL11.glPopMatrix();
+ }
+ /**
+ * Processes keyboard input
+ */
+ private void processKeyboard() {
+ //check for fullscreen key
+ if (Keyboard.isKeyDown(Keyboard.KEY_F)) {
+ try {
+ switchMode();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ //check for window key
+ if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
+ try {
+ mode = new DisplayMode(640, 480);
+ Display.setDisplayModeAndFullscreen(mode);
+ glInit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ //check for speed changes
+ if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
+ quadVelocity.y += 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
+ quadVelocity.y -= 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
+ quadVelocity.x += 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
+ quadVelocity.x -= 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_ADD)) {
+ angleRotation += 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_SUBTRACT)) {
+ angleRotation -= 0.1f;
+ }
+ //throttle
+ if (quadVelocity.x < -MAX_SPEED) {
+ quadVelocity.x = -MAX_SPEED;
+ }
+ if (quadVelocity.x > MAX_SPEED) {
+ quadVelocity.x = MAX_SPEED;
+ }
+ if (quadVelocity.y < -MAX_SPEED) {
+ quadVelocity.y = -MAX_SPEED;
+ }
+ if (quadVelocity.y > MAX_SPEED) {
+ quadVelocity.y = MAX_SPEED;
+ }
+ if (angleRotation < 0.0f) {
+ angleRotation = 0.0f;
+ }
+ if (angleRotation > MAX_SPEED) {
+ angleRotation = MAX_SPEED;
+ }
+ }
+ /**
+ * Cleans up the test
+ */
+ private void cleanup() {
+ Display.destroy();
+ }
+
+ /**
+ * Retrieves a displaymode, if one such is available
+ *
+ * @param width
+ * Required width
+ * @param height
+ * Required height
+ * @param bpp
+ * Minimum required bits per pixel
+ * @return
+ */
+ 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) {
+ return modes[i];
+ }
+ }
+ return Display.getDesktopDisplayMode();
+ }
+ /**
+ * Initializes OGL
+ */
+ private void glInit() {
+ // Go into orthographic projection mode.
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluOrtho2D(0, mode.getWidth(), 0, mode.getHeight());
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, mode.getWidth(), mode.getHeight());
+ //set clear color to black
+ GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ //sync frame (only works on windows)
+ Display.setVSyncEnabled(true);
+ }
+ /**
+ * Test entry point
+ */
+ public static void main(String[] args) {
+ System.out.println("Change between fullscreen and windowed mode, by pressing F and W respectively");
+ System.out.println("Move quad using arrowkeys, and change rotation using +/-");
+ FullScreenWindowedTest fswTest = new FullScreenWindowedTest();
+ fswTest.execute();
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/Gears.java b/src/java/org/lwjgl/test/opengl/Gears.java
new file mode 100644
index 0000000..8ce8672
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/Gears.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+
+/*
+ * 3-D gear wheels. Originally by Brian Paul
+ */
+package org.lwjgl.test.opengl;
+
+import java.nio.FloatBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.ARBTransposeMatrix;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GLContext;
+
+/**
+ *
+ * This is the OpenGL "standard" Gears demo, originally by Brian Paul
+ *
+ * @author Brian Matzon
+ * @version $Revision: 3276 $
+ * $Id: Gears.java 3276 2010-02-21 21:18:17Z matzon $
+ */
+public class Gears {
+
+ private float view_rotx = 20.0f;
+
+ private float view_roty = 30.0f;
+
+ private float view_rotz = 0.0f;
+
+ private int gear1;
+
+ private int gear2;
+
+ private int gear3;
+
+ private float angle = 0.0f;
+
+ public static void main(String[] args) {
+ new Gears().execute();
+ System.exit(0);
+ }
+
+ /**
+ *
+ */
+ private void execute() {
+ try {
+ init();
+ } catch (LWJGLException le) {
+ le.printStackTrace();
+ System.out.println("Failed to initialize Gears.");
+ return;
+ }
+
+ loop();
+
+ destroy();
+ }
+
+ /**
+ *
+ */
+ private void destroy() {
+ Display.destroy();
+ }
+
+ /**
+ *
+ */
+ private void loop() {
+ long startTime = System.currentTimeMillis() + 5000;
+ long fps = 0;
+
+ while (!Display.isCloseRequested()) {
+ angle += 2.0f;
+
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+
+ GL11.glPushMatrix();
+ GL11.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
+ GL11.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
+ GL11.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(-3.0f, -2.0f, 0.0f);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear1);
+ GL11.glPopMatrix();
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(3.1f, -2.0f, 0.0f);
+ GL11.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear2);
+ GL11.glPopMatrix();
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(-3.1f, 4.2f, 0.0f);
+ GL11.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear3);
+ GL11.glPopMatrix();
+
+ GL11.glPopMatrix();
+
+ Display.update();
+ if (startTime > System.currentTimeMillis()) {
+ fps++;
+ } else {
+ long timeUsed = 5000 + (startTime - System.currentTimeMillis());
+ startTime = System.currentTimeMillis() + 5000;
+ System.out.println(fps + " frames in " + (float) (timeUsed / 1000f) + " seconds = "
+ + (fps / (timeUsed / 1000f)));
+ fps = 0;
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private void init() throws LWJGLException {
+ // create Window of size 300x300
+ Display.setLocation((Display.getDisplayMode().getWidth() - 300) / 2,
+ (Display.getDisplayMode().getHeight() - 300) / 2);
+ Display.setDisplayMode(new DisplayMode(300, 300));
+ Display.setTitle("Gears");
+ Display.create();
+
+ // setup ogl
+ FloatBuffer pos = BufferUtils.createFloatBuffer(4).put(new float[] { 5.0f, 5.0f, 10.0f, 0.0f});
+ FloatBuffer red = BufferUtils.createFloatBuffer(4).put(new float[] { 0.8f, 0.1f, 0.0f, 1.0f});
+ FloatBuffer green = BufferUtils.createFloatBuffer(4).put(new float[] { 0.0f, 0.8f, 0.2f, 1.0f});
+ FloatBuffer blue = BufferUtils.createFloatBuffer(4).put(new float[] { 0.2f, 0.2f, 1.0f, 1.0f});
+
+ pos.flip();
+ red.flip();
+ green.flip();
+ blue.flip();
+
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, pos);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_LIGHTING);
+ GL11.glEnable(GL11.GL_LIGHT0);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = GL11.glGenLists(1);
+ GL11.glNewList(gear1, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0f, 4.0f, 1.0f, 20, 0.7f);
+ GL11.glEndList();
+
+ gear2 = GL11.glGenLists(1);
+ GL11.glNewList(gear2, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5f, 2.0f, 2.0f, 10, 0.7f);
+ GL11.glEndList();
+
+ gear3 = GL11.glGenLists(1);
+ GL11.glNewList(gear3, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3f, 2.0f, 0.5f, 10, 0.7f);
+ GL11.glEndList();
+
+ GL11.glEnable(GL11.GL_NORMALIZE);
+
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+
+ System.err.println("GL_VENDOR: " + GL11.glGetString(GL11.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + GL11.glGetString(GL11.GL_RENDERER));
+ System.err.println("GL_VERSION: " + GL11.glGetString(GL11.GL_VERSION));
+ System.err.println();
+ System.err.println("glLoadTransposeMatrixfARB() supported: " + GLContext.getCapabilities().GL_ARB_transpose_matrix);
+ if (!GLContext.getCapabilities().GL_ARB_transpose_matrix) {
+ // --- not using extensions
+ GL11.glLoadIdentity();
+ } else {
+ // --- using extensions
+ final FloatBuffer identityTranspose = BufferUtils.createFloatBuffer(16).put(
+ new float[] { 1, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1});
+ identityTranspose.flip();
+ ARBTransposeMatrix.glLoadTransposeMatrixARB(identityTranspose);
+ }
+
+ float h = (float) 300 / (float) 300;
+ GL11.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glTranslatef(0.0f, 0.0f, -40.0f);
+ }
+
+ /**
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * @param inner_radius radius of hole at center
+ * @param outer_radius radius at center of teeth
+ * @param width width of gear
+ * @param teeth number of teeth
+ * @param tooth_depth depth of tooth
+ */
+ private void gear(float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) {
+ int i;
+ float r0, r1, r2;
+ float angle, da;
+ float u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0f;
+ r2 = outer_radius + tooth_depth / 2.0f;
+
+ da = 2.0f * (float) Math.PI / teeth / 4.0f;
+
+ GL11.glShadeModel(GL11.GL_FLAT);
+
+ GL11.glNormal3f(0.0f, 0.0f, 1.0f);
+
+ /* draw front face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ if (i < teeth) {
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da),
+ width * 0.5f);
+ }
+ }
+ GL11.glEnd();
+
+ /* draw front sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw outward faces of teeth */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle);
+ v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle);
+ len = (float) Math.sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da);
+ v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da);
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ }
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f);
+ GL11.glEnd();
+
+ GL11.glShadeModel(GL11.GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ }
+ GL11.glEnd();
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/PbufferTest.java b/src/java/org/lwjgl/test/opengl/PbufferTest.java
new file mode 100644
index 0000000..eac8e8c
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/PbufferTest.java
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.Pbuffer;
+import org.lwjgl.opengl.PixelFormat;
+import org.lwjgl.util.glu.GLU;
+import org.lwjgl.util.vector.Vector2f;
+
+/**
+ *
+ * Tests Pbuffers
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: PbufferTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class PbufferTest {
+
+ /** Intended deiplay mode */
+ private DisplayMode mode;
+
+ /** our quad moving around */
+ private Vector2f quadPosition;
+
+ /** our quadVelocity */
+ private Vector2f quadVelocity;
+
+ /** angle of quad */
+ private float angle;
+
+ /** degrees to rotate per frame */
+ private float angleRotation = 1.0f;
+
+ /** Max speed of all changable attributes */
+ private static final float MAX_SPEED = 20.0f;
+
+ /** Pbuffer instance */
+ private static Pbuffer pbuffer;
+
+ /** The shared texture */
+ private static int tex_handle;
+
+ /**
+ * Executes the test
+ */
+ public void execute() {
+ initialize();
+
+ mainLoop();
+
+ cleanup();
+ }
+
+ /**
+ * Initializes the test
+ */
+ private void initialize() {
+ try {
+ //find displaymode
+ pbuffer = new Pbuffer(512, 512, new PixelFormat(), null, null);
+ mode = findDisplayMode(800, 600, 16);
+ Display.setDisplayMode(mode);
+ // start of in windowed mode
+ Display.create();
+// gl = new GLWindow("Test", 50, 50, mode.width, mode.height, mode.bpp, 0, 0, 0);
+ if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
+ System.out.println("No Pbuffer support!");
+ System.exit(1);
+ }
+ System.out.println("Pbuffer support detected");
+
+ glInit();
+ initPbuffer();
+
+ Keyboard.create();
+
+ quadPosition = new Vector2f(100f, 100f);
+ quadVelocity = new Vector2f(1.0f, 1.0f);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Runs the main loop of the "test"
+ */
+ private void mainLoop() {
+ while (!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) && !Display.isCloseRequested()) {
+ if (Display.isVisible()) {
+ // check keyboard input
+ processKeyboard();
+ // do "game" logic, and render it
+ logic();
+ render();
+ } else {
+ // no need to render/paint if nothing has changed (ie. window
+ // dragged over)
+ if (Display.isDirty()) {
+ render();
+ }
+ // don't waste cpu time, sleep more
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException inte) {
+ }
+ }
+ // Update window
+ Display.update();
+ }
+ }
+
+ /**
+ * Performs the logic
+ */
+ private void logic() {
+ angle += angleRotation;
+ if (angle > 90.0f) {
+ angle = 0.0f;
+ }
+
+ quadPosition.x += quadVelocity.x;
+ quadPosition.y += quadVelocity.y;
+
+ //check colision with vertical border border
+ if (quadPosition.x + 50 >= mode.getWidth() || quadPosition.x - 50 <= 0) {
+ quadVelocity.x *= -1;
+ }
+
+ //check collision with horizontal border
+ if (quadPosition.y + 50 >= mode.getHeight() || quadPosition.y - 50 <= 0) {
+ quadVelocity.y *= -1;
+ }
+ }
+
+ private void render() {
+ if (pbuffer.isBufferLost()) {
+ System.out.println("Buffer contents lost - will recreate the buffer");
+ pbuffer.destroy();
+ try {
+ pbuffer = new Pbuffer(512, 512, new PixelFormat(), null, null);
+ initPbuffer();
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ }
+ }
+ try {
+ pbuffer.makeCurrent();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+ // Pbuffer rendering
+ //clear background
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+
+ // draw white quad
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(quadPosition.x, quadPosition.y, 0);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glColor3f(1.0f, 1.0f, 1.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ {
+ GL11.glVertex2i(-50, -50);
+ GL11.glVertex2i(50, -50);
+ GL11.glVertex2i(50, 50);
+ GL11.glVertex2i(-50, 50);
+ }
+ GL11.glEnd();
+ }
+ GL11.glPopMatrix();
+ GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, 0, 0, 512, 512, 0);
+ try {
+ Display.makeCurrent();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+
+ // OpenGL window rendering
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ // draw white quad
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(quadPosition.x, quadPosition.y, 0);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glColor3f(1.0f, 1.0f, 0.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ {
+ GL11.glTexCoord2f(0f, 0f);
+ GL11.glVertex2i(-50, -50);
+ GL11.glTexCoord2f(1f, 0f);
+ GL11.glVertex2i(50, -50);
+ GL11.glTexCoord2f(1f, 1f);
+ GL11.glVertex2i(50, 50);
+ GL11.glTexCoord2f(0f, 1f);
+ GL11.glVertex2i(-50, 50);
+ }
+ GL11.glEnd();
+ }
+ GL11.glPopMatrix();
+ }
+
+ private void initPbuffer() {
+ try {
+ pbuffer.makeCurrent();
+ initGLState(256, 256, 0.5f);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex_handle);
+ Display.makeCurrent();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Processes keyboard input
+ */
+ private void processKeyboard() {
+ Keyboard.poll();
+
+ //check for fullscreen key
+ if (Keyboard.isKeyDown(Keyboard.KEY_F)) {
+
+ try {
+ Display.setDisplayMode(mode);
+ Display.setFullscreen(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //check for window key
+ if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
+ try {
+ Display.setFullscreen(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //check for speed changes
+ if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
+ quadVelocity.y += 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
+ quadVelocity.y -= 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
+ quadVelocity.x += 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
+ quadVelocity.x -= 0.1f;
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_ADD)) {
+ angleRotation += 0.1f;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_SUBTRACT)) {
+ angleRotation -= 0.1f;
+ }
+
+ //throttle
+ if (quadVelocity.x < -MAX_SPEED) {
+ quadVelocity.x = -MAX_SPEED;
+ }
+ if (quadVelocity.x > MAX_SPEED) {
+ quadVelocity.x = MAX_SPEED;
+ }
+ if (quadVelocity.y < -MAX_SPEED) {
+ quadVelocity.y = -MAX_SPEED;
+ }
+ if (quadVelocity.y > MAX_SPEED) {
+ quadVelocity.y = MAX_SPEED;
+ }
+
+ if (angleRotation < 0.0f) {
+ angleRotation = 0.0f;
+ }
+ if (angleRotation > MAX_SPEED) {
+ angleRotation = MAX_SPEED;
+ }
+ }
+
+ private void destroyTexture() {
+ IntBuffer buffer = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
+ buffer.put(0, tex_handle);
+ GL11.glDeleteTextures(buffer);
+ }
+
+ /**
+ * Cleans up the test
+ */
+ private void cleanup() {
+ destroyTexture();
+ pbuffer.destroy();
+ Display.destroy();
+ }
+
+ /**
+ * Retrieves a displaymode, if one such is available
+ *
+ * @param width Required width
+ * @param height Required height
+ * @param bpp Minimum required bits per pixel
+ * @return
+ */
+ 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) {
+ return modes[i];
+ }
+ }
+ return null;
+ }
+
+ private void initGLState(int width, int height, float color) {
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluOrtho2D(0, mode.getWidth(), 0, mode.getHeight());
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, width, height);
+
+ //set clear color to black
+ GL11.glClearColor(color, color, color, 0.0f);
+ }
+
+ /**
+ * Initializes OGL
+ */
+ private void glInit() {
+ //sync frame (only works on windows)
+ Display.setVSyncEnabled(true);
+
+ GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);
+ GL11.glEnable(GL11.GL_TEXTURE_2D);
+ // Create shared texture
+ IntBuffer buffer = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
+ GL11.glGenTextures(buffer);
+ tex_handle = buffer.get(0);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex_handle);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
+ initGLState(mode.getWidth(), mode.getHeight(), 0f);
+ }
+
+ /**
+ * Test entry point
+ */
+ public static void main(String[] args) {
+ System.out.println(
+ "Change between fullscreen and windowed mode, by pressing F and W respectively");
+ System.out.println("Move quad using arrowkeys, and change rotation using +/-");
+ PbufferTest fswTest = new PbufferTest();
+ fswTest.execute();
+ System.exit(0);
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/SyncTest.java b/src/java/org/lwjgl/test/opengl/SyncTest.java
new file mode 100644
index 0000000..cc8cd87
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/SyncTest.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.Sys;
+import org.lwjgl.opengl.*;
+
+import java.util.Random;
+
+/** @author spasi */
+public final class SyncTest {
+
+ private SyncTest() {
+ }
+
+ public static void main(String[] args) {
+ runTest(args);
+ cleanup();
+ System.exit(0);
+ }
+
+ private static void runTest(String[] args) {
+ if ( args.length < 2 )
+ argsError("Insufficient number of arguments.");
+
+ int clears = 1;
+ int timeout = 0;
+
+ try {
+ clears = Integer.parseInt(args[0]);
+ timeout = Integer.parseInt(args[1]);
+ } catch (NumberFormatException e) {
+ argsError("Invalid number format.");
+ }
+
+ ContextAttribs ca = new ContextAttribs();
+
+ try {
+ DisplayMode[] modes = Display.getAvailableDisplayModes();
+
+ 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), ca);
+ } catch (LWJGLException e) {
+ kill(e.getMessage());
+ }
+
+ System.out.println("\n---------\n");
+
+ final String version = GL11.glGetString(GL11.GL_VERSION);
+
+ System.out.println("GL Version: " + version);
+ System.out.println("ARB_sync: " + GLContext.getCapabilities().GL_ARB_sync);
+
+ if ( !GLContext.getCapabilities().OpenGL32 && !GLContext.getCapabilities().GL_ARB_sync )
+ kill("OpenGL3.2 or ARB_sync support is required for this test.");
+
+ System.out.println("\n---------\n");
+
+ System.out.println("Clearing the framebuffer a gazillion times...");
+
+ Random rand = new Random(System.currentTimeMillis());
+ for ( int i = 0; i < clears; i++ ) {
+ GL11.glClearColor(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), 1.0f);
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ }
+
+ GLSync sync = GL32.glFenceSync(GL32.GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ System.out.println("\nWaiting on fence...");
+ long time = Sys.getTime();
+ int status = GL32.glClientWaitSync(sync, 0, timeout < 0 ? GL32.GL_TIMEOUT_IGNORED : timeout * 1000 * 1000);
+ System.out.println("\nFence sync complete after: " + ((Sys.getTime() - time) / (double)Sys.getTimerResolution()) + " seconds.");
+ System.out.print("\nWait Status: ");
+ switch ( status ) {
+ case GL32.GL_ALREADY_SIGNALED:
+ System.out.println("ALREADY_SIGNALED");
+ break;
+ case GL32.GL_CONDITION_SATISFIED:
+ System.out.println("CONDITION_SATISFIED");
+ break;
+ case GL32.GL_TIMEOUT_EXPIRED:
+ System.out.println("TIMEOUT_EXPIRED");
+ break;
+ case GL32.GL_WAIT_FAILED:
+ System.out.println("WAIT_FAILED");
+ break;
+ default:
+ System.out.println("Unexpected wait status: 0x" + Integer.toHexString(status));
+ }
+
+ System.out.println("Sync Status: " + (GL32.glGetSync(sync, GL32.GL_SYNC_STATUS) == GL32.GL_UNSIGNALED ? "UNSIGNALED" : "SIGNALED"));
+
+ GL32.glDeleteSync(sync);
+
+ int error = GL11.glGetError();
+ if ( error != 0 )
+ System.out.println("\nTest failed with OpenGL error: " + error);
+ else
+ System.out.println("\nTest completed successfully.");
+ }
+
+ private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) {
+ DisplayMode bestMode = null;
+
+ for ( int i = 0; i < modes.length; i++ ) {
+ DisplayMode mode = modes[i];
+ if ( mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85 ) {
+ if ( bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) )
+ bestMode = mode;
+ }
+ }
+
+ return bestMode;
+ }
+
+ private static void cleanup() {
+ if ( Display.isCreated() )
+ Display.destroy();
+ }
+
+ private static void argsError(final String msg) {
+ System.out.println("\nInvalid arguments error: " + msg);
+ System.out.println("\nUsage: SyncTest :\n");
+ System.out.println("clears\t- Number of times to clear the framebuffer.");
+ System.out.println("timeout\t- WaitSync timeout in milliseconds.");
+
+ cleanup();
+ System.exit(-1);
+ }
+
+ static void kill(String reason) {
+ System.out.println("The SyncTest program was terminated because an error occured.\n");
+ System.out.println("Reason: " + (reason == null ? "Unknown" : reason));
+
+ cleanup();
+ System.exit(-1);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/VBOIndexTest.java b/src/java/org/lwjgl/test/opengl/VBOIndexTest.java
new file mode 100644
index 0000000..21e68cd
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/VBOIndexTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2002-2008 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: VBOIndexTest.java 2983 2008-04-07 18:36:09Z matzon $
+ *
+ * Simple java test program.
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ */
+
+package org.lwjgl.test.opengl;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.ARBBufferObject;
+import org.lwjgl.opengl.ARBVertexBufferObject;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GLContext;
+import org.lwjgl.util.glu.GLU;
+
+public final class VBOIndexTest {
+
+ static {
+ try {
+ //find first display mode that allows us 640*480*16
+ int mode = -1;
+ DisplayMode[] modes = Display.getAvailableDisplayModes();
+ for ( int i = 0; i < modes.length; i++ ) {
+ if ( modes[i].getWidth() == 640
+ && modes[i].getHeight() == 480
+ && modes[i].getBitsPerPixel() >= 16 ) {
+ mode = i;
+ break;
+ }
+ }
+ if ( mode != -1 ) {
+ //select above found displaymode
+ System.out.println("Setting display mode to " + modes[mode]);
+ Display.setDisplayMode(modes[mode]);
+ System.out.println("Created display.");
+ }
+ } catch (Exception e) {
+ System.err.println("Failed to create display due to " + e);
+ }
+ }
+
+ static {
+ try {
+ Display.create();
+ System.out.println("Created OpenGL.");
+ } catch (Exception e) {
+ System.err.println("Failed to create OpenGL due to " + e);
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Is the game finished?
+ */
+ private static boolean finished;
+
+ /**
+ * A rotating square!
+ */
+ private static float angle;
+ private static int buffer_id;
+ private static int indices_buffer_id;
+ private static FloatBuffer vertices;
+ private static ByteBuffer mapped_buffer = null;
+ private static FloatBuffer mapped_float_buffer = null;
+ private static IntBuffer indices;
+ private static ByteBuffer mapped_indices_buffer = null;
+ private static IntBuffer mapped_indices_int_buffer = null;
+
+ public static void main(String[] arguments) {
+ try {
+ init();
+ while ( !finished ) {
+ Display.update();
+
+ if ( !Display.isVisible() )
+ Thread.sleep(200);
+ else if ( Display.isCloseRequested() )
+ System.exit(0);
+
+ mainLoop();
+ render();
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ cleanup();
+ }
+ System.exit(0);
+ }
+
+ /**
+ * All calculations are done in here
+ */
+ private static void mainLoop() {
+ angle += 1f;
+ if ( angle > 360.0f )
+ angle = 0.0f;
+
+ if ( Mouse.getDX() != 0 || Mouse.getDY() != 0 || Mouse.getDWheel() != 0 )
+ System.out.println("Mouse moved " + Mouse.getDX() + " " + Mouse.getDY() + " " + Mouse.getDWheel());
+ for ( int i = 0; i < Mouse.getButtonCount(); i++ )
+ if ( Mouse.isButtonDown(i) )
+ System.out.println("Button " + i + " down");
+ if ( Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) )
+ finished = true;
+ for ( int i = 0; i < Keyboard.getNumKeyboardEvents(); i++ ) {
+ Keyboard.next();
+ if ( Keyboard.getEventKey() == Keyboard.KEY_ESCAPE && Keyboard.getEventKeyState() )
+ finished = true;
+ if ( Keyboard.getEventKey() == Keyboard.KEY_T && Keyboard.getEventKeyState() )
+ System.out.println("Current time: " + Sys.getTime());
+ }
+ }
+
+ /**
+ * All rendering is done in here
+ */
+ private static void render() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ GL11.glPushMatrix();
+ GL11.glTranslatef(Display.getDisplayMode().getWidth() / 2, Display.getDisplayMode().getHeight() / 2, 0.0f);
+ GL11.glRotatef(angle, 0, 0, 1.0f);
+
+
+ ByteBuffer new_mapped_buffer = ARBBufferObject.glMapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,
+ ARBBufferObject.GL_WRITE_ONLY_ARB,
+ mapped_buffer);
+ if ( new_mapped_buffer != mapped_buffer )
+ mapped_float_buffer = new_mapped_buffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mapped_buffer = new_mapped_buffer;
+
+ new_mapped_buffer = ARBBufferObject.glMapBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ARBBufferObject.GL_WRITE_ONLY_ARB,
+ mapped_indices_buffer);
+ if ( new_mapped_buffer != mapped_indices_buffer )
+ mapped_indices_int_buffer = new_mapped_buffer.order(ByteOrder.nativeOrder()).asIntBuffer();
+
+ mapped_float_buffer.rewind();
+ vertices.rewind();
+ mapped_float_buffer.put(vertices);
+
+ mapped_indices_int_buffer.rewind();
+ indices.rewind();
+ mapped_indices_int_buffer.put(indices);
+ if ( ARBBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB) &&
+ ARBBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB) ) {
+ GL11.glDrawElements(GL11.GL_QUADS, 4, GL11.GL_UNSIGNED_INT, 0);
+ }
+ GL11.glPopMatrix();
+ }
+
+ /**
+ * Initialize
+ */
+ private static void init() throws Exception {
+
+ System.out.println("Timer resolution: " + Sys.getTimerResolution());
+ // Go into orthographic projection mode.
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluOrtho2D(0, Display.getDisplayMode().getWidth(), 0, Display.getDisplayMode().getHeight());
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
+ if ( !GLContext.getCapabilities().GL_ARB_vertex_buffer_object ) {
+ System.out.println("ARB VBO not supported!");
+ System.exit(1);
+ }
+ IntBuffer int_buffer = ByteBuffer.allocateDirect(8).order(ByteOrder.nativeOrder()).asIntBuffer();
+ ARBBufferObject.glGenBuffersARB(int_buffer);
+ buffer_id = int_buffer.get(0);
+ indices_buffer_id = int_buffer.get(1);
+ ARBBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer_id);
+ ARBBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, indices_buffer_id);
+ vertices = ByteBuffer.allocateDirect(2 * 4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ vertices.put(-50).put(-50).put(50).put(-50).put(50).put(50).put(-50).put(50);
+ vertices.rewind();
+ indices = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asIntBuffer();
+ indices.put(0).put(1).put(2).put(3);
+ indices.rewind();
+ ARBBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, 2 * 4 * 4, ARBBufferObject.GL_STREAM_DRAW_ARB);
+ ARBBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, 4 * 4, ARBBufferObject.GL_STREAM_DRAW_ARB);
+ GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
+ GL11.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
+ }
+
+ /**
+ * Cleanup
+ */
+ private static void cleanup() {
+ IntBuffer int_buffer = ByteBuffer.allocateDirect(8).order(ByteOrder.nativeOrder()).asIntBuffer();
+ int_buffer.put(0, buffer_id);
+ int_buffer.put(1, indices_buffer_id);
+ ARBBufferObject.glDeleteBuffersARB(int_buffer);
+ Display.destroy();
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/VBOTest.java b/src/java/org/lwjgl/test/opengl/VBOTest.java
new file mode 100644
index 0000000..7bdf9ea
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/VBOTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2002-2008 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: VBOTest.java 3287 2010-03-14 23:24:40Z spasi $
+ *
+ * Simple java test program.
+ *
+ * @author elias_naur
+ * @version $Revision: 3287 $
+ */
+
+package org.lwjgl.test.opengl;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.ARBBufferObject;
+import org.lwjgl.opengl.ARBVertexBufferObject;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GLContext;
+import org.lwjgl.util.glu.GLU;
+
+public final class VBOTest {
+
+ static {
+ try {
+ //find first display mode that allows us 640*480*16
+ int mode = -1;
+ DisplayMode[] modes = Display.getAvailableDisplayModes();
+ for ( int i = 0; i < modes.length; i++ ) {
+ if ( modes[i].getWidth() == 640
+ && modes[i].getHeight() == 480
+ && modes[i].getBitsPerPixel() >= 16 ) {
+ mode = i;
+ break;
+ }
+ }
+ if ( mode != -1 ) {
+ //select above found displaymode
+ System.out.println("Setting display mode to " + modes[mode]);
+ Display.setDisplayMode(modes[mode]);
+ System.out.println("Created display.");
+ }
+ } catch (Exception e) {
+ System.err.println("Failed to create display due to " + e);
+ }
+ }
+
+ static {
+ try {
+ Display.create();
+ System.out.println("Created OpenGL.");
+ } catch (Exception e) {
+ System.err.println("Failed to create OpenGL due to " + e);
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Is the game finished?
+ */
+ private static boolean finished;
+
+ /**
+ * A rotating square!
+ */
+ private static float angle;
+ private static int buffer_id;
+ private static FloatBuffer vertices;
+ private static ByteBuffer mapped_buffer = null;
+ private static FloatBuffer mapped_float_buffer = null;
+
+ public static void main(String[] arguments) {
+ try {
+ init();
+ while ( !finished ) {
+ Display.update();
+
+ if ( !Display.isVisible() )
+ Thread.sleep(200);
+ else if ( Display.isCloseRequested() )
+ System.exit(0);
+
+ mainLoop();
+ render();
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ cleanup();
+ }
+ System.exit(0);
+ }
+
+ /**
+ * All calculations are done in here
+ */
+ private static void mainLoop() {
+ angle += 1f;
+ if ( angle > 360.0f )
+ angle = 0.0f;
+
+ if ( Mouse.getDX() != 0 || Mouse.getDY() != 0 || Mouse.getDWheel() != 0 )
+ System.out.println("Mouse moved " + Mouse.getDX() + " " + Mouse.getDY() + " " + Mouse.getDWheel());
+ for ( int i = 0; i < Mouse.getButtonCount(); i++ )
+ if ( Mouse.isButtonDown(i) )
+ System.out.println("Button " + i + " down");
+ if ( Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) )
+ finished = true;
+ for ( int i = 0; i < Keyboard.getNumKeyboardEvents(); i++ ) {
+ Keyboard.next();
+ if ( Keyboard.getEventKey() == Keyboard.KEY_ESCAPE && Keyboard.getEventKeyState() )
+ finished = true;
+ if ( Keyboard.getEventKey() == Keyboard.KEY_T && Keyboard.getEventKeyState() )
+ System.out.println("Current time: " + Sys.getTime());
+ }
+ }
+
+ /**
+ * All rendering is done in here
+ */
+ private static void render() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ GL11.glPushMatrix();
+ GL11.glTranslatef(Display.getDisplayMode().getWidth() / 2, Display.getDisplayMode().getHeight() / 2, 0.0f);
+ GL11.glRotatef(angle, 0, 0, 1.0f);
+ ByteBuffer new_mapped_buffer = ARBBufferObject.glMapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,
+ ARBBufferObject.GL_WRITE_ONLY_ARB,
+ mapped_buffer);
+ if ( new_mapped_buffer != mapped_buffer )
+ mapped_float_buffer = new_mapped_buffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mapped_buffer = new_mapped_buffer;
+ mapped_float_buffer.rewind();
+ vertices.rewind();
+ mapped_float_buffer.put(vertices);
+ if ( ARBBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB) )
+ GL11.glDrawArrays(GL11.GL_QUADS, 0, 4);
+ GL11.glPopMatrix();
+ }
+
+ /**
+ * Initialize
+ */
+ private static void init() throws Exception {
+ System.out.println("Timer resolution: " + Sys.getTimerResolution());
+ // Go into orthographic projection mode.
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluOrtho2D(0, Display.getDisplayMode().getWidth(), 0, Display.getDisplayMode().getHeight());
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
+ if ( !GLContext.getCapabilities().GL_ARB_vertex_buffer_object ) {
+ System.out.println("ARB VBO not supported!");
+ System.exit(1);
+ }
+ buffer_id = ARBBufferObject.glGenBuffersARB();
+ ARBBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer_id);
+ vertices = ByteBuffer.allocateDirect(2 * 4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ vertices.put(-50).put(-50).put(50).put(-50).put(50).put(50).put(-50).put(50);
+ ARBBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, 2 * 4 * 4, ARBBufferObject.GL_STREAM_DRAW_ARB);
+ GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
+ GL11.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
+ }
+
+ /**
+ * Cleanup
+ */
+ private static void cleanup() {
+ ARBBufferObject.glDeleteBuffersARB(buffer_id);
+ Display.destroy();
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/VersionTest.java b/src/java/org/lwjgl/test/opengl/VersionTest.java
new file mode 100644
index 0000000..f85ea07
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/VersionTest.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+/*
+ * Created by LWJGL.
+ * User: spasi
+ * Date: 2009-04-04
+ * Time: 21:20:24 pm
+ */
+
+package org.lwjgl.test.opengl;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.*;
+
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+
+public final class VersionTest {
+
+ private VersionTest() {
+ }
+
+ public static void main(String[] args) {
+ initialize(args);
+ cleanup();
+ System.exit(0);
+ }
+
+ private static void initialize(String[] args) {
+ if ( args.length < 2 )
+ argsError("Insufficient number of arguments");
+
+ int majorInput = 1;
+ int minorInput = 0;
+
+ try {
+ majorInput = Integer.parseInt(args[0]);
+ minorInput = Integer.parseInt(args[1]);
+ } catch (NumberFormatException e) {
+ argsError("Invalid number format");
+ }
+
+ ContextAttribs ca = new ContextAttribs(majorInput, minorInput);
+
+ if ( 2 < args.length ) {
+ for ( int i = 2; i < args.length; i++ ) {
+ if ( Pattern.matches("[0-9]+", args[i]) )
+ ca = ca.withLayer(Integer.parseInt(args[i]));
+ else if ( "debug".equalsIgnoreCase(args[i]) )
+ ca = ca.withDebug(true);
+ else if ( "fc".equalsIgnoreCase(args[i]) )
+ ca = ca.withForwardCompatible(true);
+ else if ( "core".equalsIgnoreCase(args[i]) )
+ ca = ca.withProfileCore(true);
+ else if ( "compatibility".equalsIgnoreCase(args[i]) )
+ ca = ca.withProfileCompatibility(true);
+ else
+ argsError("Unknown argument: \'" + args[i] + "\'");
+ }
+ }
+
+ 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), ca);
+ } catch (LWJGLException e) {
+ kill(e.getMessage());
+ }
+
+ System.out.println("\n---------\n");
+
+ final String version = GL11.glGetString(GL11.GL_VERSION);
+
+ System.out.print("GL Version requested: " + majorInput + '.' + minorInput);
+ if ( ca.isProfileCore() )
+ System.out.print(" - Core Profile");
+ else if ( ca.isProfileCompatibility() )
+ System.out.print(" - Compatibility Profile");
+ System.out.println("\nGL Version returned : " + version);
+
+ final StringTokenizer version_tokenizer = new StringTokenizer(version, ". ");
+
+ int majorVersion = Integer.parseInt(version_tokenizer.nextToken());
+ int minorVersion = Integer.parseInt(version_tokenizer.nextToken());
+
+ if ( majorVersion != majorInput || minorVersion != minorInput ) {
+ if ( majorInput == 1 && minorInput == 0 )
+ System.out.println("\tThe maximum supported version has been returned. The driver is well-behaved. :)");
+ else if ( majorInput < 3 && majorVersion < 3 )
+ System.out.println("\tThe maximum supported version pre-3.0 has been returned. The driver is well-behaved. :)");
+ else
+ System.out.println("\tThe requested version was not returned. The driver is buggy! :(");
+ } else
+ System.out.println("\tThe requested version was returned. :)");
+
+ if ( ca.isProfileCompatibility() && !GLContext.getCapabilities().GL_ARB_compatibility )
+ System.out.println("\tThe driver does not support the Compatibility Profile.");
+
+ System.out.println("\n---------\n");
+
+ System.out.println("Debug mode: " + ca.isDebug());
+ System.out.println("Forward compatible mode: " + ca.isForwardCompatible());
+ System.out.println("ARB_compatibility: " + GLContext.getCapabilities().GL_ARB_compatibility);
+ try {
+ GL11.glVertex3f(0.0f, 0.0f, 0.0f);
+ System.out.println("Deprecated functionality present: " + true);
+ } catch (Throwable t) {
+ System.out.println("Deprecated functionality present: " + false);
+ if ( GLContext.getCapabilities().GL_ARB_compatibility ) {
+ System.out.println("\tARB_compatibility is present, but LWJGL has enabled pseudo-forward compatible mode.");
+ }
+ }
+ }
+
+ private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) {
+ DisplayMode bestMode = null;
+
+ for ( int i = 0; i < modes.length; i++ ) {
+ DisplayMode mode = modes[i];
+ if ( mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85 ) {
+ if ( bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) )
+ bestMode = mode;
+ }
+ }
+
+ return bestMode;
+ }
+
+ private static void cleanup() {
+ if ( Display.isCreated() )
+ Display.destroy();
+ }
+
+ private static void argsError(final String msg) {
+ System.out.println("\nInvalid arguments error: " + msg);
+ System.out.println("\nUsage: VersionTest {, 'debug', 'fc'}:\n");
+ System.out.println("majorVersion\t- Major OpenGL version.");
+ System.out.println("majorVersion\t- Minor OpenGL version.");
+ System.out.println("layer\t- Layer plane (optional).");
+ System.out.println("debug\t- Enables debug mode (optional).");
+ System.out.println("fc\t- Enables forward compatibility mode (optional).");
+
+ cleanup();
+ System.exit(-1);
+ }
+
+ static void kill(String reason) {
+ System.out.println("The VersionTest program was terminated because an error occured.\n");
+ System.out.println("Reason: " + (reason == null ? "Unknown" : reason));
+
+ cleanup();
+ System.exit(-1);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/awt/AWTGears.java b/src/java/org/lwjgl/test/opengl/awt/AWTGears.java
new file mode 100644
index 0000000..8c7fd62
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/awt/AWTGears.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.awt;
+
+import java.awt.Frame;
+import java.awt.Color;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.nio.FloatBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.ARBTransposeMatrix;
+import org.lwjgl.opengl.AWTGLCanvas;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GLContext;
+
+/**
+ *
+ * AWT version of the gears demo
+ *
+ * @version $Revision$
+ * @author Brian Matzon
+ * $Id$
+ */
+public class AWTGears extends Frame {
+
+ /** AWT GL canvas */
+ private AWTGLCanvas canvas0;
+
+ private float view_rotx = 20.0f;
+
+ private float view_roty = 30.0f;
+
+ private float view_rotz = 0.0f;
+
+ private int gear1;
+
+ private int gear2;
+
+ private int gear3;
+
+ private float angle = 0.0f;
+
+ /**
+ * C'tor
+ */
+ public AWTGears() throws LWJGLException {
+ setTitle("Gears");
+ setBackground(Color.BLACK);
+ AWTGearsCanvas canvas = new AWTGearsCanvas();
+ canvas.setSize(300, 300);
+ add(canvas);
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ dispose();
+ System.exit(0);
+ }
+ });
+ setResizable(true);
+ pack();
+ setVisible(true);
+ }
+
+ private void setup() {
+ // setup ogl
+ FloatBuffer pos = BufferUtils.createFloatBuffer(4).put(new float[] { 5.0f, 5.0f, 10.0f, 0.0f});
+ FloatBuffer red = BufferUtils.createFloatBuffer(4).put(new float[] { 0.8f, 0.1f, 0.0f, 1.0f});
+ FloatBuffer green = BufferUtils.createFloatBuffer(4).put(new float[] { 0.0f, 0.8f, 0.2f, 1.0f});
+ FloatBuffer blue = BufferUtils.createFloatBuffer(4).put(new float[] { 0.2f, 0.2f, 1.0f, 1.0f});
+ pos.flip();
+ red.flip();
+ green.flip();
+ blue.flip();
+
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, pos);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_LIGHTING);
+ GL11.glEnable(GL11.GL_LIGHT0);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = GL11.glGenLists(1);
+ GL11.glNewList(gear1, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0f, 4.0f, 1.0f, 20, 0.7f);
+ GL11.glEndList();
+
+ gear2 = GL11.glGenLists(1);
+ GL11.glNewList(gear2, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5f, 2.0f, 2.0f, 10, 0.7f);
+ GL11.glEndList();
+
+ gear3 = GL11.glGenLists(1);
+ GL11.glNewList(gear3, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3f, 2.0f, 0.5f, 10, 0.7f);
+ GL11.glEndList();
+
+ GL11.glEnable(GL11.GL_NORMALIZE);
+
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+
+ System.err.println("GL_VENDOR: " + GL11.glGetString(GL11.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + GL11.glGetString(GL11.GL_RENDERER));
+ System.err.println("GL_VERSION: " + GL11.glGetString(GL11.GL_VERSION));
+ System.err.println();
+ System.err.println("glLoadTransposeMatrixfARB() supported: " + GLContext.getCapabilities().GL_ARB_transpose_matrix);
+ if (!GLContext.getCapabilities().GL_ARB_transpose_matrix) {
+ // --- not using extensions
+ GL11.glLoadIdentity();
+ } else {
+ // --- using extensions
+ final FloatBuffer identityTranspose = BufferUtils.createFloatBuffer(16).put(
+ new float[] { 1, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1});
+ identityTranspose.flip();
+ ARBTransposeMatrix.glLoadTransposeMatrixARB(identityTranspose);
+ }
+
+ float h = (float) 300 / (float) 300;
+ GL11.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glTranslatef(0.0f, 0.0f, -40.0f);
+ }
+
+ /**
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * @param inner_radius radius of hole at center
+ * @param outer_radius radius at center of teeth
+ * @param width width of gear
+ * @param teeth number of teeth
+ * @param tooth_depth depth of tooth
+ */
+ private void gear(float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) {
+ int i;
+ float r0, r1, r2;
+ float angle, da;
+ float u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0f;
+ r2 = outer_radius + tooth_depth / 2.0f;
+
+ da = 2.0f * (float) Math.PI / teeth / 4.0f;
+
+ GL11.glShadeModel(GL11.GL_FLAT);
+
+ GL11.glNormal3f(0.0f, 0.0f, 1.0f);
+
+ /* draw front face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ if (i < teeth) {
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da),
+ width * 0.5f);
+ }
+ }
+ GL11.glEnd();
+
+ /* draw front sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw outward faces of teeth */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle);
+ v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle);
+ len = (float) Math.sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da);
+ v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da);
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ }
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f);
+ GL11.glEnd();
+
+ GL11.glShadeModel(GL11.GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ }
+ GL11.glEnd();
+ }
+
+ public static void main(String[] args) throws LWJGLException {
+ new AWTGears();
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/awt/AWTGearsCanvas.java b/src/java/org/lwjgl/test/opengl/awt/AWTGearsCanvas.java
new file mode 100644
index 0000000..c6dbb9a
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/awt/AWTGearsCanvas.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.awt;
+
+import java.nio.FloatBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.ARBTransposeMatrix;
+import org.lwjgl.opengl.AWTGLCanvas;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GLContext;
+import org.lwjgl.test.applet.Test;
+
+/**
+ *
+ * AWT version of the gears demo
+ *
+ * @version $Revision$
+ * @author Brian Matzon
+ * $Id$
+ */
+public class AWTGearsCanvas extends AWTGLCanvas implements Test {
+
+ private float view_rotx = 20.0f;
+
+ private float view_roty = 30.0f;
+
+ private float view_rotz = 0.0f;
+
+ private int gear1;
+
+ private int gear2;
+
+ private int gear3;
+
+ private float angle = 0.0f;
+
+ long startTime = 0;
+ long fps = 0;
+ int current_width;
+ int current_height;
+
+ /**
+ * C'tor
+ */
+ public AWTGearsCanvas() throws LWJGLException {
+ super();
+ }
+
+ public void paintGL() {
+
+ if(startTime == 0) {
+ setup();
+ startTime = System.currentTimeMillis() + 5000;
+ }
+
+ try {
+ angle += 2.0f;
+ if (getWidth() != current_width || getHeight() != current_height) {
+ current_width = getWidth();
+ current_height = getHeight();
+ GL11.glViewport(0, 0, current_width, current_height);
+ }
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+
+ GL11.glPushMatrix();
+ GL11.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
+ GL11.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
+ GL11.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(-3.0f, -2.0f, 0.0f);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear1);
+ GL11.glPopMatrix();
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(3.1f, -2.0f, 0.0f);
+ GL11.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear2);
+ GL11.glPopMatrix();
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(-3.1f, 4.2f, 0.0f);
+ GL11.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear3);
+ GL11.glPopMatrix();
+
+ GL11.glPopMatrix();
+ swapBuffers();
+ repaint();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+ if (startTime > System.currentTimeMillis()) {
+ fps++;
+ } else {
+ long timeUsed = 5000 + (startTime - System.currentTimeMillis());
+ startTime = System.currentTimeMillis() + 5000;
+ System.out.println(fps + " frames in " + (float) (timeUsed / 1000f) + " seconds = "
+ + (fps / (timeUsed / 1000f)));
+ fps = 0;
+ }
+ }
+
+ private void setup() {
+ // setup ogl
+ FloatBuffer pos = BufferUtils.createFloatBuffer(4).put(new float[] { 5.0f, 5.0f, 10.0f, 0.0f});
+ FloatBuffer red = BufferUtils.createFloatBuffer(4).put(new float[] { 0.8f, 0.1f, 0.0f, 1.0f});
+ FloatBuffer green = BufferUtils.createFloatBuffer(4).put(new float[] { 0.0f, 0.8f, 0.2f, 1.0f});
+ FloatBuffer blue = BufferUtils.createFloatBuffer(4).put(new float[] { 0.2f, 0.2f, 1.0f, 1.0f});
+ pos.flip();
+ red.flip();
+ green.flip();
+ blue.flip();
+
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, pos);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_LIGHTING);
+ GL11.glEnable(GL11.GL_LIGHT0);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = GL11.glGenLists(1);
+ GL11.glNewList(gear1, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0f, 4.0f, 1.0f, 20, 0.7f);
+ GL11.glEndList();
+
+ gear2 = GL11.glGenLists(1);
+ GL11.glNewList(gear2, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5f, 2.0f, 2.0f, 10, 0.7f);
+ GL11.glEndList();
+
+ gear3 = GL11.glGenLists(1);
+ GL11.glNewList(gear3, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3f, 2.0f, 0.5f, 10, 0.7f);
+ GL11.glEndList();
+
+ GL11.glEnable(GL11.GL_NORMALIZE);
+
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+
+ System.err.println("GL_VENDOR: " + GL11.glGetString(GL11.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + GL11.glGetString(GL11.GL_RENDERER));
+ System.err.println("GL_VERSION: " + GL11.glGetString(GL11.GL_VERSION));
+ System.err.println();
+ System.err.println("glLoadTransposeMatrixfARB() supported: " + GLContext.getCapabilities().GL_ARB_transpose_matrix);
+ if (!GLContext.getCapabilities().GL_ARB_transpose_matrix) {
+ // --- not using extensions
+ GL11.glLoadIdentity();
+ } else {
+ // --- using extensions
+ final FloatBuffer identityTranspose = BufferUtils.createFloatBuffer(16).put(
+ new float[] { 1, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1});
+ identityTranspose.flip();
+ ARBTransposeMatrix.glLoadTransposeMatrixARB(identityTranspose);
+ }
+
+ float h = (float) 300 / (float) 300;
+ GL11.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glTranslatef(0.0f, 0.0f, -40.0f);
+ }
+
+ /**
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * @param inner_radius radius of hole at center
+ * @param outer_radius radius at center of teeth
+ * @param width width of gear
+ * @param teeth number of teeth
+ * @param tooth_depth depth of tooth
+ */
+ private void gear(float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) {
+ int i;
+ float r0, r1, r2;
+ float angle, da;
+ float u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0f;
+ r2 = outer_radius + tooth_depth / 2.0f;
+
+ da = 2.0f * (float) Math.PI / teeth / 4.0f;
+
+ GL11.glShadeModel(GL11.GL_FLAT);
+
+ GL11.glNormal3f(0.0f, 0.0f, 1.0f);
+
+ /* draw front face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ if (i < teeth) {
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da),
+ width * 0.5f);
+ }
+ }
+ GL11.glEnd();
+
+ /* draw front sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw outward faces of teeth */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle);
+ v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle);
+ len = (float) Math.sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da);
+ v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da);
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ }
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f);
+ GL11.glEnd();
+
+ GL11.glShadeModel(GL11.GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ }
+ GL11.glEnd();
+ }
+
+ /*
+ * @see org.lwjgl.test.applet.Test#start()
+ */
+ public void start() {
+ }
+
+ /*
+ * @see org.lwjgl.test.applet.Test#stop()
+ */
+ public void stop() {
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/awt/AWTTest.java b/src/java/org/lwjgl/test/opengl/awt/AWTTest.java
new file mode 100644
index 0000000..80e8af7
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/awt/AWTTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.awt;
+
+import java.awt.Frame;
+import java.awt.GridLayout;
+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.util.glu.GLU;
+
+/**
+ *
+ * Tests AWTGLCanvas functionality
+ *
+ * @version $Revision: 2983 $
+ * @author $Author: matzon $
+ * $Id: AWTTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class AWTTest extends Frame {
+
+ /** AWT GL canvas */
+ private AWTGLCanvas canvas0, canvas1;
+
+ private volatile float angle;
+
+ /**
+ * C'tor
+ */
+ public AWTTest() throws LWJGLException {
+ setTitle("LWJGL AWT Canvas Test");
+ setSize(640, 320);
+ setLayout(new GridLayout(1, 2));
+ add(canvas0 = new AWTGLCanvas() {
+ int current_height;
+ int current_width;
+ public void paintGL() {
+ try {
+ if (getWidth() != current_width || getHeight() != current_height) {
+ current_width = getWidth();
+ current_height = getHeight();
+ GL11.glViewport(0, 0, current_width, current_height);
+ }
+ 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();
+ repaint();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ add(canvas1 = new AWTGLCanvas() {
+ int current_height;
+ int current_width;
+ public void paintGL() {
+ try {
+ angle += 1.0f;
+ if (getWidth() != current_width || getHeight() != current_height) {
+ current_width = getWidth();
+ current_height = getHeight();
+ GL11.glViewport(0, 0, current_width, current_height);
+ }
+ 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();
+ repaint();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ dispose();
+ System.exit(0);
+ }
+ });
+ setResizable(true);
+ setVisible(true);
+ }
+
+ public static void main(String[] args) throws LWJGLException {
+ new AWTTest();
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/awt/DemoBox.java b/src/java/org/lwjgl/test/opengl/awt/DemoBox.java
new file mode 100644
index 0000000..9e4be2d
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/awt/DemoBox.java
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Panel;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.nio.FloatBuffer;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.ARBTransposeMatrix;
+import org.lwjgl.opengl.AWTGLCanvas;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GLContext;
+
+/**
+ *
+ *
+ * @version $Revision$
+ * @author Brian Matzon
+ * $Id$
+ */
+public class DemoBox extends Frame {
+
+ /** GL canvas */
+ private DemoBoxGLCanvas demoCanvas;
+
+ /** Demo selection panel */
+ private Panel selectionPanel;
+
+ /** Hashtable of demos */
+ private Hashtable selectableDemos;
+
+ /**
+ * Creates a new demo box instance
+ */
+ public DemoBox() {
+ selectableDemos = new Hashtable();
+ selectableDemos.put("default", new NullDemoBox());
+ selectableDemos.put("clear_color", new ClearColorDemoBox());
+ selectableDemos.put("gears", new GearsDemoBox());
+ }
+
+ /**
+ * @return
+ */
+ public boolean initialize() {
+ setTitle("LWJGL - Demo Box");
+ setSize(640, 480);
+ setLayout(new GridBagLayout());
+
+ // Setup selection panel
+ // =================================
+ selectionPanel = new Panel();
+ selectionPanel.setLayout(new BorderLayout());
+ selectionPanel.add(new Label("Demo", Label.CENTER), BorderLayout.NORTH);
+
+ Button fullScreen = new Button("Fullscreen");
+ fullScreen.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent event) {
+ toggleFullscreen();
+ }
+ });
+ selectionPanel.add(fullScreen, BorderLayout.SOUTH);
+
+ final List demos = new List();
+ for (Enumeration e = selectableDemos.keys(); e.hasMoreElements();) {
+ demos.add(e.nextElement().toString());
+ }
+ selectionPanel.add(demos, BorderLayout.CENTER);
+
+ demos.addItemListener(new ItemListener() {
+
+ public void itemStateChanged(ItemEvent event) {
+ demoSelected(event.getItemSelectable().getSelectedObjects()[0].toString());
+ }
+ });
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.fill = java.awt.GridBagConstraints.BOTH;
+ gbc.weightx = 0.05;
+ gbc.weighty = 1.0;
+ add(selectionPanel, gbc);
+ // ---------------------------------
+
+ // setup demo canvas
+ // =================================
+ try {
+ demoCanvas = new DemoBoxGLCanvas(this);
+
+ gbc = new GridBagConstraints();
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ gbc.fill = java.awt.GridBagConstraints.BOTH;
+ gbc.weightx = 0.95;
+ gbc.weighty = 1.0;
+ add(demoCanvas, gbc);
+ } catch (LWJGLException le) {
+ le.printStackTrace();
+ return false;
+ }
+ // ---------------------------------
+
+ addWindowListener(new WindowAdapter() {
+
+ public void windowClosing(WindowEvent e) {
+ demoCanvas.destroy();
+ dispose();
+ System.exit(0);
+ }
+ });
+
+ //demos.select(0);
+ //demoSelected(demos.getSelectedItem());
+ return true;
+ }
+
+ public void updateFPS(float fps) {
+ if(fps != -1) {
+ setTitle("LWJGL - Demo Box (FPS: " + fps + ")");
+ } else {
+ setTitle("LWJGL - Demo Box");
+ }
+ }
+
+ /**
+ * Enter fullscreen mode for this demo
+ */
+ protected void toggleFullscreen() {
+ System.out.println("Toggle Fullscreen");
+ }
+
+ /**
+ * Selected a demo
+ * @param demo Name of demo that was selected
+ */
+ protected void demoSelected(String demo) {
+ System.out.println("Selecting demo: " + demo);
+ demoCanvas.setActiveDemo((Demo) selectableDemos.get(demo));
+ }
+
+ /**
+ * @param args
+ * @throws LWJGLException
+ */
+ public static void main(String[] args) throws LWJGLException {
+ DemoBox demo = new DemoBox();
+ demo.initialize();
+ demo.setVisible(true);
+ }
+
+ /**
+ * Interface for a demo
+ */
+ public interface Demo {
+ public boolean isInitialized();
+ public boolean initialize();
+ public void render();
+ public void destroy();
+ }
+
+ /**
+ *
+ */
+ private class DemoBoxGLCanvas extends AWTGLCanvas implements Runnable {
+
+ /** Parent demo box */
+ DemoBox parent;
+
+ /** Currently active demo */
+ Demo activeDemo;
+
+ /** last active demo */
+ Demo lastActiveDemo;
+
+ /** Render thread */
+ private Thread renderThread;
+
+ public DemoBoxGLCanvas(DemoBox parent) throws LWJGLException {
+ super();
+ this.parent = parent;
+ }
+
+ // FPS
+ long startTime = 0;
+ long fps = 0;
+
+ protected void paintGL() {
+ synchronized (this) {
+ if (lastActiveDemo != null && lastActiveDemo != activeDemo) {
+ lastActiveDemo.destroy();
+ lastActiveDemo = null;
+ if (activeDemo != null) {
+ activeDemo.initialize();
+ startTime = System.currentTimeMillis() + 5000;
+ } else {
+ parent.updateFPS(-1);
+ }
+ }
+
+ if (activeDemo != null) {
+
+ if(!activeDemo.isInitialized()) {
+ activeDemo.initialize();
+ }
+
+ activeDemo.render();
+ try {
+ swapBuffers();
+ } catch (LWJGLException le) {
+ le.printStackTrace();
+ }
+
+ if (startTime > System.currentTimeMillis()) {
+ fps++;
+ } else {
+ long timeUsed = 5000 + (startTime - System.currentTimeMillis());
+ startTime = System.currentTimeMillis() + 5000;
+ parent.updateFPS((fps / (timeUsed / 1000f)));
+ fps = 0;
+ }
+ }
+ }
+ }
+
+ public void destroy() {
+ setActiveDemo(null);
+ renderThread = null;
+ }
+
+ public void setActiveDemo(Demo activeDemo) {
+ synchronized (this) {
+ // setting no current demo
+ if (activeDemo == null) {
+ lastActiveDemo = this.activeDemo;
+ this.activeDemo = null;
+ return;
+ }
+
+ // setting to new demo
+ lastActiveDemo = this.activeDemo;
+ this.activeDemo = activeDemo;
+ }
+
+ if (renderThread == null) {
+ renderThread = new Thread(this);
+ renderThread.setName("DemoBox-Renderer");
+ renderThread.start();
+ }
+ }
+
+ public DemoBoxGLCanvas() throws LWJGLException {
+ super();
+ }
+
+ public void run() {
+ long sleep_time = 1000;
+ while (renderThread != null) {
+
+ // check for change of demo
+ synchronized (this) {
+ // if no demo set, just sleep
+ if (activeDemo == null) {
+ sleep_time = 1000;
+ } else {
+ // we have a demo!
+ sleep_time = 16;
+ repaint();
+ }
+ }
+ sleep(sleep_time);
+ }
+ System.out.println("dead");
+ }
+
+ private void sleep(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException inte) {
+ }
+ }
+ }
+
+ // Demo box demo
+ // ========================================================
+ public class ClearColorDemoBox implements Demo {
+
+ private boolean initialized;
+
+ int direction = 1;
+
+ float color;
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ public boolean initialize() {
+ return initialized = true;
+ }
+
+ public void render() {
+ GL11.glClearColor(color, color, color, 1f);
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+
+ color += direction * .05f;
+
+ if (color > 1f) {
+ color = 1f;
+ direction = -1 * direction;
+ } else if (color < 0f) {
+ direction = -1 * direction;
+ color = 0f;
+ }
+ }
+
+ public void destroy() {
+ initialized = false;
+ }
+ }
+
+ // --------------------------------------------------------
+
+ // Demo box demo
+ // ========================================================
+ public class NullDemoBox implements Demo {
+
+ private boolean initialized;
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ public boolean initialize() {
+ GL11.glClearColor(0, 0, 0, 1f);
+ return true;
+ }
+
+ public void render() {
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+ }
+
+ public void destroy() {
+ initialized = false;
+ }
+ }
+ // --------------------------------------------------------
+
+ // Demo box demo
+ // ========================================================
+ public class GearsDemoBox implements Demo {
+
+ private boolean initialized;
+
+ private float view_rotx = 20.0f;
+
+ private float view_roty = 30.0f;
+
+ private float view_rotz = 0.0f;
+
+ private int gear1;
+
+ private int gear2;
+
+ private int gear3;
+
+ private float angle = 0.0f;
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ public boolean initialize() {
+ // setup ogl
+ FloatBuffer pos = BufferUtils.createFloatBuffer(4).put(new float[] { 5.0f, 5.0f, 10.0f, 0.0f});
+ FloatBuffer red = BufferUtils.createFloatBuffer(4).put(new float[] { 0.8f, 0.1f, 0.0f, 1.0f});
+ FloatBuffer green = BufferUtils.createFloatBuffer(4).put(new float[] { 0.0f, 0.8f, 0.2f, 1.0f});
+ FloatBuffer blue = BufferUtils.createFloatBuffer(4).put(new float[] { 0.2f, 0.2f, 1.0f, 1.0f});
+ pos.flip();
+ red.flip();
+ green.flip();
+ blue.flip();
+
+ GL11.glClearColor(0, 0, 0, 1f);
+
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, pos);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_LIGHTING);
+ GL11.glEnable(GL11.GL_LIGHT0);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = GL11.glGenLists(1);
+ GL11.glNewList(gear1, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0f, 4.0f, 1.0f, 20, 0.7f);
+ GL11.glEndList();
+
+ gear2 = GL11.glGenLists(1);
+ GL11.glNewList(gear2, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5f, 2.0f, 2.0f, 10, 0.7f);
+ GL11.glEndList();
+
+ gear3 = GL11.glGenLists(1);
+ GL11.glNewList(gear3, GL11.GL_COMPILE);
+ GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3f, 2.0f, 0.5f, 10, 0.7f);
+ GL11.glEndList();
+
+ GL11.glEnable(GL11.GL_NORMALIZE);
+
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+
+ System.err.println("GL_VENDOR: " + GL11.glGetString(GL11.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + GL11.glGetString(GL11.GL_RENDERER));
+ System.err.println("GL_VERSION: " + GL11.glGetString(GL11.GL_VERSION));
+ System.err.println();
+ System.err.println("glLoadTransposeMatrixfARB() supported: " + GLContext.getCapabilities().GL_ARB_transpose_matrix);
+ if (!GLContext.getCapabilities().GL_ARB_transpose_matrix) {
+ // --- not using extensions
+ GL11.glLoadIdentity();
+ } else {
+ // --- using extensions
+ final FloatBuffer identityTranspose = BufferUtils.createFloatBuffer(16).put(
+ new float[] { 1, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1});
+ identityTranspose.flip();
+ ARBTransposeMatrix.glLoadTransposeMatrixARB(identityTranspose);
+ }
+
+ float h = (float) 300 / (float) 300;
+ GL11.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glTranslatef(0.0f, 0.0f, -40.0f);
+ return initialized = true;
+ }
+
+ public void render() {
+ angle += 2.0f;
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+
+ GL11.glPushMatrix();
+ GL11.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
+ GL11.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
+ GL11.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(-3.0f, -2.0f, 0.0f);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear1);
+ GL11.glPopMatrix();
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(3.1f, -2.0f, 0.0f);
+ GL11.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear2);
+ GL11.glPopMatrix();
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(-3.1f, 4.2f, 0.0f);
+ GL11.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f);
+ GL11.glCallList(gear3);
+ GL11.glPopMatrix();
+
+ GL11.glPopMatrix();
+ }
+
+ /**
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * @param inner_radius radius of hole at center
+ * @param outer_radius radius at center of teeth
+ * @param width width of gear
+ * @param teeth number of teeth
+ * @param tooth_depth depth of tooth
+ */
+ private void gear(float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) {
+ int i;
+ float r0, r1, r2;
+ float angle, da;
+ float u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0f;
+ r2 = outer_radius + tooth_depth / 2.0f;
+
+ da = 2.0f * (float) Math.PI / teeth / 4.0f;
+
+ GL11.glShadeModel(GL11.GL_FLAT);
+
+ GL11.glNormal3f(0.0f, 0.0f, 1.0f);
+
+ /* draw front face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ if (i < teeth) {
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da),
+ width * 0.5f);
+ }
+ }
+ GL11.glEnd();
+
+ /* draw front sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back face */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw back sides of teeth */
+ GL11.glBegin(GL11.GL_QUADS);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ }
+ GL11.glEnd();
+
+ /* draw outward faces of teeth */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
+ u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle);
+ v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle);
+ len = (float) Math.sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f);
+ GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
+ u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da);
+ v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da);
+ GL11.glNormal3f(v, -u, 0.0f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
+ GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
+ }
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f);
+ GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f);
+ GL11.glEnd();
+
+ GL11.glShadeModel(GL11.GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ GL11.glBegin(GL11.GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0f * (float) Math.PI / teeth;
+ GL11.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
+ GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
+ }
+ GL11.glEnd();
+ }
+
+ public void destroy() {
+ GL11.glDeleteLists(gear1, 1);
+ GL11.glDeleteLists(gear2, 1);
+ GL11.glDeleteLists(gear3, 1);
+ initialized = false;
+ }
+ }
+ // --------------------------------------------------------
+}
diff --git a/src/java/org/lwjgl/test/opengl/awt/DisplayParentTest.java b/src/java/org/lwjgl/test/opengl/awt/DisplayParentTest.java
new file mode 100644
index 0000000..e5848db
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/awt/DisplayParentTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.awt;
+
+import java.awt.Canvas;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.GLU;
+
+/**
+ *
+ * Tests Display.setParent()
+ *
+ * @version $Revision: 3102 $
+ * @author $Author: matzon $
+ * $Id: DisplayParentTest.java 3102 2008-06-08 09:30:24Z matzon $
+ */
+public class DisplayParentTest extends Frame {
+ boolean killswitch = false;
+ public DisplayParentTest() throws LWJGLException {
+ setTitle("LWJGL Display Parent Test");
+ setSize(640, 320);
+ setLayout(new GridLayout(1, 2));
+ final Canvas display_parent = new Canvas();
+ display_parent.setFocusable(true);
+ display_parent.setIgnoreRepaint(true);
+ add(display_parent);
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ killswitch = true;
+ }
+ });
+ setResizable(true);
+ setVisible(true);
+ Display.setParent(display_parent);
+ Display.setVSyncEnabled(true);
+ Display.create();
+ float angle = 0f;
+
+ while (isVisible() && !killswitch) {
+ angle += 1.0f;
+ int width;
+ int height;
+ if (!Display.isFullscreen()) {
+ width = display_parent.getWidth();
+ height = display_parent.getHeight();
+ } else {
+ width = Display.getDisplayMode().getWidth();
+ height = Display.getDisplayMode().getHeight();
+ }
+
+ if(width < 1 || height < 1) {
+ continue;
+ }
+
+ GL11.glViewport(0, 0, width, height);
+ 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) width, 0.0f, (float) height);
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glPushMatrix();
+ GL11.glTranslatef(width / 2.0f, height / 2.0f, 0.0f);
+ GL11.glRotatef(2*angle, 0f, 0f, -1.0f);
+ GL11.glRectf(-50.0f, -50.0f, 50.0f, 50.0f);
+ GL11.glPopMatrix();
+ Display.update();
+ while(Keyboard.next()) {
+ // closing on ESCAPE
+ if(Keyboard.getEventKey() == Keyboard.KEY_ESCAPE && Keyboard.getEventKeyState()) {
+ Display.destroy();
+ dispose();
+ break;
+ }
+
+ if(Keyboard.getEventKey() == Keyboard.KEY_SPACE && Keyboard.getEventKeyState()) {
+ Mouse.setGrabbed(!Mouse.isGrabbed());
+ }
+ if(Keyboard.getEventKey() == Keyboard.KEY_F && Keyboard.getEventKeyState()) {
+ Display.setFullscreen(!Display.isFullscreen());
+ }
+ }
+/* while (Mouse.next()) {
+System.out.println(" Mouse.getEventX() = " + Mouse.getEventX() + " | Mouse.getEventY() = " + Mouse.getEventY());
+ }*/
+ }
+ Display.destroy();
+ dispose();
+ }
+
+ public static void main(String[] args) throws LWJGLException {
+ new DisplayParentTest();
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/pbuffers/PbufferTest.java b/src/java/org/lwjgl/test/opengl/pbuffers/PbufferTest.java
new file mode 100644
index 0000000..4f822ca
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/pbuffers/PbufferTest.java
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.pbuffers;
+
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.Pbuffer;
+import org.lwjgl.opengl.PixelFormat;
+import org.lwjgl.util.glu.GLU;
+import org.lwjgl.util.vector.Vector2f;
+
+/**
+ *
+ * Tests Pbuffers
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: PbufferTest.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public final class PbufferTest {
+
+ /**
+ * Texture and pbuffer size
+ */
+ private static final int TEXTURE_SIZE = 512;
+
+ /**
+ * Size of the animated quad
+ */
+ private static final int QUAD_SIZE = 64;
+
+ /**
+ * The renderer to use when rendering to texture.
+ */
+ private TextureRenderer texRenderer;
+
+ /**
+ * Intended deiplay mode
+ */
+ private DisplayMode mode;
+
+ /**
+ * our quad moving around
+ */
+ private Vector2f quadPosition;
+
+ /**
+ * For positioning our quad in the texture
+ */
+ private float texScaleX, texScaleY;
+
+ /**
+ * our quadVelocity
+ */
+ private Vector2f quadVelocity;
+
+ /**
+ * angle of quad
+ */
+ private float angle;
+
+ /**
+ * degrees to rotate per frame
+ */
+ private float angleRotation = 1.0f;
+
+ /**
+ * Max speed of all changable attributes
+ */
+ private static final float MAX_SPEED = 20.0f;
+
+ /**
+ * The shared texture
+ */
+ private static int texID;
+
+ public PbufferTest(final int renderMode) {
+ try {
+ //find displaymode
+ mode = findDisplayMode(800, 600, 16);
+ Display.setDisplayMode(mode);
+ Display.create(new PixelFormat(16, 0, 0, 0, 0));
+
+ glInit();
+
+ if ( (Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0 ) {
+ System.out.println("No Pbuffer support!");
+ System.exit(-1);
+ }
+ System.out.println("Pbuffer support detected. Initializing...\n");
+
+ switch ( renderMode ) {
+ case 1:
+ System.out.print("Creating pbuffer with unique context...");
+ texRenderer = new UniqueRenderer(TEXTURE_SIZE, TEXTURE_SIZE, texID);
+ break;
+ case 2:
+ System.out.print("Creating render-to-texture pbuffer with unique context...");
+ texRenderer = new UniqueRendererRTT(TEXTURE_SIZE, TEXTURE_SIZE, texID);
+ break;
+ }
+
+ System.out.println("OK");
+
+ quadPosition = new Vector2f(100f, 100f);
+ quadVelocity = new Vector2f(1.0f, 1.0f);
+
+ texScaleX = TEXTURE_SIZE / (float)mode.getWidth();
+ texScaleY = TEXTURE_SIZE / (float)mode.getHeight();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Executes the test
+ */
+ public void execute() {
+ mainLoop();
+ cleanup();
+ }
+
+ /**
+ * Runs the main loop of the "test"
+ */
+ private void mainLoop() {
+ while ( !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) && !Display.isCloseRequested() ) {
+ if ( Display.isVisible() ) {
+ // check keyboard input
+ processKeyboard();
+
+ // do "game" logic, and render it
+ logic();
+
+ render();
+ } else {
+ // no need to render/paint if nothing has changed (ie. window dragged over)
+ if ( Display.isDirty() )
+ render();
+
+
+ // don't waste cpu time, sleep more
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException inte) {
+ }
+ }
+ // Update window
+ Display.update();
+ // Sync
+ Display.sync(100);
+ }
+ }
+
+ /**
+ * Performs the logic
+ */
+ private void logic() {
+ angle += angleRotation;
+ if ( angle > 360.0f )
+ angle -= 360.0f;
+
+ quadPosition.x += quadVelocity.x;
+ quadPosition.y += quadVelocity.y;
+
+ // check colision with vertical border border
+ if ( quadPosition.x + QUAD_SIZE >= mode.getWidth() || quadPosition.x - QUAD_SIZE <= 0 )
+ quadVelocity.x *= -1;
+
+ // check collision with horizontal border
+ if ( quadPosition.y + QUAD_SIZE >= mode.getHeight() || quadPosition.y - QUAD_SIZE <= 0 )
+ quadVelocity.y *= -1;
+ }
+
+ private void render() {
+ // -----------------------------------------------------------
+ // -------------------- Pbuffer rendering --------------------
+ // -----------------------------------------------------------
+ // Tell the pbuffer to get ready for rendering
+ texRenderer.enable();
+
+ // Clear the background
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+
+ // Draw quad with gradient
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(quadPosition.x * texScaleX, quadPosition.y * texScaleY, 0);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ {
+ GL11.glColor3f(1.0f, 0.0f, 0.0f);
+ GL11.glVertex2i(-QUAD_SIZE, -QUAD_SIZE);
+ GL11.glVertex2i(QUAD_SIZE, -QUAD_SIZE);
+ GL11.glColor3f(0.0f, 0.0f, 1.0f);
+ GL11.glVertex2i(QUAD_SIZE, QUAD_SIZE);
+ GL11.glVertex2i(-QUAD_SIZE, QUAD_SIZE);
+ }
+ GL11.glEnd();
+ }
+ GL11.glPopMatrix();
+
+ // Refresh the texture
+ texRenderer.updateTexture();
+
+ // -----------------------------------------------------------
+ // -------------------- Display rendering --------------------
+ // -----------------------------------------------------------
+ try {
+ Display.makeCurrent();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
+
+ // draw white quad
+ GL11.glPushMatrix();
+ {
+ GL11.glTranslatef(quadPosition.x, quadPosition.y, 0);
+ GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ GL11.glColor3f(1.0f, 1.0f, 1.0f);
+ GL11.glBegin(GL11.GL_QUADS);
+ {
+ GL11.glTexCoord2f(0f, 0f);
+ GL11.glVertex2i(-QUAD_SIZE, -QUAD_SIZE);
+ GL11.glTexCoord2f(1f, 0f);
+ GL11.glVertex2i(QUAD_SIZE, -QUAD_SIZE);
+ GL11.glTexCoord2f(1f, 1f);
+ GL11.glVertex2i(QUAD_SIZE, QUAD_SIZE);
+ GL11.glTexCoord2f(0f, 1f);
+ GL11.glVertex2i(-QUAD_SIZE, QUAD_SIZE);
+ }
+ GL11.glEnd();
+ }
+ GL11.glPopMatrix();
+ }
+
+ /**
+ * Processes keyboard input
+ */
+ private void processKeyboard() {
+ Keyboard.poll();
+
+ //check for fullscreen key
+ if ( Keyboard.isKeyDown(Keyboard.KEY_F) ) {
+ try {
+ Display.setDisplayMode(mode);
+ Display.setFullscreen(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //check for window key
+ if ( Keyboard.isKeyDown(Keyboard.KEY_W) ) {
+ try {
+ Display.setFullscreen(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //check for speed changes
+ if ( Keyboard.isKeyDown(Keyboard.KEY_UP) )
+ quadVelocity.y += 0.1f;
+ if ( Keyboard.isKeyDown(Keyboard.KEY_DOWN) )
+ quadVelocity.y -= 0.1f;
+ if ( Keyboard.isKeyDown(Keyboard.KEY_RIGHT) )
+ quadVelocity.x += 0.1f;
+ if ( Keyboard.isKeyDown(Keyboard.KEY_LEFT) )
+ quadVelocity.x -= 0.1f;
+
+ if ( Keyboard.isKeyDown(Keyboard.KEY_ADD) )
+ angleRotation += 0.1f;
+ if ( Keyboard.isKeyDown(Keyboard.KEY_SUBTRACT) )
+ angleRotation -= 0.1f;
+
+ //throttle
+ if ( quadVelocity.x < -MAX_SPEED )
+ quadVelocity.x = -MAX_SPEED;
+ if ( quadVelocity.x > MAX_SPEED )
+ quadVelocity.x = MAX_SPEED;
+ if ( quadVelocity.y < -MAX_SPEED )
+ quadVelocity.y = -MAX_SPEED;
+ if ( quadVelocity.y > MAX_SPEED )
+ quadVelocity.y = MAX_SPEED;
+
+ if ( angleRotation < 0.0f )
+ angleRotation = 0.0f;
+ if ( angleRotation > MAX_SPEED )
+ angleRotation = MAX_SPEED;
+ }
+
+ /**
+ * Cleans up the test
+ */
+ private void cleanup() {
+ // Destroy texture
+ IntBuffer buffer = BufferUtils.createIntBuffer(1);
+ buffer.put(0, texID);
+ GL11.glDeleteTextures(buffer);
+
+ texRenderer.destroy();
+ Display.destroy();
+ }
+
+ /**
+ * Retrieves a displaymode, if one such is available
+ *
+ * @param width Required width
+ * @param height Required height
+ * @param bpp Minimum required bits per pixel
+ *
+ * @return
+ */
+ 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 ) {
+ return modes[i];
+ }
+ }
+ return null;
+ }
+
+ static void initGLState(int width, int height, float color) {
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluOrtho2D(0, width, 0, height);
+
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+ GL11.glViewport(0, 0, width, height);
+
+ //set clear color
+ GL11.glClearColor(color, color, color, 0.0f);
+ }
+
+ /**
+ * Initializes OGL
+ */
+ private void glInit() {
+ // Sync frame (only works on windows)
+ Display.setVSyncEnabled(true);
+
+ // Create shared texture
+ IntBuffer buffer = BufferUtils.createIntBuffer(1);
+ GL11.glGenTextures(buffer);
+ texID = buffer.get(0);
+
+ GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
+ GL11.glEnable(GL11.GL_TEXTURE_2D);
+
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
+
+ initGLState(mode.getWidth(), mode.getHeight(), 0.0f);
+ }
+
+ /**
+ * Test entry point
+ */
+ public static void main(String[] args) {
+ if ( args.length != 1 )
+ kill("Invalid arguments length.");
+
+ int mode = -1;
+ try {
+ mode = Integer.parseInt(args[0]);
+ } catch (NumberFormatException e) {
+ kill("Invalid mode.");
+ }
+
+ if ( mode != 1 && mode != 2 )
+ kill("Invalid mode.");
+
+ System.out.println("Change between fullscreen and windowed mode, by pressing F and W respectively");
+ System.out.println("Move quad using arrowkeys, and change rotation using +/-");
+
+ PbufferTest test = new PbufferTest(mode);
+
+ test.execute();
+ System.exit(0);
+ }
+
+ private static void kill(final String msg) {
+ System.out.println(msg);
+ System.out.println("-------");
+ System.out.println("Usage: java org.lwjgl.test.opengl.pbuffer.PbufferTest ");
+ System.out.println("\n.");
+ System.out.println("\t1: no render-to-texture");
+ System.out.println("\t2: with render-to-texture");
+
+ System.exit(-1);
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/pbuffers/TextureRenderer.java b/src/java/org/lwjgl/test/opengl/pbuffers/TextureRenderer.java
new file mode 100644
index 0000000..a8a2f77
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/pbuffers/TextureRenderer.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.pbuffers;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Pbuffer;
+
+/**
+ * Implementations of this class should create a pbuffer and implement "render-to-texture" accordingly.
+ */
+abstract class TextureRenderer {
+
+ protected final int width;
+ protected final int height;
+ private final int texID;
+
+ protected Pbuffer pbuffer;
+
+ protected TextureRenderer(final int width, final int height, final int texID) {
+ this.width = width;
+ this.height = height;
+ this.texID = texID;
+
+ try {
+ pbuffer = init(width, height, texID);
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * Create and initialize the pbuffer.
+ *
+ * @param width
+ * @param height
+ * @param texID
+ * @return
+ * @throws LWJGLException
+ */
+ protected abstract Pbuffer init(int width, int height, int texID) throws LWJGLException;
+
+ /**
+ * This will be called before rendering to the renderer. Implementations should setup the pbuffer context as necessary.
+ */
+ void enable() {
+ try {
+ if ( pbuffer.isBufferLost() ) {
+ System.out.println("Buffer contents lost - recreating the pbuffer");
+ pbuffer.destroy();
+ pbuffer = init(width, height, texID);
+ }
+
+ pbuffer.makeCurrent();
+ } catch (LWJGLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Implementations should update the texture contents here.
+ */
+ abstract void updateTexture();
+
+ /**
+ * Clean-up resources held by the renderer
+ */
+ final void destroy() {
+ pbuffer.destroy();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/pbuffers/UniqueRenderer.java b/src/java/org/lwjgl/test/opengl/pbuffers/UniqueRenderer.java
new file mode 100644
index 0000000..fd3cf9e
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/pbuffers/UniqueRenderer.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.pbuffers;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.Pbuffer;
+import org.lwjgl.opengl.PixelFormat;
+
+final class UniqueRenderer extends TextureRenderer {
+
+ UniqueRenderer(final int width, final int height, final int texID) {
+ super(width, height, texID);
+ }
+
+ protected Pbuffer init(final int width, final int height, final int texID) {
+ Pbuffer pbuffer = null;
+
+ try {
+ pbuffer = new Pbuffer(width, height, new PixelFormat(16, 0, 0, 0, 0), null, null);
+
+ // Initialise state of the pbuffer context.
+ pbuffer.makeCurrent();
+
+ PbufferTest.initGLState(width, height, 0.5f);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
+
+ Display.makeCurrent();
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+
+ return pbuffer;
+ }
+
+ public void updateTexture() {
+ // Copy the pbuffer contents to the texture.
+ GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, 0, 0, width, height, 0);
+ }
+
+}
diff --git a/src/java/org/lwjgl/test/opengl/pbuffers/UniqueRendererRTT.java b/src/java/org/lwjgl/test/opengl/pbuffers/UniqueRendererRTT.java
new file mode 100644
index 0000000..c726bff
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/pbuffers/UniqueRendererRTT.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2002-2008 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.test.opengl.pbuffers;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.Pbuffer;
+import org.lwjgl.opengl.PixelFormat;
+import org.lwjgl.opengl.RenderTexture;
+
+final class UniqueRendererRTT extends TextureRenderer {
+
+ UniqueRendererRTT(final int width, final int height, final int texID) {
+ super(width, height, texID);
+ }
+
+ // Initialize texture renderer
+ protected Pbuffer init(final int width, final int height, final int texID) {
+ Pbuffer pbuffer = null;
+
+ try {
+ final RenderTexture rt = new RenderTexture(true, false, false, false, RenderTexture.RENDER_TEXTURE_2D, 0);
+ pbuffer = new Pbuffer(width, height, new PixelFormat(16, 0, 0, 0, 0), rt, null);
+
+ // Initialise state of the pbuffer context.
+ pbuffer.makeCurrent();
+
+ PbufferTest.initGLState(width, height, 0.5f);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
+
+ Display.makeCurrent();
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+
+ return pbuffer;
+ }
+
+ void enable() {
+ super.enable();
+
+ // Put the renderer contents to the texture
+ pbuffer.releaseTexImage(Pbuffer.FRONT_LEFT_BUFFER);
+ }
+
+ void updateTexture() {
+ // Bind the texture after rendering.
+ pbuffer.bindTexImage(Pbuffer.FRONT_LEFT_BUFFER);
+ }
+
+}
diff --git a/src/java/org/lwjgl/test/opengl/shaders/Shader.java b/src/java/org/lwjgl/test/opengl/shaders/Shader.java
new file mode 100644
index 0000000..1117851
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/Shader.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+/*
+ * Created by LWJGL.
+ * User: spasi
+ * Date: 2004-03-30
+ * Time: 8:41:42 pm
+ */
+package org.lwjgl.test.opengl.shaders;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.ARBProgram;
+import org.lwjgl.opengl.ARBShaderObjects;
+import org.lwjgl.opengl.GL11;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+abstract class Shader {
+
+ protected static ByteBuffer fileBuffer = BufferUtils.createByteBuffer(1024 * 10);
+
+ protected Shader() {
+ }
+
+ abstract void render();
+
+ abstract void cleanup();
+
+ protected static String getShaderText(String file) {
+ String shader = null;
+
+ try {
+ ClassLoader loader = ShadersTest.class.getClassLoader();
+ InputStream inputStream = loader.getResourceAsStream("org/lwjgl/test/opengl/shaders/" + file);
+
+ if ( inputStream == null )
+ ShadersTest.kill("A shader source file could not be found: " + file);
+
+ BufferedInputStream stream = new BufferedInputStream(inputStream);
+
+ byte character;
+ while ( (character = (byte)stream.read()) != -1 )
+ fileBuffer.put(character);
+
+ stream.close();
+
+ fileBuffer.flip();
+
+ byte[] array = new byte[fileBuffer.remaining()];
+ fileBuffer.get(array);
+ shader = new String(array);
+
+ fileBuffer.clear();
+ } catch (IOException e) {
+ ShadersTest.kill("Failed to read the shader source file: " + file, e);
+ }
+
+ return shader;
+ }
+
+ protected static void checkProgramError(String programFile, String programSource) {
+ if ( GL11.glGetError() == GL11.GL_INVALID_OPERATION ) {
+ final int errorPos = GL11.glGetInteger(ARBProgram.GL_PROGRAM_ERROR_POSITION_ARB);
+ int lineStart = 0;
+ int lineEnd = -1;
+ for ( int i = 0; i < programSource.length(); i++ ) {
+ if ( programSource.charAt(i) == '\n' ) {
+ if ( i <= errorPos ) {
+ lineStart = i + 1;
+ } else {
+ lineEnd = i;
+ break;
+ }
+ }
+ }
+
+ if ( lineEnd == -1 )
+ lineEnd = programSource.length();
+
+ ShadersTest.kill("Low-level program error in file: " + programFile
+ + "\n\tError line: " + programSource.substring(lineStart, lineEnd)
+ + "\n\tError message: " + GL11.glGetString(ARBProgram.GL_PROGRAM_ERROR_STRING_ARB));
+ }
+ }
+
+ protected static int getUniformLocation(int ID, String name) {
+ final int location = ARBShaderObjects.glGetUniformLocationARB(ID, name);
+
+ if ( location == -1 )
+ throw new IllegalArgumentException("The uniform \"" + name + "\" does not exist in the Shader Program.");
+
+ return location;
+ }
+
+ protected static void printShaderObjectInfoLog(String file, int ID) {
+ final int logLength = ARBShaderObjects.glGetObjectParameteriARB(ID, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB);
+ if ( logLength <= 1 )
+ return;
+
+ System.out.println("\nInfo Log of Shader Object: " + file);
+ System.out.println("--------------------------");
+ System.out.println(ARBShaderObjects.glGetInfoLogARB(ID, logLength));
+
+ }
+
+ protected static void printShaderProgramInfoLog(int ID) {
+ final int logLength = ARBShaderObjects.glGetObjectParameteriARB(ID, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB);
+ if ( logLength <= 1 )
+ return;
+
+ System.out.println("\nShader Program Info Log: ");
+ System.out.println("--------------------------");
+ System.out.println(ARBShaderObjects.glGetInfoLogARB(ID, logLength));
+ }
+
+}
diff --git a/src/java/org/lwjgl/test/opengl/shaders/ShaderFP.java b/src/java/org/lwjgl/test/opengl/shaders/ShaderFP.java
new file mode 100644
index 0000000..e68d8ff
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/ShaderFP.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+/*
+ * Created by LWJGL.
+ * User: spasi
+ * Date: 2004-03-30
+ * Time: 9:55:38 pm
+ */
+
+package org.lwjgl.test.opengl.shaders;
+
+import org.lwjgl.opengl.ARBFragmentProgram;
+import org.lwjgl.opengl.ARBProgram;
+import org.lwjgl.opengl.ARBVertexProgram;
+import org.lwjgl.opengl.GL11;
+
+final class ShaderFP extends Shader {
+
+ final String vpFile;
+ final String vpSource;
+
+ final int vpID;
+
+ final String fpFile;
+ final String fpSource;
+
+ final int fpID;
+
+ ShaderFP(final String vpShaderFile, final String fpShaderFile) {
+ // Initialize the vertex program.
+ vpFile = vpShaderFile;
+ vpSource = getShaderText(vpShaderFile);
+
+ vpID = ARBProgram.glGenProgramsARB();
+
+ ARBProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, vpID);
+ ARBProgram.glProgramStringARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, vpSource);
+
+ checkProgramError(vpFile, vpSource);
+
+ // Initialize the fragment program.
+ fpFile = fpShaderFile;
+ fpSource = getShaderText(fpShaderFile);
+
+ fpID = ARBProgram.glGenProgramsARB();
+
+ ARBProgram.glBindProgramARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, fpID);
+ ARBProgram.glProgramStringARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, fpSource);
+
+ checkProgramError(fpFile, fpSource);
+ }
+
+ void render() {
+ GL11.glEnable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
+ ARBProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, vpID);
+
+ GL11.glEnable(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB);
+ ARBProgram.glBindProgramARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, fpID);
+
+ ARBProgram.glProgramLocalParameter4fARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, 0,
+ ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f, 0.0f, 0.0f);
+
+ ARBProgram.glProgramLocalParameter4fARB(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB, 0,
+ ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f,
+ -ShadersTest.getDisplayWidth() * 0.5f, -ShadersTest.getDisplayHeight() * 0.5f);
+
+ ShadersTest.renderObject();
+
+ GL11.glDisable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
+ GL11.glDisable(ARBFragmentProgram.GL_FRAGMENT_PROGRAM_ARB);
+ }
+
+ void cleanup() {
+ ARBProgram.glDeleteProgramsARB(vpID);
+ ARBProgram.glDeleteProgramsARB(fpID);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/ShaderFSH.java b/src/java/org/lwjgl/test/opengl/shaders/ShaderFSH.java
new file mode 100644
index 0000000..a69f48f
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/ShaderFSH.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+/*
+ * Created by LWJGL.
+ * User: spasi
+ * Date: 2004-03-30
+ * Time: 9:55:38 pm
+ */
+
+package org.lwjgl.test.opengl.shaders;
+
+import org.lwjgl.opengl.ARBFragmentShader;
+import org.lwjgl.opengl.ARBShaderObjects;
+import org.lwjgl.opengl.ARBVertexShader;
+import org.lwjgl.opengl.GL11;
+
+final class ShaderFSH extends Shader {
+
+ final String vshFile;
+ final String vshSource;
+
+ final int vshID;
+
+ final String fshFile;
+ final String fshSource;
+
+ final int fshID;
+
+ final int programID;
+
+ final int uniformLocation;
+
+ ShaderFSH(final String vshFile, final String fshFile) {
+ // Initialize the vertex shader.
+ this.vshFile = vshFile;
+ vshSource = getShaderText(vshFile);
+
+ vshID = ARBShaderObjects.glCreateShaderObjectARB(ARBVertexShader.GL_VERTEX_SHADER_ARB);
+ ARBShaderObjects.glShaderSourceARB(vshID, vshSource);
+ ARBShaderObjects.glCompileShaderARB(vshID);
+
+ printShaderObjectInfoLog(this.vshFile, vshID);
+
+ if ( ARBShaderObjects.glGetObjectParameteriARB(vshID, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE )
+ ShadersTest.kill("A compilation error occured in a vertex shader.");
+
+ // Initialize the fragment shader.
+ this.fshFile = fshFile;
+ fshSource = getShaderText(fshFile);
+
+ fshID = ARBShaderObjects.glCreateShaderObjectARB(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
+ ARBShaderObjects.glShaderSourceARB(fshID, fshSource);
+ ARBShaderObjects.glCompileShaderARB(fshID);
+
+ printShaderObjectInfoLog(this.fshFile, fshID);
+
+ if ( ARBShaderObjects.glGetObjectParameteriARB(fshID, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE )
+ ShadersTest.kill("A compilation error occured in a fragment shader.");
+
+ // Initialize the shader program.
+ programID = ARBShaderObjects.glCreateProgramObjectARB();
+
+ ARBShaderObjects.glAttachObjectARB(programID, vshID);
+ ARBShaderObjects.glAttachObjectARB(programID, fshID);
+
+ ARBShaderObjects.glLinkProgramARB(programID);
+
+ printShaderProgramInfoLog(programID);
+
+ if ( ARBShaderObjects.glGetObjectParameteriARB(programID, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE )
+ ShadersTest.kill("A linking error occured in a shader program.");
+
+ uniformLocation = getUniformLocation(programID, "UNIFORMS");
+ }
+
+ void render() {
+ ARBShaderObjects.glUseProgramObjectARB(programID);
+
+ ARBShaderObjects.glUniform4fARB(uniformLocation,
+ ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f,
+ -ShadersTest.getDisplayWidth() * 0.5f, -ShadersTest.getDisplayHeight() * 0.5f);
+
+ ShadersTest.renderObject();
+
+ ARBShaderObjects.glUseProgramObjectARB(0);
+ }
+
+ void cleanup() {
+ ARBShaderObjects.glDetachObjectARB(programID, vshID);
+ ARBShaderObjects.glDetachObjectARB(programID, fshID);
+
+ ARBShaderObjects.glDeleteObjectARB(vshID);
+ ARBShaderObjects.glDeleteObjectARB(fshID);
+
+ ARBShaderObjects.glDeleteObjectARB(programID);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/ShaderUNI.java b/src/java/org/lwjgl/test/opengl/shaders/ShaderUNI.java
new file mode 100644
index 0000000..a50278c
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/ShaderUNI.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+/*
+ * Created by LWJGL.
+ * User: spasi
+ * Date: 2009-12-04
+ */
+
+package org.lwjgl.test.opengl.shaders;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.*;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+final class ShaderUNI extends Shader {
+
+ final String file;
+ final String source;
+
+ final int shaderID;
+ final int programID;
+
+ final int bufferID;
+ final FloatBuffer buffer;
+
+ final int uniformA_index;
+ final int uniformA_offset;
+
+ final int uniformB_index;
+ final int uniformB_offset;
+
+ ShaderUNI(final String shaderFile) {
+ file = shaderFile;
+ source = getShaderText(shaderFile);
+
+ shaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
+ GL20.glShaderSource(shaderID, source);
+ GL20.glCompileShader(shaderID);
+
+ printShaderObjectInfoLog(file, shaderID);
+
+ if ( GL20.glGetShader(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE )
+ ShadersTest.kill("A compilation error occured in a vertex shader.");
+
+ programID = GL20.glCreateProgram();
+
+ GL20.glAttachShader(programID, shaderID);
+ GL20.glLinkProgram(programID);
+
+ printShaderProgramInfoLog(programID);
+
+ if ( GL20.glGetProgram(programID, GL20.GL_LINK_STATUS) == GL11.GL_FALSE )
+ ShadersTest.kill("A linking error occured in a shader program.");
+
+ final String[] uniformNames = { "uniformA", "uniformB" };
+
+ // Get uniform block index and data size
+ final int blockIndex = ARBUniformBufferObject.glGetUniformBlockIndex(programID, "test");
+ final int blockSize = ARBUniformBufferObject.glGetActiveUniformBlock(programID, blockIndex, ARBUniformBufferObject.GL_UNIFORM_BLOCK_DATA_SIZE);
+
+ System.out.println("blockSize = " + blockSize);
+
+ // Create uniform buffer object and allocate a ByteBuffer
+ bufferID = GL15.glGenBuffers();
+ GL15.glBindBuffer(ARBUniformBufferObject.GL_UNIFORM_BUFFER, bufferID);
+ GL15.glBufferData(ARBUniformBufferObject.GL_UNIFORM_BUFFER, blockSize, GL15.GL_DYNAMIC_DRAW);
+ buffer = BufferUtils.createFloatBuffer(blockSize);
+
+ // Attach UBO and associate uniform block to binding point 0
+ ARBUniformBufferObject.glBindBufferBase(ARBUniformBufferObject.GL_UNIFORM_BUFFER, 0, bufferID);
+ ARBUniformBufferObject.glUniformBlockBinding(programID, blockIndex, 0);
+
+ // Get uniform information
+ IntBuffer indexes = BufferUtils.createIntBuffer(uniformNames.length);
+ IntBuffer params = BufferUtils.createIntBuffer(uniformNames.length);
+
+ ARBUniformBufferObject.glGetUniformIndices(programID, uniformNames, indexes);
+ uniformA_index = indexes.get(0);
+ uniformB_index = indexes.get(1);
+
+ ARBUniformBufferObject.glGetActiveUniforms(programID, indexes, ARBUniformBufferObject.GL_UNIFORM_OFFSET, params);
+ uniformA_offset = params.get(0);
+ uniformB_offset = params.get(1);
+
+ System.out.println("\nuniformA index = " + uniformA_index);
+ System.out.println("uniformB index = " + uniformB_index);
+
+ System.out.println("\nuniformA offset = " + uniformA_offset + " - should be 0 for std140");
+ System.out.println("uniformB offset = " + uniformB_offset + " - should be 16 for std140");
+
+ Util.checkGLError();
+ }
+
+ void render() {
+ GL20.glUseProgram(programID);
+
+ //* -- std140 layout
+ // Uniform A
+ buffer.put(0, ShadersTest.getSin()).put(1, ShadersTest.getSpecularity() * 8.0f);
+ // Uniform B - str140 alignment at 16 bytes
+ buffer.put(4, 0.0f).put(5, 0.7f).put(6, 0.0f);
+
+ GL15.glBindBuffer(ARBUniformBufferObject.GL_UNIFORM_BUFFER, bufferID);
+ GL15.glBufferData(ARBUniformBufferObject.GL_UNIFORM_BUFFER, buffer, GL15.GL_DYNAMIC_DRAW);
+ //*/
+
+ /* -- non-std140 layout
+ // Uniform A
+ buffer.put(ShadersTest.getSin()).put(ShadersTest.getSpecularity() * 8.0f);
+ buffer.flip();
+ GL15.glBufferSubData(ARBUniformBufferObject.GL_UNIFORM_BUFFER, uniformA_offset, buffer);
+ // Uniform B
+ buffer.clear();
+ buffer.put(0.0f).put(0.7f).put(0.0f);
+ buffer.flip();
+ GL15.glBufferSubData(ARBUniformBufferObject.GL_UNIFORM_BUFFER, uniformB_offset, buffer);
+ //*/
+
+ ShadersTest.renderObject();
+
+ GL20.glUseProgram(0);
+ }
+
+ void cleanup() {
+ GL15.glDeleteBuffers(bufferID);
+
+ GL20.glDetachShader(programID, shaderID);
+
+ GL20.glDeleteShader(shaderID);
+ GL20.glDeleteProgram(programID);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/ShaderVP.java b/src/java/org/lwjgl/test/opengl/shaders/ShaderVP.java
new file mode 100644
index 0000000..72876be
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/ShaderVP.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+/*
+ * Created by LWJGL.
+ * User: spasi
+ * Date: 2004-03-30
+ * Time: 9:55:38 pm
+ */
+
+package org.lwjgl.test.opengl.shaders;
+
+import org.lwjgl.opengl.ARBProgram;
+import org.lwjgl.opengl.ARBVertexProgram;
+import org.lwjgl.opengl.GL11;
+
+final class ShaderVP extends Shader {
+
+ final String file;
+ final String source;
+
+ final int ID;
+
+ ShaderVP(final String shaderFile) {
+ file = shaderFile;
+ source = getShaderText(shaderFile);
+
+ ID = ARBProgram.glGenProgramsARB();
+
+ ARBProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, ID);
+ ARBProgram.glProgramStringARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, ARBProgram.GL_PROGRAM_FORMAT_ASCII_ARB, source);
+
+ checkProgramError(file, source);
+ }
+
+ void render() {
+ GL11.glEnable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
+ ARBProgram.glBindProgramARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, ID);
+
+ ARBProgram.glProgramLocalParameter4fARB(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB, 0,
+ ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f, 0.0f, 0.0f);
+
+ ShadersTest.renderObject();
+
+ GL11.glDisable(ARBVertexProgram.GL_VERTEX_PROGRAM_ARB);
+ }
+
+ void cleanup() {
+ ARBProgram.glDeleteProgramsARB(ID);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/ShaderVSH.java b/src/java/org/lwjgl/test/opengl/shaders/ShaderVSH.java
new file mode 100644
index 0000000..53fc35e
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/ShaderVSH.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+/*
+ * Created by LWJGL.
+ * User: spasi
+ * Date: 2004-03-30
+ * Time: 9:55:38 pm
+ */
+
+package org.lwjgl.test.opengl.shaders;
+
+import org.lwjgl.opengl.ARBShaderObjects;
+import org.lwjgl.opengl.ARBVertexShader;
+import org.lwjgl.opengl.GL11;
+
+final class ShaderVSH extends Shader {
+
+ final String file;
+ final String source;
+
+ final int shaderID;
+ final int programID;
+
+ final int uniformLocation;
+
+ ShaderVSH(final String shaderFile) {
+ file = shaderFile;
+ source = getShaderText(shaderFile);
+
+ shaderID = ARBShaderObjects.glCreateShaderObjectARB(ARBVertexShader.GL_VERTEX_SHADER_ARB);
+ ARBShaderObjects.glShaderSourceARB(shaderID, source);
+ ARBShaderObjects.glCompileShaderARB(shaderID);
+
+ printShaderObjectInfoLog(file, shaderID);
+
+ if ( ARBShaderObjects.glGetObjectParameteriARB(shaderID, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE )
+ ShadersTest.kill("A compilation error occured in a vertex shader.");
+
+ programID = ARBShaderObjects.glCreateProgramObjectARB();
+
+ ARBShaderObjects.glAttachObjectARB(programID, shaderID);
+ ARBShaderObjects.glLinkProgramARB(programID);
+
+ printShaderProgramInfoLog(programID);
+
+ if ( ARBShaderObjects.glGetObjectParameteriARB(programID, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE )
+ ShadersTest.kill("A linking error occured in a shader program.");
+
+ uniformLocation = getUniformLocation(programID, "UNIFORMS");
+ }
+
+ void render() {
+ ARBShaderObjects.glUseProgramObjectARB(programID);
+
+ ARBShaderObjects.glUniform2fARB(uniformLocation, ShadersTest.getSin(), ShadersTest.getSpecularity() * 8.0f);
+
+ ShadersTest.renderObject();
+
+ ARBShaderObjects.glUseProgramObjectARB(0);
+ }
+
+ void cleanup() {
+ ARBShaderObjects.glDetachObjectARB(programID, shaderID);
+
+ ARBShaderObjects.glDeleteObjectARB(shaderID);
+ ARBShaderObjects.glDeleteObjectARB(programID);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java b/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java
new file mode 100644
index 0000000..4cdb311
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2002-2008 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.
+ */
+/*
+ * Created by LWJGL.
+ * User: spasi
+ * Date: 2004-03-30
+ * Time: 8:41:42 pm
+ */
+
+package org.lwjgl.test.opengl.shaders;
+
+import java.nio.FloatBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.*;
+import org.lwjgl.util.glu.GLU;
+import org.lwjgl.util.glu.Sphere;
+
+public final class ShadersTest {
+
+ private static DisplayMode displayMode;
+
+ private static boolean run = true;
+
+ private static final FloatBuffer vectorBuffer = BufferUtils.createFloatBuffer(4);
+
+ private static Sphere sphere;
+
+ private static Shader shader;
+
+ private static float frameTime;
+
+ private static float angle;
+ private static float sin;
+ private static int specularity = 4;
+
+ private ShadersTest() {
+ }
+
+ public static void main(String[] args) {
+ initialize(args);
+
+ long frameStart;
+ long lastFrameTime = 0;
+
+ while ( run ) {
+ if (!Display.isVisible() )
+ Thread.yield();
+ else {
+ // This is the current frame time.
+ frameStart = Sys.getTime();
+
+ // How many seconds passed since last frame.
+ frameTime = (float)((frameStart - lastFrameTime) / (double)Sys.getTimerResolution());
+
+ lastFrameTime = frameStart;
+
+ //angle += frameTime * 90.0f;
+ angle += 0.1f;
+ sin = (float)Math.sin(Math.toRadians(angle));
+
+ handleIO();
+
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+
+ if ( shader != null )
+ shader.render();
+ else
+ renderObject();
+
+ // Restore camera position.
+ GL11.glPopMatrix();
+ GL11.glPushMatrix();
+ }
+
+ Display.update();
+
+ if ( Display.isCloseRequested() )
+ break;
+ }
+
+ cleanup();
+ System.exit(0);
+ }
+
+ private static void initialize(String[] args) {
+ if ( args.length != 1 )
+ argsError();
+
+ 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), "UNI".equalsIgnoreCase(args[0]) ? new ContextAttribs(3, 1) : null);
+ ShadersTest.displayMode = displayMode;
+ } catch (LWJGLException e) {
+ kill(e.getMessage());
+ }
+
+ final ContextCapabilities caps = GLContext.getCapabilities();
+
+ if ( "NONE".equalsIgnoreCase(args[0]) ) {
+ shader = null;
+ } else if ( "VP".equalsIgnoreCase(args[0]) ) {
+ if ( !caps.GL_ARB_vertex_program )
+ kill("The ARB_vertex_program extension is not supported.");
+
+ shader = new ShaderVP("shaderVP.vp");
+ } else if ( "FP".equalsIgnoreCase(args[0]) ) {
+ if ( !caps.GL_ARB_vertex_program )
+ kill("The ARB_vertex_program extension is not supported.");
+ if ( !caps.GL_ARB_fragment_program )
+ kill("The ARB_fragment_program extension is not supported.");
+
+ shader = new ShaderFP("shaderFP.vp", "shaderFP.fp");
+ } else if ( "VSH".equalsIgnoreCase(args[0]) ) {
+ if ( !caps.GL_ARB_vertex_shader )
+ kill("The ARB_vertex_shader extension is not supported.");
+
+ shader = new ShaderVSH("shaderVSH.vsh");
+ } else if ( "FSH".equalsIgnoreCase(args[0]) ) {
+ if ( !caps.GL_ARB_vertex_shader )
+ kill("The ARB_vertex_shader extension is not supported.");
+ if ( !caps.GL_ARB_fragment_shader )
+ kill("The ARB_fragment_shader extension is not supported.");
+
+ shader = new ShaderFSH("shaderFSH.vsh", "shaderFSH.fsh");
+ } else if ("UNI".equalsIgnoreCase(args[0]) ) {
+ if ( !(caps.OpenGL31 || caps.GL_ARB_uniform_buffer_object) )
+ kill("Neither OpenGL version 3.1 nor ARB_uniform_buffer_object are supported.");
+
+ shader = new ShaderUNI("shaderUNI.vsh");
+ } else {
+ argsError();
+ }
+
+ GL11.glViewport(0, 0, displayMode.getWidth(), displayMode.getHeight());
+
+ GL11.glMatrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadIdentity();
+ GLU.gluPerspective(45, displayMode.getWidth() / (float)displayMode.getHeight(), 1.0f, 10.0f);
+
+ GL11.glMatrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadIdentity();
+
+ // Setup camera position.
+ GL11.glTranslatef(0.0f, 0.0f, -4.0f);
+ GL11.glRotatef(15.0f, 1.0f, 0.0f, 0.0f);
+ GL11.glPushMatrix();
+
+ GL11.glClearDepth(1.0f);
+ GL11.glDepthFunc(GL11.GL_LEQUAL);
+
+ GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
+
+ GL11.glFrontFace(GL11.GL_CCW);
+ GL11.glPolygonMode(GL11.GL_FRONT, GL11.GL_FILL);
+
+ GL11.glCullFace(GL11.GL_BACK);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+
+ GL11.glAlphaFunc(GL11.GL_NOTEQUAL, 0.0f);
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glEnable(GL11.GL_BLEND);
+
+ // Setup lighting for when we have fixed function fragment rendering.
+ GL11.glShadeModel(GL11.GL_SMOOTH);
+
+ if ( shader == null ) {
+ GL11.glEnable(GL11.GL_LIGHTING);
+ GL11.glEnable(GL11.GL_LIGHT0);
+ }
+
+ vectorBuffer.clear();
+ vectorBuffer.put(1.0f).put(1.0f).put(1.0f).put(1.0f);
+ vectorBuffer.clear();
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, vectorBuffer);
+
+ vectorBuffer.put(1.0f).put(1.0f).put(1.0f).put(1.0f);
+ vectorBuffer.clear();
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, vectorBuffer);
+
+ vectorBuffer.put(1.0f).put(1.0f).put(0.5f).put(1.0f);
+ vectorBuffer.clear();
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, vectorBuffer);
+
+ vectorBuffer.put(-1.0f / 3.0f).put(1.0f / 3.0f).put(1.0f / 3.0f).put(0.0f); // Infinite
+ vectorBuffer.clear();
+ GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, vectorBuffer);
+
+ vectorBuffer.put(0.2f).put(0.2f).put(0.2f).put(1.0f);
+ vectorBuffer.clear();
+ GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, vectorBuffer);
+
+ sphere = new Sphere();
+ }
+
+ private static void handleIO() {
+ if ( Keyboard.getNumKeyboardEvents() != 0 ) {
+ while ( Keyboard.next() ) {
+ if ( Keyboard.getEventKeyState() )
+ continue;
+
+ switch ( Keyboard.getEventKey() ) {
+ case Keyboard.KEY_EQUALS:
+ if ( specularity < 8 )
+ specularity++;
+ break;
+ case Keyboard.KEY_MINUS:
+ if ( specularity > 1 )
+ specularity--;
+ break;
+ case Keyboard.KEY_ESCAPE:
+ run = false;
+ break;
+ }
+ }
+ }
+
+ while ( Mouse.next() ) ;
+ }
+
+ static int getDisplayWidth() {
+ return displayMode.getWidth();
+ }
+
+ static int getDisplayHeight() {
+ return displayMode.getHeight();
+ }
+
+ static float getSin() {
+ return sin;
+ }
+
+ static int getSpecularity() {
+ return specularity;
+ }
+
+ static void renderObject() {
+ GL11.glColor3b((byte)255, (byte)255, (byte)255);
+ sphere.draw(1.0f, 32, 32);
+ }
+
+ private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) {
+ DisplayMode bestMode = null;
+
+ for ( int i = 0; i < modes.length; i++ ) {
+ DisplayMode mode = modes[i];
+ if ( mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85 ) {
+ if ( bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) )
+ bestMode = mode;
+ }
+ }
+
+ return bestMode;
+ }
+
+ private static void cleanup() {
+ // This is not necessary, just showing how to properly delete a program/shader.
+ if ( shader != null )
+ shader.cleanup();
+
+ if ( Display.isCreated() )
+ Display.destroy();
+ }
+
+ private static void argsError() {
+ System.out.println("\nInvalid program arguments.");
+ System.out.println("\nUsage: ShadersTest , where argument can be one of the following:\n");
+ System.out.println("none\t- Use fixed function rendering.");
+ System.out.println("vp\t- Use ARB_vertex_program (low-level) only.");
+ System.out.println("vsh\t- Use ARB_vertex_shader (GLSL) only.");
+ System.out.println("fp\t- Use ARB_vertex_program + ARB_fragment_program (low-level).");
+ System.out.println("fsh\t- Use ARB_vertex_shader + ARB_fragment_shader (GLSL).");
+ System.out.println("uni\t- Use ARB_uniform_buffer_object to update shader uniforms (GLSL).");
+
+ cleanup();
+ System.exit(-1);
+ }
+
+ static void kill(String reason) {
+ System.out.println("The ShaderTest program was terminated because an error occured.\n");
+ System.out.println("Reason: " + (reason == null ? "Unknown" : reason));
+
+ cleanup();
+ System.exit(-1);
+ }
+
+ static void kill(String reason, Throwable t) {
+ System.out.println("The ShaderTest program was terminated because an exception occured.\n");
+ System.out.println("Reason: " + reason == null ? "Unknown" : reason);
+
+ System.out.println("Exception message: " + t.getMessage());
+
+ cleanup();
+ System.exit(-1);
+ }
+
+}
diff --git a/src/java/org/lwjgl/test/opengl/shaders/shaderFP.fp b/src/java/org/lwjgl/test/opengl/shaders/shaderFP.fp
new file mode 100644
index 0000000..bf11274
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/shaderFP.fp
@@ -0,0 +1,40 @@
+!!ARBfp1.0
+OPTION ARB_precision_hint_fastest;
+
+ATTRIB winPos = fragment.position;
+ATTRIB iDots = fragment.texcoord[0];
+
+PARAM ambience = state.lightmodel.ambient;
+
+PARAM specularColor = state.light[0].specular;
+
+PARAM UNIFORMS = program.local[0];
+
+TEMP temp;
+
+OUTPUT oColor = result.color;
+
+# Offset window-space fragment position.
+ADD temp.xyz, winPos, UNIFORMS.zwxx;
+# Normalize position.
+DP3 temp.w, temp, temp;
+RSQ temp.w, temp.w;
+MUL temp.xy, temp, temp.w;
+
+# Multiply with current sin.
+MUL temp.xy, temp, UNIFORMS.x;
+# {-1..1} => {0..1}
+MAD temp.xy, temp, 0.5, 0.5;
+# Intensify colors.
+MUL temp.xy, temp, 2.0;
+MOV temp.z, 1.0;
+
+# Accumulate color contributions.
+MAD temp.xyz, iDots.x, temp, ambience;
+# Calculate ^
+POW temp.w, iDots.y, UNIFORMS.y;
+MAD oColor.xyz, temp.w, specularColor, temp;
+
+MOV oColor.w, 1.0;
+
+END
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/shaderFP.vp b/src/java/org/lwjgl/test/opengl/shaders/shaderFP.vp
new file mode 100644
index 0000000..8b14a96
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/shaderFP.vp
@@ -0,0 +1,37 @@
+!!ARBvp1.0
+
+ATTRIB iPos = vertex.position;
+ATTRIB iNormal = vertex.normal;
+
+PARAM mvp[4] = { state.matrix.mvp };
+PARAM mvIT[4] = { state.matrix.modelview.invtrans };
+
+PARAM lightDir = state.light[0].position;
+PARAM halfDir = state.light[0].half;
+
+PARAM UNIFORMS = program.local[0];
+
+TEMP normal, dots;
+
+OUTPUT oPos = result.position;
+OUTPUT oDots = result.texcoord[0];
+
+# Transform the vertex to clip coordinates.
+DP4 oPos.x, mvp[0], iPos;
+DP4 oPos.y, mvp[1], iPos;
+DP4 oPos.z, mvp[2], iPos;
+DP4 oPos.w, mvp[3], iPos;
+
+# Transform the normal to eye coordinates.
+DP3 normal.x, mvIT[0], iNormal;
+DP3 normal.y, mvIT[1], iNormal;
+DP3 normal.z, mvIT[2], iNormal;
+
+# Compute diffuse and specular dot products and clamp them.
+DP3 dots.x, normal, lightDir;
+MAX oDots.x, dots.x, 0.0;
+
+DP3 dots.y, normal, halfDir;
+MAX oDots.y, dots.y, 0.0;
+
+END
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/shaderFSH.fsh b/src/java/org/lwjgl/test/opengl/shaders/shaderFSH.fsh
new file mode 100644
index 0000000..99567c2
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/shaderFSH.fsh
@@ -0,0 +1,21 @@
+uniform vec4 UNIFORMS;
+
+varying vec2 dots;
+
+void main(void) {
+ // Offset window-space fragment position.
+ vec3 color2D = vec3(gl_FragCoord + UNIFORMS.zwxx);
+
+ // Normalize position.
+ // Multiply with current sin.
+ color2D.xy = normalize(color2D).xy * UNIFORMS.x;
+ // {-1..1} => {0..1} & Intensify colors.
+ color2D.xy = (vec2(color2D) * 0.5 + 0.5) * 2.0;
+ color2D.z = 1.0;
+
+ // Accumulate color contributions.
+ // Hardcoded ambience and specular color, due to buggy drivers.
+ color2D = dots.x * color2D + vec3(0.2, 0.2, 0.2);
+ gl_FragColor.rgb = pow(dots.y, UNIFORMS.y) * vec3(1.0, 1.0, 0.5) + color2D;
+ gl_FragColor.a = 1.0;
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/shaderFSH.vsh b/src/java/org/lwjgl/test/opengl/shaders/shaderFSH.vsh
new file mode 100644
index 0000000..4fc5db3
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/shaderFSH.vsh
@@ -0,0 +1,13 @@
+uniform vec4 UNIFORMS;
+
+varying vec2 dots;
+
+void main(void) {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+
+ vec3 normal = gl_NormalMatrix * gl_Normal;
+
+ // Pass the dot products to the fragment shader.
+ dots.x = max(dot(normal, vec3(gl_LightSource[0].position)), 0.0);
+ dots.y = max(dot(normal, vec3(gl_LightSource[0].halfVector)), 0.0);
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/shaderUNI.vsh b/src/java/org/lwjgl/test/opengl/shaders/shaderUNI.vsh
new file mode 100644
index 0000000..d1fbd74
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/shaderUNI.vsh
@@ -0,0 +1,28 @@
+#version 140
+#extension GL_ARB_uniform_buffer_object : enable
+
+layout(std140) uniform test {
+ vec2 uniformA;
+ vec3 uniformB;
+};
+
+void main(void) {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+
+ vec3 normal = gl_NormalMatrix * gl_Normal;
+
+ float diffuseDot = max(dot(normal, vec3(gl_LightSource[0].position)), 0.0);
+ float specularDot = max(dot(normal, vec3(gl_LightSource[0].halfVector)), 0.0);
+ specularDot = pow(specularDot, uniformA.y);
+
+ // Normalize position, to get a {-1..1} value for each vertex.
+ // Multiply with current sin.
+ vec3 color3D = normalize(vec3(gl_Vertex)) * uniformA.x;
+ // {-1..1} => {0..1} & Intensify colors.
+ color3D = (color3D * 0.5 + 0.5) * 2.0;
+
+ // Accumulate color contributions.
+ color3D = diffuseDot * (uniformB + color3D) + vec3(gl_LightModel.ambient);
+ gl_FrontColor.rgb = specularDot * vec3(gl_LightSource[0].specular) + color3D;
+ gl_FrontColor.a = 1.0;
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/shaderVP.vp b/src/java/org/lwjgl/test/opengl/shaders/shaderVP.vp
new file mode 100644
index 0000000..a410222
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/shaderVP.vp
@@ -0,0 +1,59 @@
+!!ARBvp1.0
+
+ATTRIB iPos = vertex.position;
+ATTRIB iNormal = vertex.normal;
+
+PARAM mvp[4] = { state.matrix.mvp };
+PARAM mvIT[4] = { state.matrix.modelview.invtrans };
+
+PARAM ambience = state.lightmodel.ambient;
+
+PARAM lightDir = state.light[0].position;
+PARAM halfDir = state.light[0].half;
+PARAM diffuseColor = state.light[0].diffuse;
+PARAM specularColor = state.light[0].specular;
+
+PARAM UNIFORMS = program.local[0];
+
+TEMP temp, temp2, normal, dots;
+
+OUTPUT oPos = result.position;
+OUTPUT oColor = result.color;
+
+# Transform the vertex to clip coordinates.
+DP4 oPos.x, mvp[0], iPos;
+DP4 oPos.y, mvp[1], iPos;
+DP4 oPos.z, mvp[2], iPos;
+DP4 oPos.w, mvp[3], iPos;
+
+# Transform the normal to eye coordinates.
+DP3 normal.x, mvIT[0], iNormal;
+DP3 normal.y, mvIT[1], iNormal;
+DP3 normal.z, mvIT[2], iNormal;
+
+# Compute diffuse and specular dot products and use LIT to compute
+# lighting coefficients.
+DP3 dots.x, normal, lightDir;
+DP3 dots.y, normal, halfDir;
+MOV dots.w, UNIFORMS.y;
+LIT dots, dots;
+
+# Normalize position, to get a {-1..1} value for each vertex.
+DP3 temp.w, iPos, iPos;
+RSQ temp.w, temp.w;
+MUL temp.xyz, iPos, temp.w;
+
+# Multiply with current sin.
+MUL temp.xyz, temp, UNIFORMS.x;
+# {-1..1} => {0..1}
+MAD temp.xyz, temp, 0.5, 0.5;
+# Intensify colors.
+MUL temp.xyz, temp, 2.0;
+
+# Accumulate color contributions.
+MAD temp.xyz, dots.y, temp, ambience;
+MAD oColor.xyz, dots.z, specularColor, temp;
+MOV oColor.w, 1.0;
+
+
+END
\ No newline at end of file
diff --git a/src/java/org/lwjgl/test/opengl/shaders/shaderVSH.vsh b/src/java/org/lwjgl/test/opengl/shaders/shaderVSH.vsh
new file mode 100644
index 0000000..c34ae1b
--- /dev/null
+++ b/src/java/org/lwjgl/test/opengl/shaders/shaderVSH.vsh
@@ -0,0 +1,22 @@
+uniform vec2 UNIFORMS;
+
+void main(void) {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+
+ vec3 normal = gl_NormalMatrix * gl_Normal;
+
+ float diffuseDot = max(dot(normal, vec3(gl_LightSource[0].position)), 0.0);
+ float specularDot = max(dot(normal, vec3(gl_LightSource[0].halfVector)), 0.0);
+ specularDot = pow(specularDot, UNIFORMS.y);
+
+ // Normalize position, to get a {-1..1} value for each vertex.
+ // Multiply with current sin.
+ vec3 color3D = normalize(vec3(gl_Vertex)) * UNIFORMS.x;
+ // {-1..1} => {0..1} & Intensify colors.
+ color3D = (color3D * 0.5 + 0.5) * 2.0;
+
+ // Accumulate color contributions.
+ color3D = diffuseDot * color3D + vec3(gl_LightModel.ambient);
+ gl_FrontColor.rgb = specularDot * vec3(gl_LightSource[0].specular) + color3D;
+ gl_FrontColor.a = 1.0;
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/Color.java b/src/java/org/lwjgl/util/Color.java
new file mode 100644
index 0000000..87e5ab0
--- /dev/null
+++ b/src/java/org/lwjgl/util/Color.java
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+/**
+ * A mutable Color class
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: Color.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public final class Color implements ReadableColor, Serializable, WritableColor {
+
+ static final long serialVersionUID = 1L;
+
+ /** Color components, publicly accessible */
+ private byte red, green, blue, alpha;
+
+ /**
+ * Constructor for Color.
+ */
+ public Color() {
+ this(0, 0, 0, 255);
+ }
+
+ /**
+ * Constructor for Color. Alpha defaults to 255.
+ */
+ public Color(int r, int g, int b) {
+ this(r, g, b, 255);
+ }
+
+ /**
+ * Constructor for Color. Alpha defaults to 255.
+ */
+ public Color(byte r, byte g, byte b) {
+ this(r, g, b, (byte) 255);
+ }
+
+ /**
+ * Constructor for Color.
+ */
+ public Color(int r, int g, int b, int a) {
+ set(r, g, b, a);
+ }
+
+ /**
+ * Constructor for Color.
+ */
+ public Color(byte r, byte g, byte b, byte a) {
+ set(r, g, b, a);
+ }
+
+ /**
+ * Constructor for Color
+ */
+ public Color(ReadableColor c) {
+ setColor(c);
+ }
+
+ /**
+ * Set a color
+ */
+ public void set(int r, int g, int b, int a) {
+ red = (byte) r;
+ green = (byte) g;
+ blue = (byte) b;
+ alpha = (byte) a;
+ }
+
+ /**
+ * Set a color
+ */
+ public void set(byte r, byte g, byte b, byte a) {
+ this.red = r;
+ this.green = g;
+ this.blue = b;
+ this.alpha = a;
+ }
+
+ /**
+ * Set a color
+ */
+ public void set(int r, int g, int b) {
+ set(r, g, b, 255);
+ }
+
+ /**
+ * Set a color
+ */
+ public void set(byte r, byte g, byte b) {
+ set(r, g, b, (byte) 255);
+ }
+
+ /**
+ * Accessor
+ */
+ public int getRed() {
+ return red & 0xFF;
+ }
+
+ /**
+ * Accessor
+ */
+ public int getGreen() {
+ return green & 0xFF;
+ }
+
+ /**
+ * Accessor
+ */
+ public int getBlue() {
+ return blue & 0xFF;
+ }
+
+ /**
+ * Accessor
+ */
+ public int getAlpha() {
+ return alpha & 0xFF;
+ }
+
+ /**
+ * Set the Red component
+ */
+ public void setRed(int red) {
+ this.red = (byte) red;
+ }
+
+ /**
+ * Set the Green component
+ */
+ public void setGreen(int green) {
+ this.green = (byte) green;
+ }
+
+ /**
+ * Set the Blue component
+ */
+ public void setBlue(int blue) {
+ this.blue = (byte) blue;
+ }
+
+ /**
+ * Set the Alpha component
+ */
+ public void setAlpha(int alpha) {
+ this.alpha = (byte) alpha;
+ }
+
+ /**
+ * Set the Red component
+ */
+ public void setRed(byte red) {
+ this.red = red;
+ }
+
+ /**
+ * Set the Green component
+ */
+ public void setGreen(byte green) {
+ this.green = green;
+ }
+
+ /**
+ * Set the Blue component
+ */
+ public void setBlue(byte blue) {
+ this.blue = blue;
+ }
+
+ /**
+ * Set the Alpha component
+ */
+ public void setAlpha(byte alpha) {
+ this.alpha = alpha;
+ }
+
+ /**
+ * Stringify
+ */
+ public String toString() {
+ return "Color [" + getRed() + ", " + getGreen() + ", " + getBlue() + ", " + getAlpha() + "]";
+ }
+
+ /**
+ * Equals
+ */
+ public boolean equals(Object o) {
+ return (o != null)
+ && (o instanceof ReadableColor)
+ && (((ReadableColor) o).getRed() == this.getRed())
+ && (((ReadableColor) o).getGreen() == this.getGreen())
+ && (((ReadableColor) o).getBlue() == this.getBlue())
+ && (((ReadableColor) o).getAlpha() == this.getAlpha());
+ }
+
+ /**
+ * Hashcode
+ */
+ public int hashCode() {
+ return (red << 24) | (green << 16) | (blue << 8) | alpha;
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#getAlphaByte()
+ */
+ public byte getAlphaByte() {
+ return alpha;
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#getBlueByte()
+ */
+ public byte getBlueByte() {
+ return blue;
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#getGreenByte()
+ */
+ public byte getGreenByte() {
+ return green;
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#getRedByte()
+ */
+ public byte getRedByte() {
+ return red;
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#writeRGBA(java.nio.ByteBuffer)
+ */
+ public void writeRGBA(ByteBuffer dest) {
+ dest.put(red);
+ dest.put(green);
+ dest.put(blue);
+ dest.put(alpha);
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#writeRGB(java.nio.ByteBuffer)
+ */
+ public void writeRGB(ByteBuffer dest) {
+ dest.put(red);
+ dest.put(green);
+ dest.put(blue);
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#writeABGR(java.nio.ByteBuffer)
+ */
+ public void writeABGR(ByteBuffer dest) {
+ dest.put(alpha);
+ dest.put(blue);
+ dest.put(green);
+ dest.put(red);
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#writeARGB(java.nio.ByteBuffer)
+ */
+ public void writeARGB(ByteBuffer dest) {
+ dest.put(alpha);
+ dest.put(red);
+ dest.put(green);
+ dest.put(blue);
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#writeBGR(java.nio.ByteBuffer)
+ */
+ public void writeBGR(ByteBuffer dest) {
+ dest.put(blue);
+ dest.put(green);
+ dest.put(red);
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableColor#writeBGRA(java.nio.ByteBuffer)
+ */
+ public void writeBGRA(ByteBuffer dest) {
+ dest.put(blue);
+ dest.put(green);
+ dest.put(red);
+ dest.put(alpha);
+ }
+
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readRGBA(ByteBuffer src) {
+ red = src.get();
+ green = src.get();
+ blue = src.get();
+ alpha = src.get();
+ }
+
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readRGB(ByteBuffer src) {
+ red = src.get();
+ green = src.get();
+ blue = src.get();
+ }
+
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readARGB(ByteBuffer src) {
+ alpha = src.get();
+ red = src.get();
+ green = src.get();
+ blue = src.get();
+ }
+
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readBGRA(ByteBuffer src) {
+ blue = src.get();
+ green = src.get();
+ red = src.get();
+ alpha = src.get();
+ }
+
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readBGR(ByteBuffer src) {
+ blue = src.get();
+ green = src.get();
+ red = src.get();
+ }
+
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readABGR(ByteBuffer src) {
+ alpha = src.get();
+ blue = src.get();
+ green = src.get();
+ red = src.get();
+ }
+
+ /**
+ * Set this color's color by copying another color
+ * @param src The source color
+ */
+ public void setColor(ReadableColor src) {
+ red = src.getRedByte();
+ green = src.getGreenByte();
+ blue = src.getBlueByte();
+ alpha = src.getAlphaByte();
+ }
+
+ /**
+ * HSB to RGB conversion, pinched from java.awt.Color.
+ * @param hue (0..1.0f)
+ * @param saturation (0..1.0f)
+ * @param brightness (0..1.0f)
+ */
+ public void fromHSB(float hue, float saturation, float brightness) {
+ if (saturation == 0.0F) {
+ red = green = blue = (byte) (brightness * 255F + 0.5F);
+ } else {
+ float f3 = (hue - (float) Math.floor(hue)) * 6F;
+ float f4 = f3 - (float) Math.floor(f3);
+ float f5 = brightness * (1.0F - saturation);
+ float f6 = brightness * (1.0F - saturation * f4);
+ float f7 = brightness * (1.0F - saturation * (1.0F - f4));
+ switch ((int) f3) {
+ case 0 :
+ red = (byte) (brightness * 255F + 0.5F);
+ green = (byte) (f7 * 255F + 0.5F);
+ blue = (byte) (f5 * 255F + 0.5F);
+ break;
+ case 1 :
+ red = (byte) (f6 * 255F + 0.5F);
+ green = (byte) (brightness * 255F + 0.5F);
+ blue = (byte) (f5 * 255F + 0.5F);
+ break;
+ case 2 :
+ red = (byte) (f5 * 255F + 0.5F);
+ green = (byte) (brightness * 255F + 0.5F);
+ blue = (byte) (f7 * 255F + 0.5F);
+ break;
+ case 3 :
+ red = (byte) (f5 * 255F + 0.5F);
+ green = (byte) (f6 * 255F + 0.5F);
+ blue = (byte) (brightness * 255F + 0.5F);
+ break;
+ case 4 :
+ red = (byte) (f7 * 255F + 0.5F);
+ green = (byte) (f5 * 255F + 0.5F);
+ blue = (byte) (brightness * 255F + 0.5F);
+ break;
+ case 5 :
+ red = (byte) (brightness * 255F + 0.5F);
+ green = (byte) (f5 * 255F + 0.5F);
+ blue = (byte) (f6 * 255F + 0.5F);
+ break;
+ }
+ }
+ }
+
+ /**
+ * RGB to HSB conversion, pinched from java.awt.Color.
+ * The HSB value is returned in dest[] if dest[] is supplied.
+ * Values range from 0..1
+ * @param dest Destination floats, or null
+ * @return dest, or a new float array
+ */
+ public float[] toHSB(float dest[]) {
+ int r = getRed();
+ int g = getGreen();
+ int b = getBlue();
+ if (dest == null)
+ dest = new float[3];
+ int l = r <= g ? g : r;
+ if (b > l)
+ l = b;
+ int i1 = r >= g ? g : r;
+ if (b < i1)
+ i1 = b;
+ float brightness = l / 255F;
+ float saturation;
+ if (l != 0)
+ saturation = (float) (l - i1) / (float) l;
+ else
+ saturation = 0.0F;
+ float hue;
+ if (saturation == 0.0F) {
+ hue = 0.0F;
+ } else {
+ float f3 = (float) (l - r) / (float) (l - i1);
+ float f4 = (float) (l - g) / (float) (l - i1);
+ float f5 = (float) (l - b) / (float) (l - i1);
+ if (r == l)
+ hue = f5 - f4;
+ else if (g == l)
+ hue = (2.0F + f3) - f5;
+ else
+ hue = (4F + f4) - f3;
+ hue /= 6F;
+ if (hue < 0.0F)
+ hue++;
+ }
+ dest[0] = hue;
+ dest[1] = saturation;
+ dest[2] = brightness;
+ return dest;
+ }
+
+}
diff --git a/src/java/org/lwjgl/util/Dimension.java b/src/java/org/lwjgl/util/Dimension.java
new file mode 100644
index 0000000..a77b253
--- /dev/null
+++ b/src/java/org/lwjgl/util/Dimension.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import java.io.Serializable;
+
+/**
+ * A 2D integer Dimension class, which looks remarkably like an AWT one.
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: Dimension.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public final class Dimension implements Serializable, ReadableDimension, WritableDimension {
+
+ static final long serialVersionUID = 1L;
+
+ /** The dimensions! */
+ private int width, height;
+
+ /**
+ * Constructor for Dimension.
+ */
+ public Dimension() {
+ super();
+ }
+
+ /**
+ * Constructor for Dimension.
+ */
+ public Dimension(int w, int h) {
+ this.width = w;
+ this.height = h;
+ }
+
+ /**
+ * Constructor for Dimension.
+ */
+ public Dimension(ReadableDimension d) {
+ setSize(d);
+ }
+
+ public void setSize(int w, int h) {
+ this.width = w;
+ this.height = h;
+ }
+
+ public void setSize(ReadableDimension d) {
+ this.width = d.getWidth();
+ this.height = d.getHeight();
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableDimension#getSize(com.shavenpuppy.jglib.Dimension)
+ */
+ public void getSize(WritableDimension dest) {
+ dest.setSize(this);
+ }
+
+ /**
+ * Checks whether two dimension objects have equal values.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof ReadableDimension) {
+ ReadableDimension d = (ReadableDimension) obj;
+ return (width == d.getWidth()) && (height == d.getHeight());
+ }
+ return false;
+ }
+
+ /**
+ * Returns the hash code for this Dimension
.
+ *
+ * @return a hash code for this Dimension
+ */
+ public int hashCode() {
+ int sum = width + height;
+ return sum * (sum + 1) / 2 + width;
+ }
+
+ /**
+ * Returns a string representation of the values of this
+ * Dimension
object's height
and
+ * width
fields. This method is intended to be used only
+ * for debugging purposes, and the content and format of the returned
+ * string may vary between implementations. The returned string may be
+ * empty but may not be null
.
+ *
+ * @return a string representation of this Dimension
+ * object
+ */
+ public String toString() {
+ return getClass().getName() + "[width=" + width + ",height=" + height + "]";
+ }
+
+ /**
+ * Gets the height.
+ * @return Returns a int
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the height.
+ * @param height The height to set
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * Gets the width.
+ * @return Returns a int
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the width.
+ * @param width The width to set
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+}
diff --git a/src/java/org/lwjgl/util/Display.java b/src/java/org/lwjgl/util/Display.java
new file mode 100644
index 0000000..a340639
--- /dev/null
+++ b/src/java/org/lwjgl/util/Display.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.opengl.DisplayMode;
+
+/**
+ * Display initialization utility, that can be used to find display modes and pick
+ * one for you based on your criteria.
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: Display.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public final class Display {
+
+ private static final boolean DEBUG = false;
+
+ /**
+ * Determine the available display modes that match the specified minimum and maximum criteria.
+ * If any given criterium is specified as -1 then it is ignored.
+ *
+ * @param minWidth the minimum display resolution in pixels
+ * @param minHeight the minimum display resolution in pixels
+ * @param maxWidth the maximum display resolution in pixels
+ * @param maxHeight the maximum display resolution in pixels
+ * @param minBPP the minimum bit depth per pixel
+ * @param maxBPP the maximum bit depth per pixel
+ * @param minFreq the minimum display frequency in Hz
+ * @param maxFreq the maximum display frequency in Hz
+ * @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) throws LWJGLException
+ {
+ // First get the available display modes
+ DisplayMode[] modes = org.lwjgl.opengl.Display.getAvailableDisplayModes();
+
+ if (LWJGLUtil.DEBUG || DEBUG) {
+ System.out.println("Available screen modes:");
+ for (int i = 0; i < modes.length; i ++) {
+ System.out.println(modes[i]);
+ }
+ }
+
+ ArrayList matches = new ArrayList(modes.length);
+
+ for (int i = 0; i < modes.length; i ++) {
+ assert modes[i] != null : ""+i+" "+modes.length;
+ if (minWidth != -1 && modes[i].getWidth() < minWidth)
+ continue;
+ if (maxWidth != -1 && modes[i].getWidth() > maxWidth)
+ continue;
+ if (minHeight != -1 && modes[i].getHeight() < minHeight)
+ continue;
+ if (maxHeight != -1 && modes[i].getHeight() > maxHeight)
+ continue;
+ if (minBPP != -1 && modes[i].getBitsPerPixel() < minBPP)
+ continue;
+ if (maxBPP != -1 && modes[i].getBitsPerPixel() > maxBPP)
+ continue;
+ //if (modes[i].bpp == 24)
+ // continue;
+ if (modes[i].getFrequency() != 0) {
+ if (minFreq != -1 && modes[i].getFrequency() < minFreq)
+ continue;
+ if (maxFreq != -1 && modes[i].getFrequency() > maxFreq)
+ continue;
+ }
+ matches.add(modes[i]);
+ }
+
+ DisplayMode[] ret = new DisplayMode[matches.size()];
+ matches.toArray(ret);
+ if (LWJGLUtil.DEBUG && DEBUG) {
+ System.out.println("Filtered screen modes:");
+ for (int i = 0; i < ret.length; i ++) {
+ System.out.println(ret[i]);
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Create the display by choosing from a list of display modes based on an order of preference.
+ * You must supply a list of allowable display modes, probably by calling getAvailableDisplayModes(),
+ * and an array with the order in which you would like them sorted in descending order.
+ * This method attempts to create the topmost display mode; if that fails, it will try the next one,
+ * and so on, until there are no modes left. If no mode is set at the end, an exception is thrown.
+ * @param dm a list of display modes to choose from
+ * @param param the names of the DisplayMode fields in the order in which you would like them sorted.
+ * @return the chosen display mode
+ * @throws NoSuchFieldException if one of the params is not a field in DisplayMode
+ * @throws Exception if no display mode could be set
+ * @see org.lwjgl.opengl.DisplayMode
+ */
+ public static DisplayMode setDisplayMode(DisplayMode[] dm, final String[] param) throws Exception {
+
+ class FieldAccessor {
+ final String fieldName;
+ final int order;
+ final int preferred;
+ final boolean usePreferred;
+ FieldAccessor(String fieldName, int order, int preferred, boolean usePreferred) {
+ this.fieldName = fieldName;
+ this.order = order;
+ this.preferred = preferred;
+ this.usePreferred = usePreferred;
+ }
+ int getInt(DisplayMode mode) {
+ if ("width".equals(fieldName)) {
+ return mode.getWidth();
+ }
+ if ("height".equals(fieldName)) {
+ return mode.getHeight();
+ }
+ if ("freq".equals(fieldName)) {
+ return mode.getFrequency();
+ }
+ if ("bpp".equals(fieldName)) {
+ return mode.getBitsPerPixel();
+ }
+ throw new IllegalArgumentException("Unknown field "+fieldName);
+ }
+ }
+
+ class Sorter implements Comparator {
+
+ final FieldAccessor[] field;
+
+ Sorter() {
+ field = new FieldAccessor[param.length];
+ for (int i = 0; i < field.length; i ++) {
+ int idx = param[i].indexOf('=');
+ if (idx > 0) {
+ field[i] = new FieldAccessor(param[i].substring(0, idx), 0, Integer.parseInt(param[i].substring(idx + 1, param[i].length())), true);
+ } else if (param[i].charAt(0) == '-') {
+ field[i] = new FieldAccessor(param[i].substring(1), -1, 0, false);
+ } else {
+ field[i] = new FieldAccessor(param[i], 1, 0, false);
+ }
+ }
+ }
+
+ /**
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ */
+ public int compare(Object o1, Object o2) {
+ DisplayMode dm1 = (DisplayMode) o1;
+ DisplayMode dm2 = (DisplayMode) o2;
+
+ for (int i = 0; i < field.length; i ++) {
+ int f1 = field[i].getInt(dm1);
+ int f2 = field[i].getInt(dm2);
+
+ if (field[i].usePreferred && f1 != f2) {
+ if (f1 == field[i].preferred)
+ return -1;
+ else if (f2 == field[i].preferred)
+ return 1;
+ else {
+ // Score according to the difference between the values
+ int absf1 = Math.abs(f1 - field[i].preferred);
+ int absf2 = Math.abs(f2 - field[i].preferred);
+ if (absf1 < absf2)
+ return -1;
+ else if (absf1 > absf2)
+ return 1;
+ else
+ continue;
+ }
+ } else if (f1 < f2)
+ return field[i].order;
+ else if (f1 == f2)
+ continue;
+ else
+ return -field[i].order;
+ }
+
+ return 0;
+ }
+ }
+
+ // Sort the display modes
+ Arrays.sort(dm, new Sorter());
+
+ // Try them out in the appropriate order
+ if (LWJGLUtil.DEBUG || DEBUG) {
+ System.out.println("Sorted display modes:");
+ for (int i = 0; i < dm.length; i ++) {
+ System.out.println(dm[i]);
+ }
+ }
+ for (int i = 0; i < dm.length; i ++) {
+ try {
+ if (LWJGLUtil.DEBUG || DEBUG)
+ System.out.println("Attempting to set displaymode: "+dm[i]);
+ org.lwjgl.opengl.Display.setDisplayMode(dm[i]);
+ return dm[i];
+ } catch (Exception e) {
+ if (LWJGLUtil.DEBUG || DEBUG) {
+ System.out.println("Failed to set display mode to "+dm[i]);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ throw new Exception("Failed to set display mode.");
+ }
+
+}
diff --git a/src/java/org/lwjgl/util/Point.java b/src/java/org/lwjgl/util/Point.java
new file mode 100644
index 0000000..c9ccb8e
--- /dev/null
+++ b/src/java/org/lwjgl/util/Point.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import java.io.Serializable;
+
+/**
+ * A 2D integer point class, which looks remarkably like an AWT one.
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: Point.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public final class Point implements ReadablePoint, WritablePoint, Serializable {
+
+ static final long serialVersionUID = 1L;
+
+ /** The location */
+ private int x, y;
+
+ /**
+ * Constructor for Point.
+ */
+ public Point() {
+ super();
+ }
+
+ /**
+ * Constructor for Point.
+ */
+ public Point(int x, int y) {
+ setLocation(x, y);
+ }
+
+ /**
+ * Constructor for Point.
+ */
+ public Point(ReadablePoint p) {
+ setLocation(p);
+ }
+
+ public void setLocation(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public void setLocation(ReadablePoint p) {
+ this.x = p.getX();
+ this.y = p.getY();
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ /**
+ * Translate a point.
+ * @param dx The translation to apply
+ * @param dy The translation to apply
+ */
+ public void translate(int dx, int dy) {
+ this.x += dx;
+ this.y += dy;
+ }
+
+ /**
+ * Translate a point.
+ * @param p The translation to apply
+ */
+ public void translate(ReadablePoint p) {
+ this.x += p.getX();
+ this.y += p.getY();
+ }
+
+ /**
+ * Un-translate a point.
+ * @param p The translation to apply
+ */
+ public void untranslate(ReadablePoint p) {
+ this.x -= p.getX();
+ this.y -= p.getY();
+ }
+
+ /**
+ * Determines whether an instance of Point2D
is equal
+ * to this point. Two instances of Point2D
are equal if
+ * the values of their x
and y
member
+ * fields, representing their position in the coordinate space, are
+ * the same.
+ * @param obj an object to be compared with this point
+ * @return true
if the object to be compared is
+ * an instance of Point
and has
+ * the same values; false
otherwise
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof Point) {
+ Point pt = (Point) obj;
+ return (x == pt.x) && (y == pt.y);
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Returns a string representation of this point and its location
+ * in the (x, y) coordinate space. This method is
+ * intended to be used only for debugging purposes, and the content
+ * and format of the returned string may vary between implementations.
+ * The returned string may be empty but may not be null
.
+ *
+ * @return a string representation of this point
+ */
+ public String toString() {
+ return getClass().getName() + "[x=" + x + ",y=" + y + "]";
+ }
+
+ /**
+ * Returns the hash code for this Point
.
+ *
+ * @return a hash code for this Point
+ */
+ public int hashCode() {
+ int sum = x + y;
+ return sum * (sum + 1) / 2 + x;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public void getLocation(WritablePoint dest) {
+ dest.setLocation(x, y);
+ }
+
+}
diff --git a/src/java/org/lwjgl/util/ReadableColor.java b/src/java/org/lwjgl/util/ReadableColor.java
new file mode 100644
index 0000000..8127d45
--- /dev/null
+++ b/src/java/org/lwjgl/util/ReadableColor.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Readonly interface for Colors
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: ReadableColor.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface ReadableColor {
+
+ /**
+ * Return the red component (0..255)
+ * @return int
+ */
+ public int getRed();
+
+ /**
+ * Return the red component (0..255)
+ * @return int
+ */
+ public int getGreen();
+
+ /**
+ * Return the red component (0..255)
+ * @return int
+ */
+ public int getBlue();
+
+ /**
+ * Return the red component (0..255)
+ * @return int
+ */
+ public int getAlpha();
+
+ /**
+ * Return the red component
+ * @return int
+ */
+ public byte getRedByte();
+
+ /**
+ * Return the red component
+ * @return int
+ */
+ public byte getGreenByte();
+
+ /**
+ * Return the red component
+ * @return int
+ */
+ public byte getBlueByte();
+
+ /**
+ * Return the red component
+ * @return int
+ */
+ public byte getAlphaByte();
+
+ /**
+ * Write the RGBA color directly out to a ByteBuffer
+ * @param dest the buffer to write to
+ */
+ public void writeRGBA(ByteBuffer dest);
+
+ /**
+ * Write the RGB color directly out to a ByteBuffer
+ * @param dest the buffer to write to
+ */
+ public void writeRGB(ByteBuffer dest);
+
+ /**
+ * Write the ABGR color directly out to a ByteBuffer
+ * @param dest the buffer to write to
+ */
+ public void writeABGR(ByteBuffer dest);
+
+ /**
+ * Write the BGR color directly out to a ByteBuffer
+ * @param dest the buffer to write to
+ */
+ public void writeBGR(ByteBuffer dest);
+
+ /**
+ * Write the BGRA color directly out to a ByteBuffer
+ * @param dest the buffer to write to
+ */
+ public void writeBGRA(ByteBuffer dest);
+
+ /**
+ * Write the ARGB color directly out to a ByteBuffer
+ * @param dest the buffer to write to
+ */
+ public void writeARGB(ByteBuffer dest);
+
+ /*
+ * Some standard colors
+ */
+ public static final ReadableColor RED = new Color(255, 0, 0);
+ public static final ReadableColor ORANGE = new Color(255, 128, 0);
+ public static final ReadableColor YELLOW = new Color(255, 255, 0);
+ public static final ReadableColor GREEN = new Color(0, 255, 0);
+ public static final ReadableColor CYAN = new Color(0, 255, 255);
+ public static final ReadableColor BLUE = new Color(0, 0, 255);
+ public static final ReadableColor PURPLE = new Color(255, 0, 255);
+ public static final ReadableColor WHITE = new Color(255, 255, 255);
+ public static final ReadableColor BLACK = new Color(0, 0, 0);
+ public static final ReadableColor LTGREY = new Color(192, 192, 192);
+ public static final ReadableColor DKGREY = new Color(64, 64, 64);
+ public static final ReadableColor GREY = new Color(128, 128, 128);
+
+
+
+}
diff --git a/src/java/org/lwjgl/util/ReadableDimension.java b/src/java/org/lwjgl/util/ReadableDimension.java
new file mode 100644
index 0000000..251be8c
--- /dev/null
+++ b/src/java/org/lwjgl/util/ReadableDimension.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+/**
+ * Readonly interface for Dimensions
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: ReadableDimension.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface ReadableDimension {
+
+ /**
+ * Get the width
+ * @return int
+ */
+ public int getWidth();
+
+ /**
+ * Get the height
+ * @return int
+ */
+ public int getHeight();
+
+ /**
+ * Copy this ReadableDimension into a destination Dimension
+ * @param dest The destination
+ */
+ public void getSize(WritableDimension dest);
+
+}
diff --git a/src/java/org/lwjgl/util/ReadablePoint.java b/src/java/org/lwjgl/util/ReadablePoint.java
new file mode 100644
index 0000000..4dea341
--- /dev/null
+++ b/src/java/org/lwjgl/util/ReadablePoint.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+/**
+ * Readonly interface for Points
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: ReadablePoint.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface ReadablePoint {
+
+ /**
+ * @return int
+ */
+ public int getX();
+
+ /**
+ * @return int
+ */
+ public int getY();
+
+ /**
+ * Copy this ReadablePoint into a destination Point
+ * @param dest The destination Point, or null, to create a new Point
+ */
+ public void getLocation(WritablePoint dest);
+}
diff --git a/src/java/org/lwjgl/util/ReadableRectangle.java b/src/java/org/lwjgl/util/ReadableRectangle.java
new file mode 100644
index 0000000..6e8fb32
--- /dev/null
+++ b/src/java/org/lwjgl/util/ReadableRectangle.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+/**
+ * Readonly interface for Rectangles
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: ReadableRectangle.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface ReadableRectangle extends ReadableDimension, ReadablePoint {
+
+ /**
+ * Copy this readable rectangle's bounds into a destination Rectangle
+ * @param dest The destination Rectangle, or null, to create a new Rectangle
+ */
+ public void getBounds(WritableRectangle dest);
+
+}
diff --git a/src/java/org/lwjgl/util/Rectangle.java b/src/java/org/lwjgl/util/Rectangle.java
new file mode 100644
index 0000000..357fbf6
--- /dev/null
+++ b/src/java/org/lwjgl/util/Rectangle.java
@@ -0,0 +1,581 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import java.io.Serializable;
+
+/**
+ * A 2D integer Rectangle class which looks remarkably like an AWT one.
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: Rectangle.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public final class Rectangle implements ReadableRectangle, WritableRectangle, Serializable {
+
+ static final long serialVersionUID = 1L;
+
+ /** Rectangle's bounds */
+ private int x, y, width, height;
+
+ /**
+ * Constructor for Rectangle.
+ */
+ public Rectangle() {
+ super();
+ }
+ /**
+ * Constructor for Rectangle.
+ */
+ public Rectangle(int x, int y, int w, int h) {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ }
+ /**
+ * Constructor for Rectangle.
+ */
+ public Rectangle(ReadablePoint p, ReadableDimension d) {
+ x = p.getX();
+ y = p.getY();
+ width = d.getWidth();
+ height = d.getHeight();
+ }
+ /**
+ * Constructor for Rectangle.
+ */
+ public Rectangle(ReadableRectangle r) {
+ x = r.getX();
+ y = r.getY();
+ width = r.getWidth();
+ height = r.getHeight();
+ }
+
+ public void setLocation(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public void setLocation(ReadablePoint p) {
+ this.x = p.getX();
+ this.y = p.getY();
+ }
+
+ public void setSize(int w, int h) {
+ this.width = w;
+ this.height = h;
+ }
+
+ public void setSize(ReadableDimension d) {
+ this.width = d.getWidth();
+ this.height = d.getHeight();
+ }
+
+ public void setBounds(int x, int y, int w, int h) {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ }
+
+ public void setBounds(ReadablePoint p, ReadableDimension d) {
+ x = p.getX();
+ y = p.getY();
+ width = d.getWidth();
+ height = d.getHeight();
+ }
+
+ public void setBounds(ReadableRectangle r) {
+ x = r.getX();
+ y = r.getY();
+ width = r.getWidth();
+ height = r.getHeight();
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableRectangle#getBounds(com.shavenpuppy.jglib.Rectangle)
+ */
+ public void getBounds(WritableRectangle dest) {
+ dest.setBounds(x, y, width, height);
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadablePoint#getLocation(com.shavenpuppy.jglib.Point)
+ */
+ public void getLocation(WritablePoint dest) {
+ dest.setLocation(x, y);
+ }
+
+ /* (Overrides)
+ * @see com.shavenpuppy.jglib.ReadableDimension#getSize(com.shavenpuppy.jglib.Dimension)
+ */
+ public void getSize(WritableDimension dest) {
+ dest.setSize(width, height);
+ }
+
+ /**
+ * Translate the rectangle by an amount.
+ * @param x The translation amount on the x axis
+ * @param y The translation amount on the y axis
+ */
+ public void translate(int x, int y) {
+ this.x += x;
+ this.y += y;
+ }
+
+ /**
+ * Translate the rectangle by an amount.
+ * @param point The translation amount
+ */
+ public void translate(ReadablePoint point) {
+ this.x += point.getX();
+ this.y += point.getY();
+ }
+
+ /**
+ * Un-translate the rectangle by an amount.
+ * @param point The translation amount
+ */
+ public void untranslate(ReadablePoint point) {
+ this.x -= point.getX();
+ this.y -= point.getY();
+ }
+
+ /**
+ * Checks whether or not this Rectangle
contains the
+ * specified Point
.
+ * @param p the Point
to test
+ * @return true
if the Point
+ * (x, y) is inside this
+ * Rectangle
;
+ * false
otherwise.
+ */
+ public boolean contains(ReadablePoint p) {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Checks whether or not this Rectangle
contains the
+ * point at the specified location
+ * (x, y).
+ * @param X the specified x coordinate
+ * @param Y the specified y coordinate
+ * @return true
if the point
+ * (x, y) is inside this
+ * Rectangle
;
+ * false
otherwise.
+ */
+ public boolean contains(int X, int Y) {
+ int w = this.width;
+ int h = this.height;
+ if ((w | h) < 0) {
+ // At least one of the dimensions is negative...
+ return false;
+ }
+ // Note: if either dimension is zero, tests below must return false...
+ int x = this.x;
+ int y = this.y;
+ if (X < x || Y < y) {
+ return false;
+ }
+ w += x;
+ h += y;
+ // overflow || intersect
+ return ((w < x || w > X) && (h < y || h > Y));
+ }
+
+ /**
+ * Checks whether or not this Rectangle
entirely contains
+ * the specified Rectangle
.
+ * @param r the specified Rectangle
+ * @return true
if the Rectangle
+ * is contained entirely inside this Rectangle
;
+ * false
otherwise.
+ */
+ public boolean contains(ReadableRectangle r) {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Checks whether this Rectangle
entirely contains
+ * the Rectangle
+ * at the specified location (X, Y) with the
+ * specified dimensions (W, H).
+ * @param X the specified x coordinate
+ * @param Y the specified y coordinate
+ * @param W the width of the Rectangle
+ * @param H the height of the Rectangle
+ * @return true
if the Rectangle
specified by
+ * (X, Y, W, H)
+ * is entirely enclosed inside this Rectangle
;
+ * false
otherwise.
+ */
+ public boolean contains(int X, int Y, int W, int H) {
+ int w = this.width;
+ int h = this.height;
+ if ((w | h | W | H) < 0) {
+ // At least one of the dimensions is negative...
+ return false;
+ }
+ // Note: if any dimension is zero, tests below must return false...
+ int x = this.x;
+ int y = this.y;
+ if (X < x || Y < y) {
+ return false;
+ }
+ w += x;
+ W += X;
+ if (W <= X) {
+ // X+W overflowed or W was zero, return false if...
+ // either original w or W was zero or
+ // x+w did not overflow or
+ // the overflowed x+w is smaller than the overflowed X+W
+ if (w >= x || W > w)
+ return false;
+ } else {
+ // X+W did not overflow and W was not zero, return false if...
+ // original w was zero or
+ // x+w did not overflow and x+w is smaller than X+W
+ if (w >= x && W > w)
+ return false;
+ }
+ h += y;
+ H += Y;
+ if (H <= Y) {
+ if (h >= y || H > h)
+ return false;
+ } else {
+ if (h >= y && H > h)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Determines whether or not this Rectangle
and the specified
+ * Rectangle
intersect. Two rectangles intersect if
+ * their intersection is nonempty.
+ *
+ * @param r the specified Rectangle
+ * @return true
if the specified Rectangle
+ * and this Rectangle
intersect;
+ * false
otherwise.
+ */
+ public boolean intersects(ReadableRectangle r) {
+ int tw = this.width;
+ int th = this.height;
+ int rw = r.getWidth();
+ int rh = r.getHeight();
+ if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
+ return false;
+ }
+ int tx = this.x;
+ int ty = this.y;
+ int rx = r.getX();
+ int ry = r.getY();
+ rw += rx;
+ rh += ry;
+ tw += tx;
+ th += ty;
+ // overflow || intersect
+ return ((rw < rx || rw > tx) && (rh < ry || rh > ty) && (tw < tx || tw > rx) && (th < ty || th > ry));
+ }
+
+ /**
+ * Computes the intersection of this Rectangle
with the
+ * specified Rectangle
. Returns a new Rectangle
+ * that represents the intersection of the two rectangles.
+ * If the two rectangles do not intersect, the result will be
+ * an empty rectangle.
+ *
+ * @param r the specified Rectangle
+ * @return the largest Rectangle
contained in both the
+ * specified Rectangle
and in
+ * this Rectangle
; or if the rectangles
+ * do not intersect, an empty rectangle.
+ */
+ public Rectangle intersection(ReadableRectangle r, Rectangle dest) {
+ int tx1 = this.x;
+ int ty1 = this.y;
+ int rx1 = r.getX();
+ int ry1 = r.getY();
+ long tx2 = tx1;
+ tx2 += this.width;
+ long ty2 = ty1;
+ ty2 += this.height;
+ long rx2 = rx1;
+ rx2 += r.getWidth();
+ long ry2 = ry1;
+ ry2 += r.getHeight();
+ if (tx1 < rx1)
+ tx1 = rx1;
+ if (ty1 < ry1)
+ ty1 = ry1;
+ if (tx2 > rx2)
+ tx2 = rx2;
+ if (ty2 > ry2)
+ ty2 = ry2;
+ tx2 -= tx1;
+ ty2 -= ty1;
+ // tx2,ty2 will never overflow (they will never be
+ // larger than the smallest of the two source w,h)
+ // they might underflow, though...
+ if (tx2 < Integer.MIN_VALUE)
+ tx2 = Integer.MIN_VALUE;
+ if (ty2 < Integer.MIN_VALUE)
+ ty2 = Integer.MIN_VALUE;
+ if (dest == null)
+ dest = new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
+ else
+ dest.setBounds(tx1, ty1, (int) tx2, (int) ty2);
+ return dest;
+
+ }
+
+ /**
+ * Computes the union of this Rectangle
with the
+ * specified Rectangle
. Returns a new
+ * Rectangle
that
+ * represents the union of the two rectangles
+ * @param r the specified Rectangle
+ * @return the smallest Rectangle
containing both
+ * the specified Rectangle
and this
+ * Rectangle
.
+ */
+ public WritableRectangle union(ReadableRectangle r, WritableRectangle dest) {
+ int x1 = Math.min(x, r.getX());
+ int x2 = Math.max(x + width, r.getX() + r.getWidth());
+ int y1 = Math.min(y, r.getY());
+ int y2 = Math.max(y + height, r.getY() + r.getHeight());
+ dest.setBounds(x1, y1, x2 - x1, y2 - y1);
+ return dest;
+ }
+
+ /**
+ * Adds a point, specified by the integer arguments newx
+ * and newy
, to this Rectangle
. The
+ * resulting Rectangle
is
+ * the smallest Rectangle
that contains both the
+ * original Rectangle
and the specified point.
+ *
+ * After adding a point, a call to contains
with the
+ * added point as an argument does not necessarily return
+ * true
. The contains
method does not
+ * return true
for points on the right or bottom
+ * edges of a Rectangle
. Therefore, if the added point
+ * falls on the right or bottom edge of the enlarged
+ * Rectangle
, contains
returns
+ * false
for that point.
+ * @param newx the x coordinates of the new point
+ * @param newy the y coordinates of the new point
+ */
+ public void add(int newx, int newy) {
+ int x1 = Math.min(x, newx);
+ int x2 = Math.max(x + width, newx);
+ int y1 = Math.min(y, newy);
+ int y2 = Math.max(y + height, newy);
+ x = x1;
+ y = y1;
+ width = x2 - x1;
+ height = y2 - y1;
+ }
+
+ /**
+ * Adds the specified Point
to this
+ * Rectangle
. The resulting Rectangle
+ * is the smallest Rectangle
that contains both the
+ * original Rectangle
and the specified
+ * Point
.
+ *
+ * After adding a Point
, a call to contains
+ * with the added Point
as an argument does not
+ * necessarily return true
. The contains
+ * method does not return true
for points on the right
+ * or bottom edges of a Rectangle
. Therefore if the added
+ * Point
falls on the right or bottom edge of the
+ * enlarged Rectangle
, contains
returns
+ * false
for that Point
.
+ * @param pt the new Point
to add to this
+ * Rectangle
+ */
+ public void add(ReadablePoint pt) {
+ add(pt.getX(), pt.getY());
+ }
+
+ /**
+ * Adds a Rectangle
to this Rectangle
.
+ * The resulting Rectangle
is the union of the two
+ * rectangles.
+ * @param r the specified Rectangle
+ */
+ public void add(ReadableRectangle r) {
+ int x1 = Math.min(x, r.getX());
+ int x2 = Math.max(x + width, r.getX() + r.getWidth());
+ int y1 = Math.min(y, r.getY());
+ int y2 = Math.max(y + height, r.getY() + r.getHeight());
+ x = x1;
+ y = y1;
+ width = x2 - x1;
+ height = y2 - y1;
+ }
+
+ /**
+ * Resizes the Rectangle
both horizontally and vertically.
+ *
+ * This method modifies the Rectangle
so that it is
+ * h
units larger on both the left and right side,
+ * and v
units larger at both the top and bottom.
+ *
+ * The new Rectangle
has (x - h
,
+ * y - v
) as its top-left corner, a
+ * width of
+ * width
+
2h
,
+ * and a height of
+ * height
+
2v
.
+ *
+ * If negative values are supplied for h
and
+ * v
, the size of the Rectangle
+ * decreases accordingly.
+ * The grow
method does not check whether the resulting
+ * values of width
and height
are
+ * non-negative.
+ * @param h the horizontal expansion
+ * @param v the vertical expansion
+ */
+ public void grow(int h, int v) {
+ x -= h;
+ y -= v;
+ width += h * 2;
+ height += v * 2;
+ }
+
+ /**
+ * Determines whether or not this Rectangle
is empty. A
+ * Rectangle
is empty if its width or its height is less
+ * than or equal to zero.
+ * @return true
if this Rectangle
is empty;
+ * false
otherwise.
+ */
+ public boolean isEmpty() {
+ return (width <= 0) || (height <= 0);
+ }
+ /**
+ * Checks whether two rectangles are equal.
+ *
+ * The result is true
if and only if the argument is not
+ * null
and is a Rectangle
object that has the
+ * same top-left corner, width, and height as this Rectangle
.
+ * @param obj the Object
to compare with
+ * this Rectangle
+ * @return true
if the objects are equal;
+ * false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof Rectangle) {
+ Rectangle r = (Rectangle) obj;
+ return ((x == r.x) && (y == r.y) && (width == r.width) && (height == r.height));
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Debugging
+ * @return a String
+ */
+ public String toString() {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]";
+ }
+ /**
+ * Gets the height.
+ * @return Returns a int
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the height.
+ * @param height The height to set
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * Gets the width.
+ * @return Returns a int
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the width.
+ * @param width The width to set
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * Gets the x.
+ * @return Returns a int
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * Sets the x.
+ * @param x The x to set
+ */
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ /**
+ * Gets the y.
+ * @return Returns a int
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * Sets the y.
+ * @param y The y to set
+ */
+ public void setY(int y) {
+ this.y = y;
+ }
+
+}
diff --git a/src/java/org/lwjgl/util/Renderable.java b/src/java/org/lwjgl/util/Renderable.java
new file mode 100644
index 0000000..61d3df7
--- /dev/null
+++ b/src/java/org/lwjgl/util/Renderable.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+/**
+ *
+ * Simple interface to things that can be Rendered.
+ *
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: Renderable.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface Renderable {
+
+ /**
+ * "Render" this thing. This will involve calls to the GL.
+ */
+ public void render();
+
+}
diff --git a/src/java/org/lwjgl/util/Timer.java b/src/java/org/lwjgl/util/Timer.java
new file mode 100644
index 0000000..9a4d25a
--- /dev/null
+++ b/src/java/org/lwjgl/util/Timer.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import org.lwjgl.Sys;
+
+/**
+ *
+ * A hires timer. This measures time in seconds as floating point values.
+ * All Timers created are updated simultaneously by calling the static method
+ * tick(). This ensures that within a single iteration of a game loop that
+ * all timers are updated consistently with each other.
+ *
+ * @author cix_foo
+ * @version $Revision: 2983 $
+ * $Id: Timer.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public class Timer {
+
+ // Record the timer resolution on classload
+ private static long resolution = Sys.getTimerResolution();
+
+ // Every so often we will re-query the timer resolution
+ private static final int QUERY_INTERVAL = 50; // in calls to tick()
+ private static int queryCount = 0;
+
+ // Globally keeps track of time for all instances of Timer
+ private static long currentTime;
+
+ // When the timer was started
+ private long startTime;
+
+ // The last time recorded by getTime()
+ private long lastTime;
+
+ // Whether the timer is paused
+ private boolean paused;
+
+ static {
+ tick();
+ }
+
+ /**
+ * Constructs a timer. The timer will be reset to 0.0 and resumed immediately.
+ */
+ public Timer() {
+ reset();
+ resume();
+ }
+
+ /**
+ * @return the time in seconds, as a float
+ */
+ public float getTime() {
+ if (!paused) {
+ lastTime = currentTime - startTime;
+ }
+
+ return (float) ((double) lastTime / (double) resolution);
+ }
+ /**
+ * @return whether this timer is paused
+ */
+ public boolean isPaused() {
+ return paused;
+ }
+
+ /**
+ * Pause the timer. Whilst paused the time will not change for this timer
+ * when tick() is called.
+ *
+ * @see #resume()
+ */
+ public void pause() {
+ paused = true;
+ }
+
+ /**
+ * Reset the timer. Equivalent to set(0.0f);
+ * @see #set(float)
+ */
+ public void reset() {
+ set(0.0f);
+ }
+
+ /**
+ * Resume the timer.
+ * @see #pause()
+ */
+ public void resume() {
+ paused = false;
+ startTime = currentTime - lastTime;
+ }
+
+ /**
+ * Set the time of this timer
+ * @param newTime the new time, in seconds
+ */
+ public void set(float newTime) {
+ long newTimeInTicks = (long) ((double) newTime * (double) resolution);
+ startTime = currentTime - newTimeInTicks;
+ lastTime = newTimeInTicks;
+ }
+
+ /**
+ * Get the next time update from the system's hires timer. This method should
+ * be called once per main loop iteration; all timers are updated simultaneously
+ * from it.
+ */
+ public static void tick() {
+ currentTime = Sys.getTime();
+
+ // Periodically refresh the timer resolution:
+ queryCount ++;
+ if (queryCount > QUERY_INTERVAL) {
+ queryCount = 0;
+ resolution = Sys.getTimerResolution();
+ }
+ }
+
+ /**
+ * Debug output.
+ */
+ public String toString() {
+ return "Timer[Time=" + getTime() + ", Paused=" + paused + "]";
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/WaveData.java b/src/java/org/lwjgl/util/WaveData.java
new file mode 100644
index 0000000..1f2dec4
--- /dev/null
+++ b/src/java/org/lwjgl/util/WaveData.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.ShortBuffer;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+import org.lwjgl.openal.AL10;
+
+/**
+ *
+ * Utitlity class for loading wavefiles.
+ *
+ * @author Brian Matzon
+ * @version $Revision: 3274 $
+ * $Id: WaveData.java 3274 2010-02-20 10:43:22Z matzon $
+ */
+public class WaveData {
+ /** actual wave data */
+ public final ByteBuffer data;
+
+ /** format type of data */
+ public final int format;
+
+ /** sample rate of data */
+ public final int samplerate;
+
+ /**
+ * Creates a new WaveData
+ *
+ * @param data actual wavedata
+ * @param format format of wave data
+ * @param samplerate sample rate of data
+ */
+ private WaveData(ByteBuffer data, int format, int samplerate) {
+ this.data = data;
+ this.format = format;
+ this.samplerate = samplerate;
+ }
+
+ /**
+ * Disposes the wavedata
+ */
+ public void dispose() {
+ data.clear();
+ }
+
+ /**
+ * Creates a WaveData container from the specified url
+ *
+ * @param path URL to file
+ * @return WaveData containing data, or null if a failure occured
+ */
+ public static WaveData create(URL path) {
+ try {
+ return create(
+ AudioSystem.getAudioInputStream(
+ new BufferedInputStream(path.openStream())));
+ } catch (Exception e) {
+ org.lwjgl.LWJGLUtil.log("Unable to create from: " + path + ", " + e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Creates a WaveData container from the specified in the classpath
+ *
+ * @param path path to file (relative, and in classpath)
+ * @return WaveData containing data, or null if a failure occured
+ */
+ public static WaveData create(String path) {
+ return create(WaveData.class.getClassLoader().getResource(path));
+ }
+
+ /**
+ * Creates a WaveData container from the specified inputstream
+ *
+ * @param is InputStream to read from
+ * @return WaveData containing data, or null if a failure occured
+ */
+ public static WaveData create(InputStream is) {
+ try {
+ return create(
+ AudioSystem.getAudioInputStream(is));
+ } catch (Exception e) {
+ org.lwjgl.LWJGLUtil.log("Unable to create from inputstream, " + e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Creates a WaveData container from the specified bytes
+ *
+ * @param buffer array of bytes containing the complete wave file
+ * @return WaveData containing data, or null if a failure occured
+ */
+ public static WaveData create(byte[] buffer) {
+ try {
+ return create(
+ AudioSystem.getAudioInputStream(
+ new BufferedInputStream(new ByteArrayInputStream(buffer))));
+ } catch (Exception e) {
+ org.lwjgl.LWJGLUtil.log("Unable to create from byte array, " + e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Creates a WaveData container from the specified ByetBuffer.
+ * If the buffer is backed by an array, it will be used directly,
+ * else the contents of the buffer will be copied using get(byte[]).
+ *
+ * @param buffer ByteBuffer containing sound file
+ * @return WaveData containing data, or null if a failure occured
+ */
+ public static WaveData create(ByteBuffer buffer) {
+ try {
+ byte[] bytes = null;
+
+ if(buffer.hasArray()) {
+ bytes = buffer.array();
+ } else {
+ bytes = new byte[buffer.capacity()];
+ buffer.get(bytes);
+ }
+ return create(bytes);
+ } catch (Exception e) {
+ org.lwjgl.LWJGLUtil.log("Unable to create from ByteBuffer, " + e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Creates a WaveData container from the specified stream
+ *
+ * @param ais AudioInputStream to read from
+ * @return WaveData containing data, or null if a failure occured
+ */
+ public static WaveData create(AudioInputStream ais) {
+ //get format of data
+ AudioFormat audioformat = ais.getFormat();
+
+ // get channels
+ int channels = 0;
+ if (audioformat.getChannels() == 1) {
+ if (audioformat.getSampleSizeInBits() == 8) {
+ channels = AL10.AL_FORMAT_MONO8;
+ } else if (audioformat.getSampleSizeInBits() == 16) {
+ channels = AL10.AL_FORMAT_MONO16;
+ } else {
+ assert false : "Illegal sample size";
+ }
+ } else if (audioformat.getChannels() == 2) {
+ if (audioformat.getSampleSizeInBits() == 8) {
+ channels = AL10.AL_FORMAT_STEREO8;
+ } else if (audioformat.getSampleSizeInBits() == 16) {
+ channels = AL10.AL_FORMAT_STEREO16;
+ } else {
+ assert false : "Illegal sample size";
+ }
+ } else {
+ assert false : "Only mono or stereo is supported";
+ }
+
+ //read data into buffer
+ ByteBuffer buffer = null;
+ try {
+ int available = ais.available();
+ if(available <= 0) {
+ available = ais.getFormat().getChannels() * (int) ais.getFrameLength() * ais.getFormat().getSampleSizeInBits() / 8;
+ }
+ byte[] buf = new byte[ais.available()];
+ int read = 0, total = 0;
+ while ((read = ais.read(buf, total, buf.length - total)) != -1
+ && total < buf.length) {
+ total += read;
+ }
+ buffer = convertAudioBytes(buf, audioformat.getSampleSizeInBits() == 16);
+ } catch (IOException ioe) {
+ return null;
+ }
+
+
+ //create our result
+ WaveData wavedata =
+ new WaveData(buffer, channels, (int) audioformat.getSampleRate());
+
+ //close stream
+ try {
+ ais.close();
+ } catch (IOException ioe) {
+ }
+
+ return wavedata;
+ }
+
+ private static ByteBuffer convertAudioBytes(byte[] audio_bytes, boolean two_bytes_data) {
+ ByteBuffer dest = ByteBuffer.allocateDirect(audio_bytes.length);
+ dest.order(ByteOrder.nativeOrder());
+ ByteBuffer src = ByteBuffer.wrap(audio_bytes);
+ src.order(ByteOrder.LITTLE_ENDIAN);
+ if (two_bytes_data) {
+ ShortBuffer dest_short = dest.asShortBuffer();
+ ShortBuffer src_short = src.asShortBuffer();
+ while (src_short.hasRemaining())
+ dest_short.put(src_short.get());
+ } else {
+ while (src.hasRemaining())
+ dest.put(src.get());
+ }
+ dest.rewind();
+ return dest;
+ }
+}
diff --git a/src/java/org/lwjgl/util/WritableColor.java b/src/java/org/lwjgl/util/WritableColor.java
new file mode 100644
index 0000000..d70983a
--- /dev/null
+++ b/src/java/org/lwjgl/util/WritableColor.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Write interface for Colors
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: WritableColor.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface WritableColor {
+ /**
+ * Set a color
+ */
+ public void set(int r, int g, int b, int a);
+ /**
+ * Set a color
+ */
+ public void set(byte r, byte g, byte b, byte a);
+ /**
+ * Set a color
+ */
+ public void set(int r, int g, int b);
+ /**
+ * Set a color
+ */
+ public void set(byte r, byte g, byte b);
+ /**
+ * Set the Red component
+ */
+ public void setRed(int red);
+ /**
+ * Set the Green component
+ */
+ public void setGreen(int green);
+ /**
+ * Set the Blue component
+ */
+ public void setBlue(int blue);
+ /**
+ * Set the Alpha component
+ */
+ public void setAlpha(int alpha);
+ /**
+ * Set the Red component
+ */
+ public void setRed(byte red);
+ /**
+ * Set the Green component
+ */
+ public void setGreen(byte green);
+ /**
+ * Set the Blue component
+ */
+ public void setBlue(byte blue);
+ /**
+ * Set the Alpha component
+ */
+ public void setAlpha(byte alpha);
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readRGBA(ByteBuffer src);
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readRGB(ByteBuffer src);
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readARGB(ByteBuffer src);
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readBGRA(ByteBuffer src);
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readBGR(ByteBuffer src);
+ /**
+ * Read a color from a byte buffer
+ * @param src The source buffer
+ */
+ public void readABGR(ByteBuffer src);
+ /**
+ * Set this color's color by copying another color
+ * @param src The source color
+ */
+ public void setColor(ReadableColor src);
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/WritableDimension.java b/src/java/org/lwjgl/util/WritableDimension.java
new file mode 100644
index 0000000..6852012
--- /dev/null
+++ b/src/java/org/lwjgl/util/WritableDimension.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+/**
+ * Write interface for Dimensions
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: WritableDimension.java 2983 2008-04-07 18:36:09Z matzon $
+
+ */
+public interface WritableDimension {
+ public void setSize(int w, int h);
+ public void setSize(ReadableDimension d);
+ /**
+ * Sets the height.
+ * @param height The height to set
+ */
+ public void setHeight(int height);
+ /**
+ * Sets the width.
+ * @param width The width to set
+ */
+ public void setWidth(int width);
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/WritablePoint.java b/src/java/org/lwjgl/util/WritablePoint.java
new file mode 100644
index 0000000..4b6c60a
--- /dev/null
+++ b/src/java/org/lwjgl/util/WritablePoint.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+/**
+ * Write interface for Points
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: WritablePoint.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface WritablePoint {
+ public void setLocation(int x, int y);
+ public void setLocation(ReadablePoint p);
+ public void setX(int x);
+ public void setY(int y);
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/WritableRectangle.java b/src/java/org/lwjgl/util/WritableRectangle.java
new file mode 100644
index 0000000..bc31371
--- /dev/null
+++ b/src/java/org/lwjgl/util/WritableRectangle.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+/**
+ * Write interface for Rectangles
+ * @author $Author: matzon $
+ * @version $Revision: 2983 $
+ * $Id: WritableRectangle.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+public interface WritableRectangle extends WritablePoint, WritableDimension {
+
+ /**
+ * Sets the bounds of the rectangle
+ * @param x Position of rectangle on x axis
+ * @param y Position of rectangle on y axis
+ * @param width Width of rectangle
+ * @param height Height of rectangle
+ */
+ public void setBounds(int x, int y, int width, int height);
+
+ /**
+ * Sets the bounds of the rectangle
+ * @param location
+ * @param size
+ */
+ public void setBounds(ReadablePoint location, ReadableDimension size);
+
+ /**
+ * Sets the bounds of the rectangle
+ * @param src
+ */
+ public void setBounds(ReadableRectangle src);
+}
diff --git a/src/java/org/lwjgl/util/XPMFile.java b/src/java/org/lwjgl/util/XPMFile.java
new file mode 100644
index 0000000..eefc685
--- /dev/null
+++ b/src/java/org/lwjgl/util/XPMFile.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2002-2008 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.util;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+/**
+ *
+ * NOTE: This simple XPM reader does not support extensions nor hotspots
+ *
+ *
+ * @author Brian Matzon
+ * @author Jos Hirth
+ * @version $Revision$
+ * $Id$
+ */
+
+public class XPMFile {
+
+ /** Array of bytes (RGBA) */
+ private byte bytes[] = null;
+
+ private final static int WIDTH = 0;
+
+ private final static int HEIGHT = 1;
+
+ private final static int NUMBER_OF_COLORS = 2;
+
+ private final static int CHARACTERS_PER_PIXEL = 3;
+
+ private static int[] format = new int[4];
+
+ /*
+ * Private constructor, use load(String filename)
+ */
+ private XPMFile() {
+ }
+
+ /**
+ * Loads the XPM file
+ *
+ * @param file
+ * path to file
+ * @return XPMFile loaded, or exception
+ * @throws IOException
+ * If any IO exceptions occurs while reading file
+ */
+ public static XPMFile load(String file) throws IOException {
+ return load(new FileInputStream(new File(file)));
+ }
+
+ /**
+ * Loads the XPM file
+ *
+ * @param is
+ * InputStream to read file from
+ * @return XPMFile loaded, or exception
+ */
+ public static XPMFile load(InputStream is) {
+ XPMFile xFile = new XPMFile();
+ xFile.readImage(is);
+ return xFile;
+ }
+
+ /**
+ * @return the height of the image.
+ */
+ public int getHeight() {
+ return format[HEIGHT];
+ }
+
+ /**
+ * @return the width of the image.
+ */
+ public int getWidth() {
+ return format[WIDTH];
+ }
+
+ /**
+ * @return The data of the image.
+ */
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ /**
+ * Read the image from the specified file.
+ */
+ private void readImage(InputStream is) {
+ try {
+ LineNumberReader reader = new LineNumberReader(
+ new InputStreamReader(is));
+ HashMap colors = new HashMap();
+
+ format = parseFormat(nextLineOfInterest(reader));
+
+ // setup color mapping
+ for (int i = 0; i < format[NUMBER_OF_COLORS]; i++) {
+ Object[] colorDefinition = parseColor(nextLineOfInterest(reader));
+ colors.put(colorDefinition[0], colorDefinition[1]);
+ }
+
+ // read actual image (convert to RGBA)
+ bytes = new byte[format[WIDTH] * format[HEIGHT] * 4];
+ for (int i = 0; i < format[HEIGHT]; i++) {
+ parseImageLine(nextLineOfInterest(reader), format, colors, i);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new IllegalArgumentException("Unable to parse XPM File");
+ }
+ }
+
+ /**
+ * Finds the next interesting line of text.
+ *
+ * @param reader
+ * The LineNumberReader to read from
+ * @return The next interesting String (with stripped quotes)
+ * @throws IOException
+ * If any IO exceptions occurs while reading file
+ */
+ private String nextLineOfInterest(LineNumberReader reader)
+ throws IOException {
+ String ret;
+ do {
+ ret = reader.readLine();
+ } while (!ret.startsWith("\""));
+ // lacks sanity check
+ return ret.substring(1, ret.lastIndexOf('\"'));
+ }
+
+ /**
+ * Parses the format of the xpm file given a format string
+ *
+ * @param format
+ * String to parse
+ * @return Array specifying width, height, colors, characters per pixel
+ */
+ private int[] parseFormat(String format) {
+ // format should look like this:
+ // 16 16 122 2
+
+ // tokenize it
+ StringTokenizer st = new StringTokenizer(format);
+
+ return new int[] { Integer.parseInt(st.nextToken()), /* width */
+ Integer.parseInt(st.nextToken()), /* height */
+ Integer.parseInt(st.nextToken()), /* colors */
+ Integer.parseInt(st.nextToken()) /* chars per pixel */
+ };
+ }
+
+ /**
+ * Given a line defining a color/pixel, parses this into an array containing
+ * a key and a color
+ *
+ * @param line
+ * Line to parse
+ * @return Array containing a key (String) and a color (Integer)
+ */
+ private Object[] parseColor(String line) {
+ // line should look like this:
+ // # c #0A0A0A
+
+ // NOTE: will break if the color is something like "black" or "gray50"
+ // etc (instead of #rrggbb).
+
+ String key = line.substring(0, format[CHARACTERS_PER_PIXEL]);
+ // since we always assume color as type we dont need to read it
+ // String type = line.substring(format[CHARACTERS_PER_PIXEL] + 1,
+ // format[CHARACTERS_PER_PIXEL] + 2);
+ String color = line.substring(format[CHARACTERS_PER_PIXEL] + 4);
+
+ // we always assume type is color, and supplied as #
+ return new Object[] { key, new Integer(Integer.parseInt(color, 16)) };
+ }
+
+ /**
+ * Parses an Image line into its byte values
+ *
+ * @param line
+ * Line of chars to parse
+ * @param format
+ * Format to expext it in
+ * @param colors
+ * Colors to lookup
+ * @param index
+ * current index into lines, we've reached
+ */
+ private void parseImageLine(String line, int[] format, HashMap colors,
+ int index) {
+ // offset for next line
+ int offset = index * 4 * format[WIDTH];
+
+ // read characters times,
+ // each iteration equals one pixel
+ for (int i = 0; i < format[WIDTH]; i++) {
+ String key = line
+ .substring(
+ i * format[CHARACTERS_PER_PIXEL],
+ (i * format[CHARACTERS_PER_PIXEL] + format[CHARACTERS_PER_PIXEL]));
+ Integer color = (Integer) colors.get(key);
+ bytes[offset + (i * 4)] = (byte) ((color.intValue() & 0x00ff0000) >> 16);
+ bytes[offset + ((i * 4) + 1)] = (byte) ((color.intValue() & 0x0000ff00) >> 8);
+ bytes[offset + ((i * 4) + 2)] = (byte) ((color.intValue() & 0x000000ff) >> 0); // looks
+ // better
+ // :)
+ bytes[offset + ((i * 4) + 3)] = (byte) 0xff; // always 0xff alpha
+ }
+ }
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ if (args.length != 1) {
+ System.out.println("usage:\nXPMFile ");
+ }
+
+ try {
+ String out = args[0].substring(0, args[0].indexOf(".")) + ".raw";
+ XPMFile file = XPMFile.load(args[0]);
+ BufferedOutputStream bos = new BufferedOutputStream(
+ new FileOutputStream(new File(out)));
+ bos.write(file.getBytes());
+ bos.close();
+
+ // showResult(file.getBytes());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ /*
+ private static void showResult(byte[] bytes) {
+ final BufferedImage i = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
+ int c = 0;
+ for (int y = 0; y < 16; y++) {
+ for (int x = 0; x < 16; x++) {
+ i.setRGB(x, y, (bytes[c] << 16) + (bytes[c + 1] << 8) + (bytes[c + 2] << 0) + (bytes[c + 3] << 24));//+(128<<24));//
+ c += 4;
+ }
+ }
+
+ final Frame frame = new Frame("XPM Result");
+ frame.add(new Canvas() {
+
+ public void paint(Graphics g) {
+ g.drawImage(i, 0, 0, frame);
+ }
+ });
+
+ frame.addWindowListener(new WindowAdapter() {
+
+ public void windowClosing(WindowEvent e) {
+ frame.dispose();
+ }
+
+ });
+
+ frame.setSize(100, 100);
+ frame.setVisible(true);
+ }*/
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/applet/AppletLoader.java b/src/java/org/lwjgl/util/applet/AppletLoader.java
new file mode 100644
index 0000000..d9778b8
--- /dev/null
+++ b/src/java/org/lwjgl/util/applet/AppletLoader.java
@@ -0,0 +1,1357 @@
+/*
+ * Copyright (c) 2002-2008 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.util.applet;
+
+import java.applet.Applet;
+import java.applet.AppletStub;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.HttpURLConnection;
+import java.net.JarURLConnection;
+import java.net.SocketPermission;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureClassLoader;
+import java.security.cert.Certificate;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Pack200;
+
+import sun.security.util.SecurityConstants;
+
+/**
+ *
+ * The AppletLoader enables deployment of LWJGL to applets in an easy
+ * and polished way. The loader will display a configurable logo and progressbar
+ * while the relevant jars (generic and native) are downloaded from a specified source.
+ *
+ *
+ * The downloaded jars are extracted to the users temporary directory - and if enabled, cached for
+ * faster loading in future uses.
+ *
+ *
+ * The following applet parameters are required:
+ *
+ * - al_main - [String] Full package and class the applet to instantiate and display when loaded.
+ * - al_logo - [String Path of of the logo resource to paint while loading.
+ * - al_progressbar - [String] Path of the progressbar resource to paint on top of the logo, width clipped by percentage.
+ * - al_jars - [String] Comma seperated list of jars to download.
+ * - al_windows - [String] Jar containing native files for windows.
+ * - al_linux - [String] Jar containing native files for linux.
+ * - al_mac - [String] Jar containing native files for mac.
+ * - al_solaris - [String] Jar containing native files for solaris.
+ * - al_freebsd - [String] Jar containing native files for freebsd.
+ *
+ *
+ *
+ * Additionally the following parameters can be supplied to tweak the behaviour of the AppletLoader.
+ *
+ * - al_version - [int or float] Version of deployment. If this is specified, the jars will be cached and
+ * reused if the version matches. If version doesn't match all of the files are reloaded.
+ * - al_bgcolor - [String] Hex formated color to use as background. Default: ffffff.
+ * - al_fgcolor - [String] Hex formated color to use as foreground. Default: 000000.
+ * - al_errorcolor - [String] Hex formated color to use as foreground color on error. Default: ff0000.
+ * - al_debug - [boolean] Whether to enable debug mode. Default: false.
+ * - al_prepend_host - [boolean] Whether to limit caching to this domain, disable if your applet is hosted on multple domains and needs to share the cache. Default: true.
+ *
+ *
+ * @author kappaOne
+ * @author Brian Matzon
+ * @version $Revision$
+ * $Id$
+ */
+public class AppletLoader extends Applet implements Runnable, AppletStub {
+
+ /** initializing */
+ public static final int STATE_INIT = 1;
+
+ /** determining which packages that are required */
+ public static final int STATE_DETERMINING_PACKAGES = 2;
+
+ /** checking for already downloaded files */
+ public static final int STATE_CHECKING_CACHE = 3;
+
+ /** downloading packages */
+ public static final int STATE_DOWNLOADING = 4;
+
+ /** extracting packages */
+ public static final int STATE_EXTRACTING_PACKAGES = 5;
+
+ /** updating the classpath */
+ public static final int STATE_UPDATING_CLASSPATH = 6;
+
+ /** switching to real applet */
+ public static final int STATE_SWITCHING_APPLET = 7;
+
+ /** initializing real applet */
+ public static final int STATE_INITIALIZE_REAL_APPLET = 8;
+
+ /** stating real applet */
+ public static final int STATE_START_REAL_APPLET = 9;
+
+ /** done */
+ public static final int STATE_DONE = 10;
+
+ /** used to calculate length of progress bar */
+ protected int percentage;
+
+ /** current size of download in bytes */
+ protected int currentSizeDownload;
+
+ /** total size of download in bytes */
+ protected int totalSizeDownload;
+
+ /** current size of extracted in bytes */
+ protected int currentSizeExtract;
+
+ /** total size of extracted in bytes */
+ protected int totalSizeExtract;
+
+ /** logo to be shown while loading */
+ protected Image logo;
+
+ /** progressbar to render while loading */
+ protected Image progressbar;
+
+ /** offscreen image used */
+ protected Image offscreen;
+
+ /** background color of applet */
+ protected Color bgColor = Color.white;
+
+ /** Color to write errors in */
+ protected Color errorColor = Color.red;
+
+ /** color to write foreground in */
+ protected Color fgColor = Color.black;
+
+ /** urls of the jars to download */
+ protected URL[] urlList;
+
+ /** classLoader used to add downloaded jars to the classpath */
+ protected ClassLoader classLoader;
+
+ /** actual thread that does the loading */
+ protected Thread loaderThread;
+
+ /** animation thread that renders our load screen while loading */
+ protected Thread animationThread;
+
+ /** applet to load after all downloads are complete */
+ protected Applet lwjglApplet;
+
+ /** whether a fatal error occured */
+ protected boolean fatalError;
+
+ /** fatal error that occured */
+ protected String fatalErrorDescription;
+
+ /** whether we're running in debug mode */
+ protected boolean debugMode;
+
+ /** whether to prepend host to cache path */
+ protected boolean prependHost;
+
+ /** String to display as a subtask */
+ protected String subtaskMessage = "";
+
+ /** state of applet loader */
+ protected int state = STATE_INIT;
+
+ /** whether lzma is supported */
+ protected boolean lzmaSupported = false;
+
+ /** whether pack200 is supported */
+ protected boolean pack200Supported = false;
+
+ /** generic error message to display on error */
+ protected String[] genericErrorMessage = { "An error occured while loading the applet.",
+ "Please contact support to resolve this issue.",
+ ""};
+
+ /** whether a certificate refused error occured */
+ protected boolean certificateRefused;
+
+ /** error message to display if user refuses to accept certicate*/
+ protected String[] certificateRefusedMessage = { "Permissions for Applet Refused.",
+ "Please accept the permissions dialog to allow",
+ "the applet to continue the loading process."};
+
+ /** have natives been loaded by another instance of this applet */
+ static protected boolean natives_loaded = false;
+
+ /*
+ * @see java.applet.Applet#init()
+ */
+ public void init() {
+ state = STATE_INIT;
+
+ // sanity check
+ String[] requiredArgs = {"al_main", "al_logo", "al_progressbar", "al_jars"};
+ for(int i=0; i 0) {
+ messageX = (getWidth() - fm.stringWidth(subtaskMessage)) / 2;
+ og.drawString(subtaskMessage, messageX, messageY+20);
+ }
+
+ // draw loading bar, clipping it depending on percentage done
+ int barSize = (progressbar.getWidth(this) * percentage) / 100;
+ og.clipRect(0, 0, x + barSize, getHeight());
+ og.drawImage(progressbar, x, y, null);
+ }
+
+ og.dispose();
+
+ // finally draw it all
+ g.drawImage(offscreen, 0, 0, null);
+ }
+
+ /**
+ * @return string describing the state of the loader
+ */
+ protected String getDescriptionForState() {
+ switch (state) {
+ case STATE_INIT:
+ return "Initializing loader";
+ case STATE_DETERMINING_PACKAGES:
+ return "Determining packages to load";
+ case STATE_CHECKING_CACHE:
+ return "Checking cache for existing files";
+ case STATE_DOWNLOADING:
+ return "Downloading packages";
+ case STATE_EXTRACTING_PACKAGES:
+ return "Extracting downloaded packages";
+ case STATE_UPDATING_CLASSPATH:
+ return "Updating classpath";
+ case STATE_SWITCHING_APPLET:
+ return "Switching applet";
+ case STATE_INITIALIZE_REAL_APPLET:
+ return "Initializing real applet";
+ case STATE_START_REAL_APPLET:
+ return "Starting real applet";
+ case STATE_DONE:
+ return "Done loading";
+ default:
+ return "unknown state";
+ }
+ }
+
+ /**
+ * Trims the passed file string based on the available capabilities
+ * @param file string of files to be trimmed
+ * @return trimmed string based on capabilities of client
+ */
+ protected String trimExtensionByCapabilities(String file) {
+ if (!pack200Supported) {
+ file = file.replaceAll(".pack", "");
+ }
+
+ if (!lzmaSupported) {
+ file = file.replaceAll(".lzma", "");
+ }
+ return file;
+ }
+
+ /**
+ * Reads list of jars to download and adds the urls to urlList
+ * also finds out which OS you are on and adds appropriate native
+ * jar to the urlList
+ */
+ protected void loadJarURLs() throws Exception {
+ state = STATE_DETERMINING_PACKAGES;
+
+ // jars to load
+ String jarList = getParameter("al_jars");
+
+ jarList = trimExtensionByCapabilities(jarList);
+
+ StringTokenizer jar = new StringTokenizer(jarList, ", ");
+
+ int jarCount = jar.countTokens() + 1;
+
+ urlList = new URL[jarCount];
+
+ URL path = getCodeBase();
+
+ // set jars urls
+ for (int i = 0; i < jarCount - 1; i++) {
+ urlList[i] = new URL(path, jar.nextToken());
+ }
+
+ // native jar url
+ String osName = System.getProperty("os.name");
+ String nativeJar = null;
+
+ if (osName.startsWith("Win")) {
+ nativeJar = getParameter("al_windows");
+ } else if (osName.startsWith("Linux")) {
+ nativeJar = getParameter("al_linux");
+ } else if (osName.startsWith("Mac")) {
+ nativeJar = getParameter("al_mac");
+ } else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
+ nativeJar = getParameter("al_solaris");
+ } else if (osName.startsWith("FreeBSD")) {
+ nativeJar = getParameter("al_freebsd");
+ } else {
+ fatalErrorOccured("OS (" + osName + ") not supported", null);
+ }
+
+ if (nativeJar == null) {
+ fatalErrorOccured("no lwjgl natives files found", null);
+ } else {
+ nativeJar = trimExtensionByCapabilities(nativeJar);
+ urlList[jarCount - 1] = new URL(path, nativeJar);
+ }
+ }
+
+ /**
+ * 4 steps
+ *
+ * 1) check version of applet and decide whether to download jars
+ * 2) download the jars
+ * 3) extract natives
+ * 4) add to jars to class path
+ * 5) switch applets
+ */
+ public void run() {
+ state = STATE_CHECKING_CACHE;
+
+ percentage = 5;
+
+ try {
+ debug_sleep(2000);
+
+ // parse the urls for the jars into the url list
+ loadJarURLs();
+
+ // get path where applet will be stored
+ String path = (String) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+
+ // we append the code base to avoid naming collisions with al_title
+ String codebase = "";
+ if(prependHost) {
+ codebase = getCodeBase().getHost();
+ if(codebase == null || codebase.length() == 0) {
+ codebase = "localhost";
+ }
+ codebase += File.separator;
+ }
+ return System.getProperty("java.io.tmpdir") + File.separator + codebase + getParameter("al_title") + File.separator;
+ }
+ });
+
+ File dir = new File(path);
+
+ // create directory
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ dir = new File(dir, "version");
+
+ // if applet already available don't download anything
+ boolean cacheAvailable = false;
+
+ // version of applet
+ String version = getParameter("al_version");
+ float latestVersion = 0;
+
+ // if applet version specifed, check if you have latest version of applet
+ if (version != null) {
+
+ latestVersion = Float.parseFloat(version);
+
+ // if version file exists
+ if (dir.exists()) {
+ // compare to new version
+ if (latestVersion <= readVersionFile(dir)) {
+ cacheAvailable = true;
+ percentage = 90;
+
+ if(debugMode) {
+ System.out.println("Loading Cached Applet Version " + latestVersion);
+ }
+ debug_sleep(2000);
+ }
+ }
+ }
+
+ // if jars not available or need updating download them
+ if (!cacheAvailable) {
+ // downloads jars from the server
+ downloadJars(path); // 10-55%
+
+ // Extract Pack and LZMA files
+ extractJars(path); // 55-65%
+
+ // Extracts Native Files
+ extractNatives(path); // 65-85%
+
+ // add version information once jars downloaded successfully
+ if (version != null) {
+ percentage = 90;
+ writeVersionFile(dir, latestVersion);
+ }
+ }
+
+ // add the downloaded jars and natives to classpath
+ updateClassPath(path);
+
+ // switch to LWJGL Applet
+ switchApplet();
+
+ state = STATE_DONE;
+ } catch (AccessControlException ace) {
+ fatalErrorOccured(ace.getMessage(), ace);
+ certificateRefused = true;
+ } catch (Exception e) {
+ fatalErrorOccured(e.getMessage(), e);
+ } finally {
+ loaderThread = null;
+ }
+ }
+
+ /**
+ * read the current version file
+ *
+ * @param file the file to read
+ * @return the version value of saved file
+ * @throws Exception if it fails to read value
+ */
+ protected float readVersionFile(File file) throws Exception {
+ DataInputStream dis = new DataInputStream(new FileInputStream(file));
+ float version = dis.readFloat();
+ dis.close();
+ return version;
+ }
+
+ /**
+ * write out version file of applet
+ *
+ * @param file the file to write out to
+ * @param version the version of the applet as a float
+ * @throws Exception if it fails to write file
+ */
+ protected void writeVersionFile(File file, float version) throws Exception {
+ DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
+ dos.writeFloat(version);
+ dos.close();
+ }
+
+ /**
+ * Edits the ClassPath at runtime to include the jars
+ * that have just been downloaded and then adds the
+ * lwjgl natives folder property.
+ *
+ * @param path location where applet is stored
+ * @throws Exception if it fails to add classpath
+ */
+ protected void updateClassPath(String path) throws Exception {
+
+ state = STATE_UPDATING_CLASSPATH;
+
+ percentage = 95;
+
+ URL[] urls = new URL[urlList.length];
+
+ for (int i = 0; i < urlList.length; i++) {
+ urls[i] = new URL("file:" + path + getJarName(urlList[i]));
+ }
+
+ // add downloaded jars to the classpath with required permissions
+ classLoader = new URLClassLoader(urls) {
+ protected PermissionCollection getPermissions (CodeSource codesource) {
+ PermissionCollection perms = null;
+
+ try {
+ // getPermissions from original classloader is important as it checks for signed jars and shows any security dialogs needed
+ Method method = SecureClassLoader.class.getDeclaredMethod("getPermissions", new Class[] { CodeSource.class });
+ method.setAccessible(true);
+ perms = (PermissionCollection)method.invoke(getClass().getClassLoader(), new Object[] {codesource});
+
+ String host = getCodeBase().getHost();
+
+ if (host != null && (host.length() > 0)) {
+ // add permission for downloaded jars to access host they were from
+ perms.add(new SocketPermission(host, SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION));
+ }
+ else if (codesource.getLocation().getProtocol().equals("file")) {
+ // if running locally add file permission
+ String path = codesource.getLocation().getFile().replace('/', File.separatorChar);
+ perms.add(new FilePermission(path, SecurityConstants.FILE_READ_ACTION));
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return perms;
+ }
+ };
+
+ debug_sleep(2000);
+
+ // unload natives loaded by a previous instance of this lwjgl applet
+ unloadNatives(path);
+
+ // add natives files path to native class path
+ System.setProperty("org.lwjgl.librarypath", path + "natives");
+
+ // Make sure jinput knows about the new path too
+ System.setProperty("net.java.games.input.librarypath", path + "natives");
+
+ // mark natives as loaded
+ natives_loaded = true;
+ }
+
+ /**
+ * Unload natives loaded by a different classloader.
+ *
+ * Due to limitations of the jvm, native files can only
+ * be loaded once and only be used by the classloader
+ * they were loaded from.
+ *
+ * Due to the way applets on plugin1 work, one jvm must
+ * be used for all applets. We need to use multiple
+ * classloaders in the same jvm due to LWJGL's static
+ * nature. I order to solver this we simply remove the
+ * natives from a previous classloader allowing a new
+ * classloader to use those natives in the same jvm.
+ *
+ * This method will only attempt to unload natives from a
+ * previous classloader if it detects that the natives have
+ * been loaded in the same jvm.
+ *
+ * @param nativePath directory where natives are stored
+ */
+ private void unloadNatives(String nativePath) {
+
+ // check whether natives have been loaded into this jvm
+ if (!natives_loaded) {
+ return;
+ }
+
+ try {
+ Field field = ClassLoader.class.getDeclaredField("loadedLibraryNames");
+ field.setAccessible(true);
+ Vector libs = (Vector) field.get(getClass().getClassLoader());
+
+ String path = new File(nativePath).getCanonicalPath();
+
+ for (int i = 0; i < libs.size(); i++) {
+ String s = (String) libs.get(i);
+
+ // if a native from the nativePath directory is loaded, unload it
+ if (s.startsWith(path)) {
+ libs.remove(i);
+ i--;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * replace the current applet with the lwjgl applet
+ * using AppletStub and initialise and start it
+ */
+ protected void switchApplet() throws Exception {
+
+ state = STATE_SWITCHING_APPLET;
+ percentage = 100;
+
+ debug_sleep(2000);
+
+ Class appletClass = classLoader.loadClass(getParameter("al_main"));
+ lwjglApplet = (Applet) appletClass.newInstance();
+
+ lwjglApplet.setStub(this);
+ lwjglApplet.setSize(getWidth(), getHeight());
+
+ setLayout(new BorderLayout());
+ add(lwjglApplet);
+ validate();
+
+ state = STATE_INITIALIZE_REAL_APPLET;
+ lwjglApplet.init();
+
+ state = STATE_START_REAL_APPLET;
+ lwjglApplet.start();
+ }
+
+ /**
+ * Will download the jars from the server using the list of urls
+ * in urlList, while at the same time updating progress bar
+ *
+ * @param path location of the directory to save to
+ * @throws Exception if download fails
+ */
+ protected void downloadJars(String path) throws Exception {
+
+ state = STATE_DOWNLOADING;
+
+ URLConnection urlconnection;
+
+ // store file sizes, used for download verification
+ int[] fileSizes = new int[urlList.length];
+
+ // calculate total size of jars to download
+ for (int i = 0; i < urlList.length; i++) {
+ urlconnection = urlList[i].openConnection();
+ urlconnection.setDefaultUseCaches(false);
+ if (urlconnection instanceof HttpURLConnection) {
+ ((HttpURLConnection) urlconnection).setRequestMethod("HEAD");
+ }
+ fileSizes[i] = urlconnection.getContentLength();
+ totalSizeDownload += fileSizes[i];
+ }
+
+ int initialPercentage = percentage = 10;
+
+ // download each jar
+ byte buffer[] = new byte[65536];
+ for (int i = 0; i < urlList.length; i++) {
+
+ int unsuccessfulAttempts = 0;
+ int maxUnsuccessfulAttempts = 3;
+ boolean downloadFile = true;
+
+ // download the jar a max of 3 times
+ while(downloadFile) {
+ downloadFile = false;
+
+ debug_sleep(2000);
+
+ urlconnection = urlList[i].openConnection();
+
+ if (urlconnection instanceof HttpURLConnection) {
+ urlconnection.setRequestProperty("Cache-Control", "no-cache");
+ urlconnection.connect();
+ }
+
+ String currentFile = getFileName(urlList[i]);
+ InputStream inputstream = getJarInputStream(currentFile, urlconnection);
+ FileOutputStream fos = new FileOutputStream(path + currentFile);
+
+
+ int bufferSize;
+ long downloadStartTime = System.currentTimeMillis();
+ int downloadedAmount = 0;
+ int fileSize = 0;
+ String downloadSpeedMessage = "";
+
+ while ((bufferSize = inputstream.read(buffer, 0, buffer.length)) != -1) {
+ debug_sleep(10);
+ fos.write(buffer, 0, bufferSize);
+ currentSizeDownload += bufferSize;
+ fileSize += bufferSize;
+ percentage = initialPercentage + ((currentSizeDownload * 45) / totalSizeDownload);
+ subtaskMessage = "Retrieving: " + currentFile + " " + ((currentSizeDownload * 100) / totalSizeDownload) + "%";
+
+ downloadedAmount += bufferSize;
+ long timeLapse = System.currentTimeMillis() - downloadStartTime;
+ // update only if a second or more has passed
+ if (timeLapse >= 1000) {
+ // get kb/s, nice that bytes/millis is same as kilobytes/seconds
+ float downloadSpeed = (float) downloadedAmount / timeLapse;
+ // round to two decimal places
+ downloadSpeed = ((int)(downloadSpeed*100))/100f;
+ // set current speed message
+ downloadSpeedMessage = " @ " + downloadSpeed + " KB/sec";
+ // reset downloaded amount
+ downloadedAmount = 0;
+ // reset start time
+ downloadStartTime = System.currentTimeMillis();
+ }
+
+ subtaskMessage += downloadSpeedMessage;
+ }
+
+ inputstream.close();
+ fos.close();
+
+ // download complete, verify if it was successful
+ if (urlconnection instanceof HttpURLConnection) {
+ if (fileSize == fileSizes[i]) {
+ // successful download
+ }
+ else if (fileSizes[i] <= 0) {
+ // If contentLength for fileSizes[i] <= 0, we don't know if the download
+ // is complete. We're going to guess the download is complete.
+ }
+ else {
+ unsuccessfulAttempts++;
+ // download failed try again
+ if (unsuccessfulAttempts < maxUnsuccessfulAttempts) {
+ downloadFile = true;
+ currentSizeDownload -= fileSize; // reset progress bar
+ }
+ else {
+ // retry attempts exhasted, download failed
+ throw new Exception("failed to download " + currentFile);
+ }
+ }
+ }
+ }
+ }
+ subtaskMessage = "";
+ }
+
+ /**
+ * Retrieves a jar files input stream. This method exists primarily to fix an Opera hang in getInputStream
+ * @param urlconnection connection to get input stream from
+ * @return InputStream or null if not possible
+ */
+ protected InputStream getJarInputStream(final String currentFile, final URLConnection urlconnection) throws Exception {
+ final InputStream[] is = new InputStream[1];
+
+ // try to get the input stream 3 times.
+ // Wait at most 5 seconds before interrupting the thread
+ for (int j = 0; j < 3 && is[0] == null; j++) {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ is[0] = urlconnection.getInputStream();
+ } catch (IOException e) {
+ /* ignored */
+ }
+ }
+ };
+ t.setName("JarInputStreamThread");
+ t.start();
+
+ int iterationCount = 0;
+ while(is[0] == null && iterationCount++ < 5) {
+ try {
+ t.join(1000);
+ } catch (InterruptedException inte) {
+ /* ignored */
+ }
+ }
+
+ if(is[0] == null) {
+ try {
+ t.interrupt();
+ t.join();
+ } catch (InterruptedException inte) {
+ /* ignored */
+ }
+ }
+ }
+
+ if(is[0] == null) {
+ throw new Exception("Unable to get input stream for " + currentFile);
+ }
+
+
+ return is[0];
+ }
+
+ /**
+ * Extract LZMA File
+ * @param in Input path to pack file
+ * @param out output path to resulting file
+ * @throws exception if any errors occur
+ */
+ protected void extractLZMA(String in, String out) throws Exception {
+
+ File f = new File(in);
+ FileInputStream fileInputHandle = new FileInputStream(f);
+
+ // use reflection to avoid hard dependency
+ Class clazz = Class.forName( "LZMA.LzmaInputStream" );
+ Constructor constructor = clazz.getDeclaredConstructor( new Class[] {InputStream.class} );
+ InputStream inputHandle = (InputStream) constructor.newInstance( new Object[] {fileInputHandle} );
+
+ OutputStream outputHandle;
+ outputHandle = new FileOutputStream(out);
+
+ byte [] buffer = new byte [1<<14];
+
+ int ret = inputHandle.read(buffer);
+ while (ret >= 1) {
+ outputHandle.write(buffer,0,ret);
+ ret = inputHandle.read(buffer);
+ }
+
+ inputHandle.close();
+ outputHandle.close();
+
+ outputHandle = null;
+ inputHandle = null;
+
+ // delete LZMA file, as it is no longer needed
+ f.delete();
+ }
+
+ /**
+ * Extract Pack File
+ * @param in Input path to pack file
+ * @param out output path to resulting file
+ * @throws exception if any errors occur
+ */
+ protected void extractPack(String in, String out) throws Exception {
+ File f = new File(in);
+ FileOutputStream fostream = new FileOutputStream(out);
+ JarOutputStream jostream = new JarOutputStream(fostream);
+
+ Pack200.Unpacker unpacker = Pack200.newUnpacker();
+ unpacker.unpack(f, jostream);
+ jostream.close();
+
+ // delete pack file as its no longer needed
+ f.delete();
+ }
+
+ /**
+ * Extract all jars from any lzma/pack files
+ *
+ * @param path output path
+ * @throws exception if any errors occur
+ */
+ protected void extractJars(String path) throws Exception {
+ state = STATE_EXTRACTING_PACKAGES;
+
+ float increment = (float) 10.0 / urlList.length;
+ // extract all lzma and pack.lzma files
+ for (int i = 0; i < urlList.length; i++) {
+ percentage = 55 + (int) (increment * (i+1));
+ String filename = getFileName(urlList[i]);
+
+ if (filename.endsWith(".pack.lzma")) {
+ subtaskMessage = "Extracting: " + filename + " to " + filename.replaceAll(".lzma", "");
+ debug_sleep(1000);
+ extractLZMA(path + filename, path + filename.replaceAll(".lzma", ""));
+
+ subtaskMessage = "Extracting: " + filename.replaceAll(".lzma", "") + " to " + filename.replaceAll(".pack.lzma", "");
+ debug_sleep(1000);
+ extractPack(path + filename.replaceAll(".lzma", ""), path + filename.replaceAll(".pack.lzma", ""));
+ }
+ else if (filename.endsWith(".pack")) {
+ subtaskMessage = "Extracting: " + filename + " to " + filename.replace(".pack", "");
+ debug_sleep(1000);
+ extractPack(path + filename, path + filename.replace(".pack", ""));
+ }
+ else if (filename.endsWith(".lzma")) {
+ subtaskMessage = "Extracting: " + filename + " to " + filename.replace(".lzma", "");
+ debug_sleep(1000);
+ extractLZMA(path + filename, path + filename.replace(".lzma", ""));
+ }
+ }
+ }
+
+ /**
+ * This method will extract all file from the native jar and extract them
+ * to the subdirectory called "natives" in the local path, will also check
+ * to see if the native jar files is signed properly
+ *
+ * @param path base folder containing all downloaded jars
+ * @throws Exception if it fails to extract files
+ */
+ protected void extractNatives(String path) throws Exception {
+
+ state = STATE_EXTRACTING_PACKAGES;
+
+ int initialPercentage = percentage;
+
+ // get name of jar file with natives from urlList, it will be the last url
+ String nativeJar = getJarName(urlList[urlList.length - 1]);
+
+ // get the current certificate to compare against native files
+ Certificate[] certificate = AppletLoader.class.getProtectionDomain().getCodeSource().getCertificates();
+
+ // workaround for bug where cached applet loader does not have certificates!?
+ if (certificate == null) {
+ URL location = AppletLoader.class.getProtectionDomain().getCodeSource().getLocation();
+
+ // manually load the certificate
+ JarURLConnection jurl = (JarURLConnection) (new URL("jar:" + location.toString() + "!/org/lwjgl/util/applet/AppletLoader.class").openConnection());
+ jurl.setDefaultUseCaches(true);
+ certificate = jurl.getCertificates();
+ }
+
+ // create native folder
+ File nativeFolder = new File(path + "natives");
+ if (!nativeFolder.exists()) {
+ nativeFolder.mkdir();
+ }
+
+ // open jar file
+ JarFile jarFile = new JarFile(path + nativeJar, true);
+
+ // get list of files in jar
+ Enumeration entities = jarFile.entries();
+
+ totalSizeExtract = 0;
+
+ // calculate the size of the files to extract for progress bar
+ while (entities.hasMoreElements()) {
+ JarEntry entry = (JarEntry) entities.nextElement();
+
+ // skip directories and anything in directories
+ // conveniently ignores the manifest
+ if (entry.isDirectory() || entry.getName().indexOf('/') != -1) {
+ continue;
+ }
+ totalSizeExtract += entry.getSize();
+ }
+
+ currentSizeExtract = 0;
+
+ // reset point to begining by getting list of file again
+ entities = jarFile.entries();
+
+ // extract all files from the jar
+ while (entities.hasMoreElements()) {
+ JarEntry entry = (JarEntry) entities.nextElement();
+
+ // skip directories and anything in directories
+ // conveniently ignores the manifest
+ if (entry.isDirectory() || entry.getName().indexOf('/') != -1) {
+ continue;
+ }
+
+ // check if native file already exists if so delete it to make room for new one
+ // useful when using the reload button on the browser
+ File f = new File(path + "natives" + File.separator + entry.getName());
+ if (f.exists()) {
+ if (!f.delete()) {
+ continue; // unable to delete file, it is in use, skip extracting it
+ }
+ }
+
+ debug_sleep(1000);
+
+ InputStream in = jarFile.getInputStream(jarFile.getEntry(entry.getName()));
+ OutputStream out = new FileOutputStream(path + "natives" + File.separator + entry.getName());
+
+ int bufferSize;
+ byte buffer[] = new byte[65536];
+
+ while ((bufferSize = in.read(buffer, 0, buffer.length)) != -1) {
+ debug_sleep(10);
+ out.write(buffer, 0, bufferSize);
+ currentSizeExtract += bufferSize;
+
+ // update progress bar
+ percentage = initialPercentage + ((currentSizeExtract * 20) / totalSizeExtract);
+ subtaskMessage = "Extracting: " + entry.getName() + " " + ((currentSizeExtract * 100) / totalSizeExtract) + "%";
+ }
+
+ // validate if the certificate for native file is correct
+ validateCertificateChain(certificate, entry.getCertificates());
+
+ in.close();
+ out.close();
+ }
+ subtaskMessage = "";
+
+ jarFile.close();
+
+ // delete native jar as it is no longer needed
+ File f = new File(path + nativeJar);
+ f.delete();
+ }
+
+ /**
+ * Validates the certificate chain for a single file
+ *
+ * @param ownCerts Chain of certificates to check against
+ * @param native_certs Chain of certificates to check
+ */
+ protected static void validateCertificateChain(Certificate[] ownCerts, Certificate[] native_certs) throws Exception {
+ if (native_certs == null)
+ throw new Exception("Unable to validate certificate chain. Native entry did not have a certificate chain at all");
+
+ if (ownCerts.length != native_certs.length)
+ throw new Exception("Unable to validate certificate chain. Chain differs in length [" + ownCerts.length + " vs " + native_certs.length + "]");
+
+ for (int i = 0; i < ownCerts.length; i++) {
+ if (!ownCerts[i].equals(native_certs[i])) {
+ throw new Exception("Certificate mismatch: " + ownCerts[i] + " != " + native_certs[i]);
+ }
+ }
+ }
+
+ /**
+ * Get Image from path provided
+ *
+ * @param s location of the image
+ * @return the Image file
+ */
+ protected Image getImage(String s) {
+ try {
+ URL url = AppletLoader.class.getResource("/"+s);
+
+ // if image not found in jar, look outside it
+ if (url == null) {
+ url = new URL(getCodeBase(), s);
+ }
+
+ Image image = super.getImage(url);
+
+ // wait for image to load
+ MediaTracker tracker = new MediaTracker(this);
+ tracker.addImage(image, 0);
+ tracker.waitForAll();
+
+ return image;
+ } catch (Exception e) {
+ /* */
+ }
+ return null;
+ }
+
+
+ /**
+ * Get jar name from URL.
+ *
+ * @param url Get jar file name from this url
+ * @return file name as string
+ */
+ protected String getJarName(URL url) {
+ String fileName = url.getFile();
+
+ if (fileName.endsWith(".pack.lzma")) {
+ fileName = fileName.replaceAll(".pack.lzma", "");
+ } else if (fileName.endsWith(".pack")) {
+ fileName = fileName.replaceAll(".pack", "");
+ } else if (fileName.endsWith(".lzma")) {
+ fileName = fileName.replaceAll(".lzma", "");
+ }
+
+ return fileName.substring(fileName.lastIndexOf('/') + 1);
+ }
+
+ /**
+ * Get file name portion of URL.
+ *
+ * @param url Get file name from this url
+ * @return file name as string
+ */
+ protected String getFileName(URL url) {
+ String fileName = url.getFile();
+ return fileName.substring(fileName.lastIndexOf('/') + 1);
+ }
+
+ /**
+ * Retrieves the color
+ *
+ * @param color Color to load
+ * @param defaultColor Default color to use if no color to load
+ * @return Color to use
+ */
+ protected Color getColor(String color, Color defaultColor) {
+ String param_color = getParameter(color);
+ if (param_color != null) {
+ return new Color(Integer.parseInt(param_color, 16));
+ }
+ return defaultColor;
+ }
+
+ /**
+ * Retrieves the boolean value for the applet
+ * @param name Name of parameter
+ * @param defaultValue default value to return if no such parameter
+ * @return value of parameter or defaultValue
+ */
+ protected boolean getBooleanParameter(String name, boolean defaultValue) {
+ String parameter = getParameter(name);
+ if(parameter != null) {
+ return Boolean.parseBoolean(parameter);
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Sets the state of the loaded and prints some debug information
+ *
+ * @param error Error message to print
+ */
+ protected void fatalErrorOccured(String error, Exception e) {
+ fatalError = true;
+ fatalErrorDescription = "Fatal error occured (" + state + "): " + error;
+ System.out.println(fatalErrorDescription);
+ if(e != null) {
+ System.out.println(generateStacktrace(e));
+ }
+ repaint();
+ }
+
+ /**
+ * Utility method for sleeping
+ * Will only really sleep if debug has been enabled
+ * @param ms milliseconds to sleep
+ */
+ protected void debug_sleep(long ms) {
+ if(debugMode) {
+ sleep(ms);
+ }
+ }
+
+ /**
+ * Utility method for sleeping
+ * @param ms milliseconds to sleep
+ */
+ protected void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (Exception e) {
+ /* ignored */
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/ALTypeMap.java b/src/java/org/lwjgl/util/generator/ALTypeMap.java
new file mode 100644
index 0000000..c64cbf9
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALTypeMap.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * The OpenAL specific generator behaviour
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALTypeMap.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import com.sun.mirror.declaration.*;
+import com.sun.mirror.type.*;
+
+import java.io.*;
+import java.util.*;
+import java.nio.*;
+
+public class ALTypeMap implements TypeMap {
+ private static final Map native_types_to_primitive;
+
+ static {
+ native_types_to_primitive = new HashMap();
+ native_types_to_primitive.put(ALboolean.class, PrimitiveType.Kind.BOOLEAN);
+ native_types_to_primitive.put(ALbyte.class, PrimitiveType.Kind.BYTE);
+ native_types_to_primitive.put(ALenum.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(ALfloat.class, PrimitiveType.Kind.FLOAT);
+ native_types_to_primitive.put(ALdouble.class, PrimitiveType.Kind.DOUBLE);
+ native_types_to_primitive.put(ALint.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(ALshort.class, PrimitiveType.Kind.SHORT);
+ native_types_to_primitive.put(ALsizei.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(ALubyte.class, PrimitiveType.Kind.BYTE);
+ native_types_to_primitive.put(ALuint.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(ALvoid.class, PrimitiveType.Kind.BYTE);
+ }
+
+ public PrimitiveType.Kind getPrimitiveTypeFromNativeType(Class native_type) {
+ PrimitiveType.Kind kind = native_types_to_primitive.get(native_type);
+ if (kind == null)
+ throw new RuntimeException("Unsupported type " + native_type);
+ return kind;
+ }
+
+ public Signedness getSignednessFromType(Class type) {
+ if (ALuint.class.equals(type))
+ return Signedness.UNSIGNED;
+ else if (ALint.class.equals(type))
+ return Signedness.SIGNED;
+ else if (ALshort.class.equals(type))
+ return Signedness.SIGNED;
+ else if (ALbyte.class.equals(type))
+ return Signedness.SIGNED;
+ else
+ return Signedness.NONE;
+ }
+
+ public String translateAnnotation(Class annotation_type) {
+ if (annotation_type.equals(ALuint.class))
+ return "i";
+ else if (annotation_type.equals(ALint.class))
+ return "i";
+ else if (annotation_type.equals(ALshort.class))
+ return "s";
+ else if (annotation_type.equals(ALbyte.class))
+ return "b";
+ else if (annotation_type.equals(ALfloat.class))
+ return "f";
+ else if (annotation_type.equals(ALdouble.class))
+ return "d";
+ else if (annotation_type.equals(ALboolean.class) || annotation_type.equals(ALvoid.class))
+ return "";
+ else
+ throw new RuntimeException(annotation_type + " is not allowed");
+ }
+
+ public Class getNativeTypeFromPrimitiveType(PrimitiveType.Kind kind) {
+ Class type;
+ switch (kind) {
+ case INT:
+ type = ALint.class;
+ break;
+ case FLOAT:
+ type = ALfloat.class;
+ break;
+ case DOUBLE:
+ type = ALdouble.class;
+ break;
+ case SHORT:
+ type = ALshort.class;
+ break;
+ case BYTE:
+ type = ALbyte.class;
+ break;
+ case BOOLEAN:
+ type = ALboolean.class;
+ break;
+ default:
+ throw new RuntimeException(kind + " is not allowed");
+ }
+ return type;
+ }
+
+ private static Class[] getValidBufferTypes(Class type) {
+ if (type.equals(IntBuffer.class))
+ return new Class[]{ALenum.class, ALint.class, ALsizei.class, ALuint.class};
+ else if (type.equals(FloatBuffer.class))
+ return new Class[]{ALfloat.class};
+ else if (type.equals(ByteBuffer.class))
+ return new Class[]{ALboolean.class, ALbyte.class, ALvoid.class};
+ else if (type.equals(ShortBuffer.class))
+ return new Class[]{ALshort.class};
+ else if (type.equals(DoubleBuffer.class))
+ return new Class[]{ALdouble.class};
+ else
+ return new Class[]{};
+ }
+
+ private static Class[] getValidPrimitiveTypes(Class type) {
+ if (type.equals(int.class))
+ return new Class[]{ALenum.class, ALint.class, ALsizei.class, ALuint.class};
+ else if (type.equals(double.class))
+ return new Class[]{ALdouble.class};
+ else if (type.equals(float.class))
+ return new Class[]{ALfloat.class};
+ else if (type.equals(short.class))
+ return new Class[]{ALshort.class};
+ else if (type.equals(byte.class))
+ return new Class[]{ALbyte.class};
+ else if (type.equals(boolean.class))
+ return new Class[]{ALboolean.class};
+ else if (type.equals(void.class))
+ return new Class[]{ALvoid.class};
+ else
+ return new Class[]{};
+ }
+
+ public String getErrorCheckMethodName() {
+ return "Util.checkALError()";
+ }
+
+ public String getRegisterNativesFunctionName() {
+ return "extal_InitializeClass";
+ }
+
+ public String getTypedefPrefix() {
+ return "ALAPIENTRY";
+ }
+
+ public void printNativeIncludes(PrintWriter writer) {
+ writer.println("#include \"extal.h\"");
+ }
+
+ public Class getStringElementType() {
+ return ALubyte.class;
+ }
+
+ public Class[] getValidAnnotationTypes(Class type) {
+ Class[] valid_types;
+ if (Buffer.class.isAssignableFrom(type))
+ valid_types = getValidBufferTypes(type);
+ else if (type.isPrimitive())
+ valid_types = getValidPrimitiveTypes(type);
+ else if (type.equals(String.class))
+ valid_types = new Class[]{ALubyte.class};
+ else
+ valid_types = new Class[]{};
+ return valid_types;
+ }
+
+ public Class getVoidType() {
+ return ALvoid.class;
+ }
+
+ public Class getInverseType(Class type) {
+ if (ALuint.class.equals(type))
+ return ALint.class;
+ else if (ALint.class.equals(type))
+ return ALuint.class;
+ else
+ return null;
+ }
+
+ public String getAutoTypeFromAnnotation(AnnotationMirror annotation) {
+ return null;
+ }
+}
diff --git a/src/java/org/lwjgl/util/generator/ALboolean.java b/src/java/org/lwjgl/util/generator/ALboolean.java
new file mode 100644
index 0000000..6c828b3
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALboolean.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALboolean.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALboolean {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALbyte.java b/src/java/org/lwjgl/util/generator/ALbyte.java
new file mode 100644
index 0000000..9a632e7
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALbyte.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALbyte.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALbyte {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALdouble.java b/src/java/org/lwjgl/util/generator/ALdouble.java
new file mode 100644
index 0000000..9aa4f3c
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALdouble.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALdouble.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALdouble {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALenum.java b/src/java/org/lwjgl/util/generator/ALenum.java
new file mode 100644
index 0000000..a12a633
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALenum.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALenum.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALenum {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALfloat.java b/src/java/org/lwjgl/util/generator/ALfloat.java
new file mode 100644
index 0000000..2777b66
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALfloat.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALfloat.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALfloat {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALint.java b/src/java/org/lwjgl/util/generator/ALint.java
new file mode 100644
index 0000000..db5db7c
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALint.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALint.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALint {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALshort.java b/src/java/org/lwjgl/util/generator/ALshort.java
new file mode 100644
index 0000000..b10c6fd
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALshort.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALshort.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALshort {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALsizei.java b/src/java/org/lwjgl/util/generator/ALsizei.java
new file mode 100644
index 0000000..8b33f37
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALsizei.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALsizei.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALsizei {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALubyte.java b/src/java/org/lwjgl/util/generator/ALubyte.java
new file mode 100644
index 0000000..12767c5
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALubyte.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALubyte.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALubyte {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALuint.java b/src/java/org/lwjgl/util/generator/ALuint.java
new file mode 100644
index 0000000..c242a9e
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALuint.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALuint.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALuint {
+}
diff --git a/src/java/org/lwjgl/util/generator/ALvoid.java b/src/java/org/lwjgl/util/generator/ALvoid.java
new file mode 100644
index 0000000..d1f7465
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ALvoid.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: ALvoid.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface ALvoid {
+}
diff --git a/src/java/org/lwjgl/util/generator/Alternate.java b/src/java/org/lwjgl/util/generator/Alternate.java
new file mode 100644
index 0000000..67fe518
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Alternate.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * When a method is annonated with @Alternate, no native stub will be created and the Java method will be renamed to value().
+ * This can be useful when we want to provide an alternate GL call with different arguments (created by different annotations)
+ *
+ * @author spasi
+ */
+@Target({ ElementType.METHOD })
+public @interface Alternate {
+
+ /** This must match an existing GL method name. */
+ String value();
+
+ /** If true, an alternate Java->native call will be created. Useful when the alternate implementation uses different types. */
+ boolean nativeAlt() default false;
+
+ /** If true, the alternate method's name will be used for the Java call. */
+ boolean javaAlt() default false;
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/Auto.java b/src/java/org/lwjgl/util/generator/Auto.java
new file mode 100644
index 0000000..e53a64f
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Auto.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * AutoType and AutoSize is annotated with @Auto.
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: Auto.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface Auto {
+}
diff --git a/src/java/org/lwjgl/util/generator/AutoResultSize.java b/src/java/org/lwjgl/util/generator/AutoResultSize.java
new file mode 100644
index 0000000..4e3145f
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/AutoResultSize.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * AutoResultSize specifies the size of a returned Buffer
+ * as an expression.
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: AutoResultSize.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.METHOD)
+public @interface AutoResultSize {
+ String value(); // The size as a java expression
+}
diff --git a/src/java/org/lwjgl/util/generator/AutoSize.java b/src/java/org/lwjgl/util/generator/AutoSize.java
new file mode 100644
index 0000000..621a48a
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/AutoSize.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * AutoSize specifies that a parameter should be pre-computed
+ * according to the remaining() of a Buffer parameter.
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: AutoSize.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Auto
+@Target(ElementType.PARAMETER)
+public @interface AutoSize {
+ String value(); // The name of the Buffer parameter
+ String expression() default ""; // This value is added after the argument
+}
diff --git a/src/java/org/lwjgl/util/generator/AutoType.java b/src/java/org/lwjgl/util/generator/AutoType.java
new file mode 100644
index 0000000..93d094c
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/AutoType.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * Indicates that a parameter should be pre-computed according
+ * to the type of a Buffer parameter.
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: AutoType.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Auto
+@Target(ElementType.PARAMETER)
+public @interface AutoType {
+ String value(); // The parameter to get the type from
+}
diff --git a/src/java/org/lwjgl/util/generator/BufferKind.java b/src/java/org/lwjgl/util/generator/BufferKind.java
new file mode 100644
index 0000000..42c2c1a
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/BufferKind.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3279 $
+ * $Id: BufferKind.java 3279 2010-03-11 21:06:49Z spasi $
+ */
+
+public enum BufferKind {
+ UnpackPBO,
+ PackPBO,
+ ElementVBO,
+ ArrayVBO,
+ IndirectBO
+}
diff --git a/src/java/org/lwjgl/util/generator/BufferObject.java b/src/java/org/lwjgl/util/generator/BufferObject.java
new file mode 100644
index 0000000..b886aff
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/BufferObject.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * This annotation implies that a Buffer parameter can be an
+ * integer VBO/PBO offset.
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: BufferObject.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.PARAMETER)
+public @interface BufferObject {
+ BufferKind value();
+}
diff --git a/src/java/org/lwjgl/util/generator/CachedReference.java b/src/java/org/lwjgl/util/generator/CachedReference.java
new file mode 100644
index 0000000..ee7b910
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/CachedReference.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * This annotation indicates that a buffer parameter is cached by
+ * OpenGL.
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: CachedReference.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.PARAMETER)
+public @interface CachedReference {
+ /** If set then this will be used as array index for accessing the stored reference. */
+ String index() default "";
+
+ /** If set then this name will be used for the reference and the reference field will not be auto generated in References. */
+ String name() default "";
+}
diff --git a/src/java/org/lwjgl/util/generator/CachedResult.java b/src/java/org/lwjgl/util/generator/CachedResult.java
new file mode 100644
index 0000000..7de1f77
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/CachedResult.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3262 $
+ * $Id: CachedResult.java 3262 2010-01-04 18:47:49Z spasi $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.METHOD)
+public @interface CachedResult {
+ boolean isRange() default false;
+}
diff --git a/src/java/org/lwjgl/util/generator/Check.java b/src/java/org/lwjgl/util/generator/Check.java
new file mode 100644
index 0000000..1c177e3
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Check.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: Check.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.PARAMETER)
+public @interface Check {
+ String value() default "";
+ boolean canBeNull() default false;
+}
diff --git a/src/java/org/lwjgl/util/generator/Code.java b/src/java/org/lwjgl/util/generator/Code.java
new file mode 100644
index 0000000..8e9e878
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Code.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: Code.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.METHOD)
+public @interface Code {
+ String value();
+}
diff --git a/src/java/org/lwjgl/util/generator/Const.java b/src/java/org/lwjgl/util/generator/Const.java
new file mode 100644
index 0000000..c8193d6
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Const.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: Const.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface Const {
+}
diff --git a/src/java/org/lwjgl/util/generator/Constant.java b/src/java/org/lwjgl/util/generator/Constant.java
new file mode 100644
index 0000000..07d0afa
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Constant.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3287 $
+ * $Id: Constant.java 3287 2010-03-14 23:24:40Z spasi $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.PARAMETER)
+public @interface Constant {
+ String value();
+ /** If true, the original parameter will not be removed from the method. */
+ boolean keepParam() default false;
+}
diff --git a/src/java/org/lwjgl/util/generator/ContextCapabilitiesGenerator.java b/src/java/org/lwjgl/util/generator/ContextCapabilitiesGenerator.java
new file mode 100644
index 0000000..36232ca
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ContextCapabilitiesGenerator.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Iterator;
+
+import com.sun.mirror.declaration.InterfaceDeclaration;
+import com.sun.mirror.declaration.MethodDeclaration;
+import com.sun.mirror.type.InterfaceType;
+
+/**
+ * Generator visitor for the context capabilities generator tool
+ *
+ * @author elias_naur
+ * @version $Revision: 3316 $
+ * $Id: ContextCapabilitiesGenerator.java 3316 2010-04-09 23:57:40Z spasi $
+ */
+public class ContextCapabilitiesGenerator {
+
+ private final static String STUBS_LOADED_NAME = "loaded_stubs";
+ private final static String ALL_INIT_METHOD_NAME = "initAllStubs";
+ private final static String POINTER_INITIALIZER_POSTFIX = "_initNativeFunctionAddresses";
+ private final static String CACHED_EXTS_VAR_NAME = "supported_extensions";
+ private final static String PROFILE_MASK_VAR_NAME = "profileMask";
+ private final static String EXTENSION_PREFIX = "GL_";
+ private final static String CORE_PREFIX = "Open";
+
+ public static void generateClassPrologue(PrintWriter writer, boolean context_specific, boolean generate_error_checks) {
+ writer.println("public class " + Utils.CONTEXT_CAPS_CLASS_NAME + " {");
+ writer.println("\tstatic final boolean DEBUG = " + Boolean.toString(generate_error_checks) + ";");
+ writer.println("\tfinal StateTracker tracker = new StateTracker();");
+ writer.println("\tfinal IntBuffer scratch_int_buffer = BufferUtils.createIntBuffer(16);");
+ writer.println();
+ if ( !context_specific ) {
+ writer.println("\tprivate static boolean " + STUBS_LOADED_NAME + " = false;");
+ }
+ }
+
+ public static void generateInitializerPrologue(PrintWriter writer) {
+ writer.println("\t" + Utils.CONTEXT_CAPS_CLASS_NAME + "(boolean forwardCompatible) throws LWJGLException {");
+ writer.println("\t\tSet " + CACHED_EXTS_VAR_NAME + " = " + ALL_INIT_METHOD_NAME + "(forwardCompatible);");
+ }
+
+ private static String translateFieldName(String interface_name) {
+ if ( interface_name.startsWith("GL") )
+ return CORE_PREFIX + interface_name;
+ else
+ return EXTENSION_PREFIX + interface_name;
+ }
+
+ public static void generateSuperClassAdds(PrintWriter writer, InterfaceDeclaration d) {
+ Collection super_interfaces = d.getSuperinterfaces();
+ if ( super_interfaces.size() > 1 )
+ throw new RuntimeException(d + " extends more than one other interface");
+ if ( super_interfaces.size() == 1 ) {
+ InterfaceType super_interface = super_interfaces.iterator().next();
+ writer.print("\t\tif (" + CACHED_EXTS_VAR_NAME + ".contains(\"");
+ writer.println(translateFieldName(d.getSimpleName()) + "\"))");
+ writer.print("\t\t\t");
+ generateAddExtension(writer, super_interface.getDeclaration());
+ }
+ }
+
+ public static void generateInitializer(PrintWriter writer, InterfaceDeclaration d) {
+ String translated_field_name = translateFieldName(d.getSimpleName());
+ writer.print("\t\tthis." + translated_field_name + " = ");
+ writer.print(CACHED_EXTS_VAR_NAME + ".contains(\"");
+ writer.print(translated_field_name + "\")");
+ Collection super_interfaces = d.getSuperinterfaces();
+ if ( super_interfaces.size() > 1 )
+ throw new RuntimeException(d + " extends more than one other interface");
+ if ( super_interfaces.size() == 1 ) {
+ InterfaceType super_interface = super_interfaces.iterator().next();
+ writer.println();
+ writer.print("\t\t\t&& " + CACHED_EXTS_VAR_NAME + ".contains(\"");
+ writer.print(translateFieldName(super_interface.getDeclaration().getSimpleName()) + "\")");
+ }
+ writer.println(";");
+ }
+
+ private static String getAddressesInitializerName(String class_name) {
+ return class_name + POINTER_INITIALIZER_POSTFIX;
+ }
+
+ public static void generateInitStubsPrologue(PrintWriter writer, boolean context_specific) {
+ writer.println("\tprivate Set " + ALL_INIT_METHOD_NAME + "(boolean forwardCompatible) throws LWJGLException {");
+
+ // Load the basic pointers we need to detect OpenGL version and supported extensions.
+ writer.println("\t\tGL11_glGetError_pointer = GLContext.getFunctionAddress(\"glGetError\");");
+ writer.println("\t\tGL11_glGetString_pointer = GLContext.getFunctionAddress(\"glGetString\");");
+
+ // Initialize GL11.glGetIntegerv and GL30.glGetStringi here, in case we have created an OpenGL 3.0 context.
+ // (they will be used in GLContext.getSupportedExtensions)
+ writer.println("\t\tGL11_glGetIntegerv_pointer = GLContext.getFunctionAddress(\"glGetIntegerv\");");
+ writer.println("\t\tGL30_glGetStringi_pointer = GLContext.getFunctionAddress(\"glGetStringi\");");
+
+ // Get the supported extensions set.
+ writer.println("\t\tGLContext.setCapabilities(this);");
+ writer.println("\t\tSet " + CACHED_EXTS_VAR_NAME + " = new HashSet(256);");
+ writer.println("\t\tint " + PROFILE_MASK_VAR_NAME + " = GLContext.getSupportedExtensions(" + CACHED_EXTS_VAR_NAME + ");");
+
+ // Force forward compatible mode when OpenGL version is 3.1 or higher and ARB_compatibility is not available.
+ writer.println("\t\tif ( supported_extensions.contains(\"OpenGL31\") && !(supported_extensions.contains(\"GL_ARB_compatibility\") || (profileMask & GL32.GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0) )");
+ writer.println("\t\t\tforwardCompatible = true;");
+
+ if ( !context_specific ) {
+ writer.println("\t\tif (" + STUBS_LOADED_NAME + ")");
+ writer.println("\t\t\treturn GLContext.getSupportedExtensions();");
+ writer.println("\t\torg.lwjgl.opengl.GL11." + Utils.STUB_INITIALIZER_NAME + "();");
+ } else {
+ writer.println("\t\tif (!" + getAddressesInitializerName("GL11") + "(forwardCompatible))");
+ writer.println("\t\t\tthrow new LWJGLException(\"GL11 not supported\");");
+ }
+ }
+
+ public static void generateInitStubsEpilogue(PrintWriter writer, boolean context_specific) {
+ if ( !context_specific ) {
+ writer.println("\t\t" + STUBS_LOADED_NAME + " = true;");
+ }
+ writer.println("\t\treturn " + CACHED_EXTS_VAR_NAME + ";");
+ writer.println("\t}");
+ }
+
+ public static void generateUnloadStubs(PrintWriter writer, InterfaceDeclaration d) {
+ if ( d.getMethods().size() > 0 ) {
+ writer.print("\t\tGLContext.resetNativeStubs(" + Utils.getSimpleClassName(d));
+ writer.println(".class);");
+ }
+ }
+
+ public static void generateInitStubs(PrintWriter writer, InterfaceDeclaration d, boolean context_specific) {
+ if ( d.getMethods().size() > 0 ) {
+ if ( context_specific ) {
+ if ( d.getAnnotation(ForceInit.class) != null )
+ writer.println("\t\t" + CACHED_EXTS_VAR_NAME + ".add(\"" + translateFieldName(d.getSimpleName()) + "\");");
+ writer.print("\t\tif (" + CACHED_EXTS_VAR_NAME + ".contains(\"");
+ writer.print(translateFieldName(d.getSimpleName()) + "\")");
+ writer.print(" && !" + getAddressesInitializerName(d.getSimpleName()) + "(");
+ if ( d.getAnnotation(DeprecatedGL.class) != null )
+ writer.print("forwardCompatible");
+ if ( d.getAnnotation(Dependent.class) != null ) {
+ if ( d.getAnnotation(DeprecatedGL.class) != null )
+ writer.print(",");
+ writer.print("supported_extensions");
+ }
+ writer.println("))");
+ //writer.print("\t\t\t" + CACHED_EXTS_VAR_NAME + ".remove(\"");
+ writer.print("\t\t\tremove(" + CACHED_EXTS_VAR_NAME + ", \"");
+ writer.println(translateFieldName(d.getSimpleName()) + "\");");
+ } else {
+ writer.print("\t\tGLContext." + Utils.STUB_INITIALIZER_NAME + "(" + Utils.getSimpleClassName(d));
+ writer.println(".class, " + CACHED_EXTS_VAR_NAME + ", \"" + translateFieldName(d.getSimpleName()) + "\");");
+ }
+ }
+ }
+
+ private static void generateAddExtension(PrintWriter writer, InterfaceDeclaration d) {
+ writer.print(CACHED_EXTS_VAR_NAME + ".add(\"");
+ writer.println(translateFieldName(d.getSimpleName()) + "\");");
+ }
+
+ public static void generateAddressesInitializers(PrintWriter writer, InterfaceDeclaration d) {
+ Iterator extends MethodDeclaration> methods = d.getMethods().iterator();
+ if ( !methods.hasNext() )
+ return;
+
+ writer.print("\tprivate boolean " + getAddressesInitializerName(d.getSimpleName()) + "(");
+
+ boolean optional;
+ boolean deprecated = d.getAnnotation(DeprecatedGL.class) != null;
+ Dependent dependent = d.getAnnotation(Dependent.class);
+ if ( deprecated )
+ writer.print("boolean forwardCompatible");
+ if ( dependent != null ) {
+ if ( deprecated )
+ writer.print(",");
+ writer.print("Set supported_extensions");
+ }
+
+ writer.println(") {");
+ writer.println("\t\treturn ");
+
+ boolean first = true;
+ while ( methods.hasNext() ) {
+ MethodDeclaration method = methods.next();
+ if ( method.getAnnotation(Alternate.class) != null )
+ continue;
+
+ if ( !first )
+ writer.println(" &");
+ else
+ first = false;
+
+ optional = method.getAnnotation(Optional.class) != null;
+ deprecated = method.getAnnotation(DeprecatedGL.class) != null;
+ dependent = method.getAnnotation(Dependent.class);
+
+ writer.print("\t\t\t(");
+ if ( optional )
+ writer.print('(');
+ if ( deprecated )
+ writer.print("forwardCompatible || ");
+ if ( dependent != null ) {
+ if ( dependent.value().indexOf(',') == -1 )
+ writer.print("!supported_extensions.contains(\"" + dependent.value() + "\") || ");
+ else {
+ writer.print("!(false");
+ for ( String extension : dependent.value().split(",") )
+ writer.print(" || supported_extensions.contains(\"" + extension + "\")");
+ writer.print(") || ");
+ }
+ }
+ if ( deprecated || dependent != null )
+ writer.print('(');
+ writer.print(Utils.getFunctionAddressName(d, method) + " = ");
+ PlatformDependent platform_dependent = method.getAnnotation(PlatformDependent.class);
+ if ( platform_dependent != null ) {
+ EnumSet platform_set = EnumSet.copyOf(Arrays.asList(platform_dependent.value()));
+ writer.print("GLContext.getPlatformSpecificFunctionAddress(\"");
+ writer.print(Platform.ALL.getPrefix() + "\", ");
+ writer.print("new String[]{");
+ Iterator platforms = platform_set.iterator();
+ while ( platforms.hasNext() ) {
+ writer.print("\"" + platforms.next().getOSPrefix() + "\"");
+ if ( platforms.hasNext() )
+ writer.print(", ");
+ }
+ writer.print("}, new String[]{");
+ platforms = platform_set.iterator();
+ while ( platforms.hasNext() ) {
+ writer.print("\"" + platforms.next().getPrefix() + "\"");
+ if ( platforms.hasNext() )
+ writer.print(", ");
+ }
+ writer.print("}, ");
+ } else
+ writer.print("GLContext.getFunctionAddress(");
+ writer.print("\"" + method.getSimpleName() + "\")) != 0");
+ if ( deprecated || dependent != null )
+ writer.print(')');
+ if ( optional )
+ writer.print(" || true)");
+ }
+ writer.println(";");
+ writer.println("\t}");
+ writer.println();
+ }
+
+ public static void generateSymbolAddresses(PrintWriter writer, InterfaceDeclaration d) {
+ for ( MethodDeclaration method : d.getMethods() ) {
+ if ( method.getAnnotation(Alternate.class) == null )
+ writer.println("\tlong " + Utils.getFunctionAddressName(d, method) + ";");
+ }
+ }
+
+ public static void generateField(PrintWriter writer, InterfaceDeclaration d) {
+ writer.println("\tpublic final boolean " + translateFieldName(d.getSimpleName()) + ";");
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/ContextGeneratorProcessorFactory.java b/src/java/org/lwjgl/util/generator/ContextGeneratorProcessorFactory.java
new file mode 100644
index 0000000..88813b9
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ContextGeneratorProcessorFactory.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import static java.util.Collections.unmodifiableCollection;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import com.sun.mirror.apt.AnnotationProcessor;
+import com.sun.mirror.apt.AnnotationProcessorEnvironment;
+import com.sun.mirror.apt.AnnotationProcessorFactory;
+import com.sun.mirror.apt.AnnotationProcessors;
+import com.sun.mirror.apt.Filer;
+import com.sun.mirror.apt.RoundCompleteEvent;
+import com.sun.mirror.apt.RoundCompleteListener;
+import com.sun.mirror.declaration.AnnotationTypeDeclaration;
+import com.sun.mirror.declaration.InterfaceDeclaration;
+import com.sun.mirror.declaration.TypeDeclaration;
+import com.sun.mirror.util.DeclarationFilter;
+
+/**
+ *
+ * Generator tool for creating the ContexCapabilities class
+ *
+ * @author elias_naur
+ * @version $Revision: 3316 $
+ * $Id: ContextGeneratorProcessorFactory.java 3316 2010-04-09 23:57:40Z spasi $
+ */
+public class ContextGeneratorProcessorFactory implements AnnotationProcessorFactory, RoundCompleteListener {
+ private static boolean first_round = true;
+
+ // Process any set of annotations
+ private static final Collection supportedAnnotations =
+ unmodifiableCollection(Arrays.asList("*"));
+
+ public Collection supportedAnnotationTypes() {
+ return supportedAnnotations;
+ }
+
+ public Collection supportedOptions() {
+ return unmodifiableCollection(Arrays.asList("-Acontextspecific", "-Ageneratechecks"));
+ }
+
+ public void roundComplete(RoundCompleteEvent event) {
+ first_round = false;
+ }
+
+ public AnnotationProcessor getProcessorFor(Set atds, AnnotationProcessorEnvironment env) {
+ // Only process the initial types, not the generated ones
+ if (first_round) {
+ env.addListener(this);
+ return new GeneratorProcessor(env);
+ } else
+ return AnnotationProcessors.NO_OP;
+ }
+
+ private static class GeneratorProcessor implements AnnotationProcessor {
+ private final AnnotationProcessorEnvironment env;
+
+ GeneratorProcessor(AnnotationProcessorEnvironment env) {
+ this.env = env;
+ }
+
+ public void process() {
+ Map options = env.getOptions();
+ boolean generate_error_checks = options.containsKey("-Ageneratechecks");
+ boolean context_specific = options.containsKey("-Acontextspecific");
+ try {
+ generateContextCapabilitiesSource(context_specific, generate_error_checks);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void generateContextCapabilitiesSource(boolean context_specific, boolean generate_error_checks) throws IOException {
+ PrintWriter writer = env.getFiler().createTextFile(Filer.Location.SOURCE_TREE, "org.lwjgl.opengl", new File(Utils.CONTEXT_CAPS_CLASS_NAME + ".java"), null);
+ writer.println("/* MACHINE GENERATED FILE, DO NOT EDIT */");
+ writer.println();
+ writer.println("package org.lwjgl.opengl;");
+ writer.println();
+ writer.println("import org.lwjgl.LWJGLException;");
+ writer.println("import org.lwjgl.LWJGLUtil;");
+ writer.println("import org.lwjgl.BufferUtils;");
+ writer.println("import java.util.Set;");
+ writer.println("import java.util.HashSet;");
+ writer.println("import java.nio.IntBuffer;");
+ writer.println();
+ ContextCapabilitiesGenerator.generateClassPrologue(writer, context_specific, generate_error_checks);
+ DeclarationFilter filter = DeclarationFilter.getFilter(InterfaceDeclaration.class);
+ Collection interface_decls = filter.filter(env.getSpecifiedTypeDeclarations());
+ for (TypeDeclaration typedecl : interface_decls) {
+ InterfaceDeclaration interface_decl = (InterfaceDeclaration)typedecl;
+ if (Utils.isFinal(interface_decl))
+ ContextCapabilitiesGenerator.generateField(writer, interface_decl);
+ }
+ writer.println();
+ for (TypeDeclaration typedecl : interface_decls) {
+ InterfaceDeclaration interface_decl = (InterfaceDeclaration)typedecl;
+ ContextCapabilitiesGenerator.generateSymbolAddresses(writer, interface_decl);
+ }
+ writer.println();
+ if (context_specific) {
+ for (TypeDeclaration typedecl : interface_decls) {
+ InterfaceDeclaration interface_decl = (InterfaceDeclaration)typedecl;
+ ContextCapabilitiesGenerator.generateAddressesInitializers(writer, interface_decl);
+ }
+ writer.println();
+ }
+
+ writer.println("\tprivate static void remove(Set supported_extensions, String extension) {");
+ writer.println("\t\tLWJGLUtil.log(extension + \" was reported as available but an entry point is missing\");");
+ writer.println("\t\tsupported_extensions.remove(extension);");
+ writer.println("\t}\n");
+
+ ContextCapabilitiesGenerator.generateInitStubsPrologue(writer, context_specific);
+ for (TypeDeclaration typedecl : interface_decls) {
+ InterfaceDeclaration interface_decl = (InterfaceDeclaration)typedecl;
+ ContextCapabilitiesGenerator.generateSuperClassAdds(writer, interface_decl);
+ }
+ for (TypeDeclaration typedecl : interface_decls) {
+ InterfaceDeclaration interface_decl = (InterfaceDeclaration)typedecl;
+ String simple_name = interface_decl.getSimpleName();
+ if (simple_name.equals("GL11"))
+ continue;
+ ContextCapabilitiesGenerator.generateInitStubs(writer, interface_decl, context_specific);
+ }
+ ContextCapabilitiesGenerator.generateInitStubsEpilogue(writer, context_specific);
+ writer.println();
+ writer.println("\tstatic void unloadAllStubs() {");
+ if (!context_specific) {
+ writer.println("\t\tif (!loaded_stubs)");
+ writer.println("\t\t\treturn;");
+ for (TypeDeclaration typedecl : interface_decls) {
+ InterfaceDeclaration interface_decl = (InterfaceDeclaration)typedecl;
+ ContextCapabilitiesGenerator.generateUnloadStubs(writer, interface_decl);
+ }
+ writer.println("\t\tloaded_stubs = false;");
+ }
+ writer.println("\t}");
+ writer.println();
+ ContextCapabilitiesGenerator.generateInitializerPrologue(writer);
+ for (TypeDeclaration typedecl : interface_decls) {
+ InterfaceDeclaration interface_decl = (InterfaceDeclaration)typedecl;
+ if (Utils.isFinal(interface_decl))
+ ContextCapabilitiesGenerator.generateInitializer(writer, interface_decl);
+ }
+ writer.println("\t\ttracker.init();");
+ writer.println("\t}");
+ writer.println("}");
+ writer.close();
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/util/generator/Dependent.java b/src/java/org/lwjgl/util/generator/Dependent.java
new file mode 100644
index 0000000..1741823
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Dependent.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ * Use this annotation on extensions with functionality that depends on the presence of other extensions.
+ * Functions in such extensions marked with this annotation will only be loaded if the specified extension is present.
+ *
+ * @author spasi
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target({ ElementType.TYPE, ElementType.METHOD })
+public @interface Dependent {
+ String value() default "";
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/DeprecatedGL.java b/src/java/org/lwjgl/util/generator/DeprecatedGL.java
new file mode 100644
index 0000000..4789d98
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/DeprecatedGL.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ * Use this annotation on extensions with deprecated functionality.
+ * Functions in such extensions marked with this annotation will not be loaded in a forward compatible context.
+ *
+ * @author spasi
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target({ ElementType.TYPE, ElementType.METHOD })
+public @interface DeprecatedGL {
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/Extension.java b/src/java/org/lwjgl/util/generator/Extension.java
new file mode 100644
index 0000000..2b9e5fa
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Extension.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: Extension.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.TYPE)
+public @interface Extension {
+ String className() default "";
+ boolean isFinal() default true;
+ String postfix();
+}
diff --git a/src/java/org/lwjgl/util/generator/FieldsGenerator.java b/src/java/org/lwjgl/util/generator/FieldsGenerator.java
new file mode 100644
index 0000000..42649f8
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/FieldsGenerator.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import com.sun.mirror.declaration.*;
+import com.sun.mirror.type.*;
+
+import java.io.*;
+import java.util.*;
+
+public class FieldsGenerator {
+ private static void validateField(FieldDeclaration field) {
+ Collection modifiers = field.getModifiers();
+ if (modifiers.size() != 3 || !modifiers.contains(Modifier.PUBLIC) || !modifiers.contains(Modifier.STATIC) ||
+ !modifiers.contains(Modifier.FINAL))
+ throw new RuntimeException("Field " + field.getSimpleName() + " is not declared public static final");
+ TypeMirror field_type = field.getType();
+ if (!(field_type instanceof PrimitiveType))
+ throw new RuntimeException("Field " + field.getSimpleName() + " is not a primitive type");
+ PrimitiveType field_type_prim = (PrimitiveType)field_type;
+ if (field_type_prim.getKind() != PrimitiveType.Kind.INT && field_type_prim.getKind() != PrimitiveType.Kind.LONG)
+ throw new RuntimeException("Field " + field.getSimpleName() + " is not of type 'int' or 'long'");
+ Object field_value = field.getConstantValue();
+ if (field_value == null)
+ throw new RuntimeException("Field " + field.getSimpleName() + " has no initial value");
+ }
+
+ private static void generateField(PrintWriter writer, FieldDeclaration field) {
+ validateField(field);
+
+ Object value = field.getConstantValue();
+ String field_value_string;
+ if ( value.getClass().equals(Integer.class) )
+ field_value_string = Integer.toHexString((Integer)field.getConstantValue());
+ else
+ field_value_string = Long.toHexString((Long)field.getConstantValue()) + 'l';
+
+ Utils.printDocComment(writer, field);
+ // Print field declaration
+ writer.println("\tpublic static final " + field.getType().toString() + " " + field.getSimpleName() + " = 0x" + field_value_string + ";");
+ }
+
+ public static void generateFields(PrintWriter writer, Collection fields) {
+ for (FieldDeclaration field : fields)
+ generateField(writer, field);
+ }
+
+}
diff --git a/src/java/org/lwjgl/util/generator/ForceInit.java b/src/java/org/lwjgl/util/generator/ForceInit.java
new file mode 100644
index 0000000..7173f6e
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/ForceInit.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ * Extensions marked with ForceInit will be initialized by LWJGL even if not exposed in the GL_EXTENSIONS string.
+ *
+ * @author spasi
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target({ ElementType.TYPE })
+public @interface ForceInit {
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GLTypeMap.java b/src/java/org/lwjgl/util/generator/GLTypeMap.java
new file mode 100644
index 0000000..0a61351
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLTypeMap.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * OpenGL sepcific generator behaviour
+ *
+ * @author elias_naur
+ * @version $Revision: 3287 $
+ * $Id: GLTypeMap.java 3287 2010-03-14 23:24:40Z spasi $
+ */
+
+import org.lwjgl.opengl.PointerWrapper;
+
+import java.io.PrintWriter;
+import java.nio.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.sun.mirror.declaration.AnnotationMirror;
+import com.sun.mirror.type.PrimitiveType;
+
+public class GLTypeMap implements TypeMap {
+
+ private static final Map native_types_to_primitive;
+
+ static {
+ native_types_to_primitive = new HashMap();
+ native_types_to_primitive.put(GLbitfield.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(GLcharARB.class, PrimitiveType.Kind.BYTE);
+ native_types_to_primitive.put(GLclampf.class, PrimitiveType.Kind.FLOAT);
+ native_types_to_primitive.put(GLfloat.class, PrimitiveType.Kind.FLOAT);
+ native_types_to_primitive.put(GLint.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(GLshort.class, PrimitiveType.Kind.SHORT);
+ native_types_to_primitive.put(GLsizeiptr.class, PrimitiveType.Kind.LONG);
+ native_types_to_primitive.put(GLuint.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(GLboolean.class, PrimitiveType.Kind.BOOLEAN);
+ native_types_to_primitive.put(GLchar.class, PrimitiveType.Kind.BYTE);
+ native_types_to_primitive.put(GLdouble.class, PrimitiveType.Kind.DOUBLE);
+ native_types_to_primitive.put(GLhalf.class, PrimitiveType.Kind.SHORT);
+ native_types_to_primitive.put(GLintptrARB.class, PrimitiveType.Kind.LONG);
+ native_types_to_primitive.put(GLsizei.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(GLushort.class, PrimitiveType.Kind.SHORT);
+ native_types_to_primitive.put(GLbyte.class, PrimitiveType.Kind.BYTE);
+ native_types_to_primitive.put(GLclampd.class, PrimitiveType.Kind.DOUBLE);
+ native_types_to_primitive.put(GLenum.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(GLhandleARB.class, PrimitiveType.Kind.INT);
+ native_types_to_primitive.put(GLintptr.class, PrimitiveType.Kind.LONG);
+ native_types_to_primitive.put(GLsizeiptrARB.class, PrimitiveType.Kind.LONG);
+ native_types_to_primitive.put(GLubyte.class, PrimitiveType.Kind.BYTE);
+ native_types_to_primitive.put(GLvoid.class, PrimitiveType.Kind.BYTE);
+ native_types_to_primitive.put(GLint64EXT.class, PrimitiveType.Kind.LONG);
+ native_types_to_primitive.put(GLuint64EXT.class, PrimitiveType.Kind.LONG);
+ native_types_to_primitive.put(GLint64.class, PrimitiveType.Kind.LONG);
+ native_types_to_primitive.put(GLuint64.class, PrimitiveType.Kind.LONG);
+ }
+
+ public PrimitiveType.Kind getPrimitiveTypeFromNativeType(Class native_type) {
+ PrimitiveType.Kind kind = native_types_to_primitive.get(native_type);
+ if ( kind == null )
+ throw new RuntimeException("Unsupported type " + native_type);
+ return kind;
+ }
+
+ public String getErrorCheckMethodName() {
+ return "Util.checkGLError()";
+ }
+
+ public String getRegisterNativesFunctionName() {
+ return "extgl_InitializeClass";
+ }
+
+ public Signedness getSignednessFromType(Class type) {
+ if ( GLuint.class.equals(type) )
+ return Signedness.UNSIGNED;
+ else if ( GLint.class.equals(type) )
+ return Signedness.SIGNED;
+ else if ( GLushort.class.equals(type) )
+ return Signedness.UNSIGNED;
+ else if ( GLshort.class.equals(type) )
+ return Signedness.SIGNED;
+ else if ( GLubyte.class.equals(type) )
+ return Signedness.UNSIGNED;
+ else if ( GLbyte.class.equals(type) )
+ return Signedness.SIGNED;
+ else if ( GLuint64EXT.class.equals(type) )
+ return Signedness.UNSIGNED;
+ else if ( GLint64EXT.class.equals(type) )
+ return Signedness.SIGNED;
+ else if ( GLuint64.class.equals(type) )
+ return Signedness.UNSIGNED;
+ else if ( GLint64.class.equals(type) )
+ return Signedness.SIGNED;
+ else
+ return Signedness.NONE;
+ }
+
+ public String translateAnnotation(Class annotation_type) {
+ if ( annotation_type.equals(GLuint.class) || annotation_type.equals(GLint.class) )
+ return "i";
+ else if ( annotation_type.equals(GLushort.class) || annotation_type.equals(GLshort.class) )
+ return "s";
+ else if ( annotation_type.equals(GLubyte.class) || annotation_type.equals(GLbyte.class) )
+ return "b";
+ else if ( annotation_type.equals(GLfloat.class) )
+ return "f";
+ else if ( annotation_type.equals(GLdouble.class) )
+ return "d";
+ else if ( annotation_type.equals(GLhalf.class) )
+ return "h";
+ else if ( annotation_type.equals(GLuint64EXT.class) || annotation_type.equals(GLint64EXT.class) || annotation_type.equals(GLuint64.class) || annotation_type.equals(GLint64.class) )
+ return "i64";
+ else if ( annotation_type.equals(GLboolean.class) || annotation_type.equals(GLvoid.class) )
+ return "";
+ else
+ throw new RuntimeException(annotation_type + " is not allowed");
+ }
+
+ public Class getNativeTypeFromPrimitiveType(PrimitiveType.Kind kind) {
+ Class type;
+ switch ( kind ) {
+ case INT:
+ type = GLint.class;
+ break;
+ case DOUBLE:
+ type = GLdouble.class;
+ break;
+ case FLOAT:
+ type = GLfloat.class;
+ break;
+ case SHORT:
+ type = GLshort.class;
+ break;
+ case BYTE:
+ type = GLbyte.class;
+ break;
+ case LONG:
+ type = GLint64EXT.class;
+ break;
+ case BOOLEAN:
+ type = GLboolean.class;
+ break;
+ default:
+ throw new RuntimeException(kind + " is not allowed");
+ }
+ return type;
+ }
+
+ public Class getVoidType() {
+ return GLvoid.class;
+ }
+
+ public Class getStringElementType() {
+ return GLubyte.class;
+ }
+
+ private static Class[] getValidBufferTypes(Class type) {
+ if ( type.equals(IntBuffer.class) )
+ return new Class[] { GLbitfield.class, GLenum.class, GLhandleARB.class, GLint.class,
+ GLsizei.class, GLuint.class, GLvoid.class };
+ else if ( type.equals(FloatBuffer.class) )
+ return new Class[] { GLclampf.class, GLfloat.class };
+ else if ( type.equals(ByteBuffer.class) )
+ return new Class[] { GLboolean.class, GLbyte.class, GLcharARB.class, GLchar.class, GLubyte.class, GLvoid.class };
+ else if ( type.equals(ShortBuffer.class) )
+ return new Class[] { GLhalf.class, GLshort.class, GLushort.class };
+ else if ( type.equals(DoubleBuffer.class) )
+ return new Class[] { GLclampd.class, GLdouble.class };
+ else if ( type.equals(LongBuffer.class) )
+ return new Class[] { GLint64EXT.class, GLuint64EXT.class, GLint64.class, GLuint64.class };
+ else
+ return new Class[] { };
+ }
+
+ private static Class[] getValidPrimitiveTypes(Class type) {
+ if ( type.equals(long.class) )
+ return new Class[] { GLintptrARB.class, GLuint.class, GLintptr.class, GLsizeiptrARB.class, GLsizeiptr.class, GLint64EXT.class, GLuint64EXT.class, GLint64.class, GLuint64.class };
+ else if ( type.equals(int.class) )
+ return new Class[] { GLbitfield.class, GLenum.class, GLhandleARB.class, GLint.class, GLuint.class,
+ GLsizei.class };
+ else if ( type.equals(double.class) )
+ return new Class[] { GLclampd.class, GLdouble.class };
+ else if ( type.equals(float.class) )
+ return new Class[] { GLclampf.class, GLfloat.class };
+ else if ( type.equals(short.class) )
+ return new Class[] { GLhalf.class, GLshort.class, GLushort.class };
+ else if ( type.equals(byte.class) )
+ return new Class[] { GLbyte.class, GLcharARB.class, GLchar.class, GLubyte.class };
+ else if ( type.equals(boolean.class) )
+ return new Class[] { GLboolean.class };
+ else if ( type.equals(void.class) )
+ return new Class[] { GLvoid.class, GLreturn.class };
+ else
+ return new Class[] { };
+ }
+
+ public String getTypedefPrefix() {
+ return "APIENTRY";
+ }
+
+ public void printNativeIncludes(PrintWriter writer) {
+ writer.println("#include \"extgl.h\"");
+ }
+
+ public Class[] getValidAnnotationTypes(Class type) {
+ Class[] valid_types;
+ if ( Buffer.class.isAssignableFrom(type) )
+ valid_types = getValidBufferTypes(type);
+ else if ( type.isPrimitive() )
+ valid_types = getValidPrimitiveTypes(type);
+ else if ( String.class.equals(type) )
+ valid_types = new Class[] { GLubyte.class };
+ else if ( PointerWrapper.class.isAssignableFrom(type) )
+ valid_types = new Class[] { GLpointer.class };
+ else if (void.class.equals(type) )
+ valid_types = new Class[] { GLreturn.class };
+ else
+ valid_types = new Class[] { };
+ return valid_types;
+ }
+
+ public Class getInverseType(Class type) {
+ if ( GLuint.class.equals(type) )
+ return GLint.class;
+ else if ( GLint.class.equals(type) )
+ return GLuint.class;
+ else if ( GLushort.class.equals(type) )
+ return GLshort.class;
+ else if ( GLshort.class.equals(type) )
+ return GLushort.class;
+ else if ( GLubyte.class.equals(type) )
+ return GLbyte.class;
+ else if ( GLbyte.class.equals(type) )
+ return GLubyte.class;
+ else if ( GLuint64EXT.class.equals(type) )
+ return GLint64EXT.class;
+ else if ( GLint64EXT.class.equals(type) )
+ return GLuint64EXT.class;
+ else if ( GLuint64.class.equals(type) )
+ return GLint64.class;
+ else if ( GLint64.class.equals(type) )
+ return GLuint64.class;
+ else
+ return null;
+ }
+
+ public String getAutoTypeFromAnnotation(AnnotationMirror annotation) {
+ Class annotation_class = NativeTypeTranslator.getClassFromType(annotation.getAnnotationType());
+ if ( annotation_class.equals(GLint.class) )
+ return "GL11.GL_INT";
+ else if ( annotation_class.equals(GLbyte.class) )
+ return "GL11.GL_BYTE";
+ else if ( annotation_class.equals(GLshort.class) )
+ return "GL11.GL_SHORT";
+ if ( annotation_class.equals(GLuint.class) )
+ return "GL11.GL_UNSIGNED_INT";
+ else if ( annotation_class.equals(GLubyte.class) )
+ return "GL11.GL_UNSIGNED_BYTE";
+ else if ( annotation_class.equals(GLushort.class) )
+ return "GL11.GL_UNSIGNED_SHORT";
+ else if ( annotation_class.equals(GLfloat.class) )
+ return "GL11.GL_FLOAT";
+ else if ( annotation_class.equals(GLdouble.class) )
+ return "GL11.GL_DOUBLE";
+ else
+ return null;
+ }
+}
diff --git a/src/java/org/lwjgl/util/generator/GLbitfield.java b/src/java/org/lwjgl/util/generator/GLbitfield.java
new file mode 100644
index 0000000..4522a5e
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLbitfield.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLbitfield.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLbitfield {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLboolean.java b/src/java/org/lwjgl/util/generator/GLboolean.java
new file mode 100644
index 0000000..b685412
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLboolean.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLboolean.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLboolean {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLbyte.java b/src/java/org/lwjgl/util/generator/GLbyte.java
new file mode 100644
index 0000000..ab3c473
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLbyte.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLbyte.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLbyte {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLchar.java b/src/java/org/lwjgl/util/generator/GLchar.java
new file mode 100644
index 0000000..9263c83
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLchar.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLchar.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLchar {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLcharARB.java b/src/java/org/lwjgl/util/generator/GLcharARB.java
new file mode 100644
index 0000000..285e5d6
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLcharARB.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLcharARB.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLcharARB {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLclampd.java b/src/java/org/lwjgl/util/generator/GLclampd.java
new file mode 100644
index 0000000..429b49f
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLclampd.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLclampd.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLclampd {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLclampf.java b/src/java/org/lwjgl/util/generator/GLclampf.java
new file mode 100644
index 0000000..356cea8
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLclampf.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLclampf.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLclampf {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLdouble.java b/src/java/org/lwjgl/util/generator/GLdouble.java
new file mode 100644
index 0000000..b3622ec
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLdouble.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLdouble.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLdouble {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLenum.java b/src/java/org/lwjgl/util/generator/GLenum.java
new file mode 100644
index 0000000..f7f68d8
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLenum.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLenum.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLenum {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLfloat.java b/src/java/org/lwjgl/util/generator/GLfloat.java
new file mode 100644
index 0000000..fe351a9
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLfloat.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLfloat.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLfloat {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLhalf.java b/src/java/org/lwjgl/util/generator/GLhalf.java
new file mode 100644
index 0000000..bf54627
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLhalf.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLhalf.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLhalf {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLhandleARB.java b/src/java/org/lwjgl/util/generator/GLhandleARB.java
new file mode 100644
index 0000000..e4c388d
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLhandleARB.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLhandleARB.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLhandleARB {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLint.java b/src/java/org/lwjgl/util/generator/GLint.java
new file mode 100644
index 0000000..8321875
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLint.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLint.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLint {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLint64.java b/src/java/org/lwjgl/util/generator/GLint64.java
new file mode 100644
index 0000000..75fc705
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLint64.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLint64 {
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GLint64EXT.java b/src/java/org/lwjgl/util/generator/GLint64EXT.java
new file mode 100644
index 0000000..7c96212
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLint64EXT.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLint64EXT {
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GLintptr.java b/src/java/org/lwjgl/util/generator/GLintptr.java
new file mode 100644
index 0000000..fa8afe1
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLintptr.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLintptr.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLintptr {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLintptrARB.java b/src/java/org/lwjgl/util/generator/GLintptrARB.java
new file mode 100644
index 0000000..f88a54a
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLintptrARB.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLintptrARB.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLintptrARB {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLpointer.java b/src/java/org/lwjgl/util/generator/GLpointer.java
new file mode 100644
index 0000000..d42f590
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLpointer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ * @author spasi
+ */
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLpointer {
+ String value(); // The native pointer type.
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GLreturn.java b/src/java/org/lwjgl/util/generator/GLreturn.java
new file mode 100644
index 0000000..51fd9e8
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLreturn.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ * When a method is annonated with @GLreturn, the specified output Buffer parameter
+ * will be used to return a single value. The primitive type will match the Buffer type.
+ * String will be returned if the Buffer is a ByteBuffer annotated with @GLchar.
+ *
+ * @author spasi
+ */
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@NativeType
+@Target({ ElementType.METHOD })
+public @interface GLreturn {
+ /** The Buffer parameter to use as the method result. */
+ String value();
+ /** The argument that specifies the maximum number of bytes that may be read (String results only). */
+ String maxLength() default "";
+ /** If true, the maxLength value is going to be used when creating the String. */
+ boolean forceMaxLength() default false;
+ ///** If we use the byte buffer for another parameter, an offset must be used. */
+ //String offset() default "";
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GLshort.java b/src/java/org/lwjgl/util/generator/GLshort.java
new file mode 100644
index 0000000..099f6e4
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLshort.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLshort.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLshort {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLsizei.java b/src/java/org/lwjgl/util/generator/GLsizei.java
new file mode 100644
index 0000000..8831151
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLsizei.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLsizei.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLsizei {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLsizeiptr.java b/src/java/org/lwjgl/util/generator/GLsizeiptr.java
new file mode 100644
index 0000000..b5169a3
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLsizeiptr.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLsizeiptr.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLsizeiptr {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLsizeiptrARB.java b/src/java/org/lwjgl/util/generator/GLsizeiptrARB.java
new file mode 100644
index 0000000..9a24cf0
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLsizeiptrARB.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLsizeiptrARB.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLsizeiptrARB {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLtime.java b/src/java/org/lwjgl/util/generator/GLtime.java
new file mode 100644
index 0000000..81506f1
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLtime.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ * Unsigned binary representing an absolute absolute or relative time interval.
+ * Precision is nanoseconds but accuracy is implementation-dependent.
+ *
+ * @author spasi
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLtime {
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GLubyte.java b/src/java/org/lwjgl/util/generator/GLubyte.java
new file mode 100644
index 0000000..b093b91
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLubyte.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLubyte.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLubyte {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLuint.java b/src/java/org/lwjgl/util/generator/GLuint.java
new file mode 100644
index 0000000..5a6adcc
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLuint.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLuint.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLuint {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLuint64.java b/src/java/org/lwjgl/util/generator/GLuint64.java
new file mode 100644
index 0000000..0cd089c
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLuint64.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLuint64 {
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GLuint64EXT.java b/src/java/org/lwjgl/util/generator/GLuint64EXT.java
new file mode 100644
index 0000000..0eae8e6
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLuint64EXT.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLuint64EXT {
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GLushort.java b/src/java/org/lwjgl/util/generator/GLushort.java
new file mode 100644
index 0000000..171f0ff
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLushort.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GLushort.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLushort {
+}
diff --git a/src/java/org/lwjgl/util/generator/GLvoid.java b/src/java/org/lwjgl/util/generator/GLvoid.java
new file mode 100644
index 0000000..d5c3113
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GLvoid.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 3279 $
+ * $Id: GLvoid.java 3279 2010-03-11 21:06:49Z spasi $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+import com.sun.mirror.type.PrimitiveType;
+
+@NativeType
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+public @interface GLvoid {
+ PrimitiveType.Kind value() default PrimitiveType.Kind.BYTE;
+}
diff --git a/src/java/org/lwjgl/util/generator/GenerateAutos.java b/src/java/org/lwjgl/util/generator/GenerateAutos.java
new file mode 100644
index 0000000..de22669
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GenerateAutos.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: GenerateAutos.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.METHOD)
+public @interface GenerateAutos {
+}
diff --git a/src/java/org/lwjgl/util/generator/GeneratorProcessorFactory.java b/src/java/org/lwjgl/util/generator/GeneratorProcessorFactory.java
new file mode 100644
index 0000000..a57a208
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GeneratorProcessorFactory.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import com.sun.mirror.apt.*;
+import com.sun.mirror.declaration.*;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Collection;
+import java.util.Set;
+import java.util.Map;
+import java.util.Arrays;
+
+import static java.util.Collections.*;
+import static com.sun.mirror.util.DeclarationVisitors.*;
+
+/**
+ *
+ * Generator tool for creating the java classes and native code
+ * from an annotated template java interface.
+ *
+ * @author elias_naur
+ * @version $Revision: 3289 $
+ * $Id: GeneratorProcessorFactory.java 3289 2010-03-16 19:05:19Z spasi $
+ */
+public class GeneratorProcessorFactory implements AnnotationProcessorFactory, RoundCompleteListener {
+ private static boolean first_round = true;
+
+ // Process any set of annotations
+ private static final Collection supportedAnnotations =
+ unmodifiableCollection(Arrays.asList("*"));
+
+ private static final Collection supportedOptions =
+ unmodifiableCollection(Arrays.asList("-Atypemap", "-Ageneratechecks", "-Acontextspecific"));
+
+ public Collection supportedAnnotationTypes() {
+ return supportedAnnotations;
+ }
+
+ public Collection supportedOptions() {
+ return supportedOptions;
+ }
+
+ public void roundComplete(RoundCompleteEvent event) {
+ first_round = false;
+ }
+
+ public AnnotationProcessor getProcessorFor(Set atds, AnnotationProcessorEnvironment env) {
+ // Only process the initial types, not the generated ones
+ if (first_round) {
+ env.addListener(this);
+ return new GeneratorProcessor(env);
+ } else
+ return AnnotationProcessors.NO_OP;
+ }
+
+ private static class GeneratorProcessor implements AnnotationProcessor {
+ private final AnnotationProcessorEnvironment env;
+
+ GeneratorProcessor(AnnotationProcessorEnvironment env) {
+ this.env = env;
+ }
+
+ public void process() {
+ Map options = env.getOptions();
+ String typemap_classname = null;
+ boolean generate_error_checks = options.containsKey("-Ageneratechecks");
+ boolean context_specific = options.containsKey("-Acontextspecific");
+ for (String k : options.keySet()) {
+ int delimiter = k.indexOf('=');
+ if (delimiter != -1) {
+ if (k.startsWith("-Atypemap")) {
+ typemap_classname = k.substring(delimiter + 1);
+ }
+ }
+ }
+ if (typemap_classname == null)
+ throw new RuntimeException("No TypeMap class name specified with -Atypemap=");
+
+ TypeDeclaration lastFile = null;
+ try {
+ long generatorLM = getGeneratorLastModified();
+ TypeMap type_map = (TypeMap)(Class.forName(typemap_classname).newInstance());
+ for (TypeDeclaration typedecl : env.getSpecifiedTypeDeclarations()) {
+ lastFile = typedecl;
+ typedecl.accept(getDeclarationScanner(new GeneratorVisitor(env, type_map, generate_error_checks, context_specific, generatorLM), NO_OP));
+ }
+ } catch (Exception e) {
+ if ( lastFile == null )
+ throw new RuntimeException(e);
+ else
+ throw new RuntimeException("\n-- Failed to process template: " + lastFile.getQualifiedName() + " --", e);
+ }
+ }
+
+ /**
+ * Gets the time of the latest change on the Generator classes.
+ *
+ * @return time of the latest change
+ */
+ private static long getGeneratorLastModified() {
+ final File pck = new File(System.getProperty("user.dir") + "/bin/org/lwjgl/util/generator");
+ if ( !pck.exists() || !pck.isDirectory() )
+ return Long.MAX_VALUE;
+
+ final File[] classes = pck.listFiles(new FileFilter() {
+ public boolean accept(final File pathname) {
+ return pathname.isFile() && pathname.getName().endsWith(".class");
+ }
+ });
+
+ if ( classes == null || classes.length == 0 )
+ return Long.MAX_VALUE;
+
+ long lastModified = 0;
+
+ for ( File clazz : classes ) {
+ long lm = clazz.lastModified();
+ if ( lastModified < lm )
+ lastModified = lm;
+ }
+
+ return lastModified;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/util/generator/GeneratorVisitor.java b/src/java/org/lwjgl/util/generator/GeneratorVisitor.java
new file mode 100644
index 0000000..93f6b31
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/GeneratorVisitor.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import com.sun.mirror.apt.*;
+import com.sun.mirror.declaration.*;
+import com.sun.mirror.type.*;
+import com.sun.mirror.util.*;
+
+import java.util.*;
+
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.io.File;
+
+import java.nio.*;
+
+/**
+ *
+ * Generator visitor for the generator tool
+ *
+ * @author elias_naur
+ * @version $Revision: 3299 $
+ * $Id: GeneratorVisitor.java 3299 2010-03-31 15:46:16Z spasi $
+ */
+public class GeneratorVisitor extends SimpleDeclarationVisitor {
+ private final AnnotationProcessorEnvironment env;
+ private final TypeMap type_map;
+ private final boolean generate_error_checks;
+ private final boolean context_specific;
+ private final long generatorLM;
+
+ public GeneratorVisitor(AnnotationProcessorEnvironment env, TypeMap type_map, boolean generate_error_checks, boolean context_specific, long generatorLM) {
+ this.env = env;
+ this.type_map = type_map;
+ this.generate_error_checks = generate_error_checks;
+ this.context_specific = context_specific;
+ this.generatorLM = generatorLM;
+ }
+
+ private void validateMethods(InterfaceDeclaration d) {
+ for (MethodDeclaration method : d.getMethods())
+ validateMethod(method);
+ }
+
+ private void validateMethod(MethodDeclaration method) {
+ if (method.isVarArgs())
+ throw new RuntimeException("Method " + method.getSimpleName() + " is variadic");
+ Collection modifiers = method.getModifiers();
+ if (!modifiers.contains(Modifier.PUBLIC))
+ throw new RuntimeException("Method " + method.getSimpleName() + " is not public");
+ if (method.getThrownTypes().size() > 0)
+ throw new RuntimeException("Method " + method.getSimpleName() + " throws checked exceptions");
+ validateParameters(method);
+ StripPostfix strip_annotation = method.getAnnotation(StripPostfix.class);
+ if (strip_annotation != null && method.getAnnotation(Alternate.class) == null) {
+ String postfix_param_name = strip_annotation.value();
+ ParameterDeclaration postfix_param = Utils.findParameter(method, postfix_param_name);
+ if (Utils.isParameterMultiTyped(postfix_param))
+ throw new RuntimeException("Postfix parameter can't be the same as a multityped parameter in method " + method);
+ if (Utils.getNIOBufferType(postfix_param.getType()) == null)
+ throw new RuntimeException("Postfix parameter type must be a nio Buffer");
+ }
+ if (Utils.getResultParameter(method) != null && !method.getReturnType().equals(env.getTypeUtils().getVoidType()))
+ throw new RuntimeException(method + " return type is not void but a parameter is annotated with Result");
+ if (method.getAnnotation(CachedResult.class) != null) {
+ if (Utils.getNIOBufferType(Utils.getMethodReturnType(method)) == null)
+ throw new RuntimeException(method + " return type is not a Buffer, but is annotated with CachedResult");
+ if (method.getAnnotation(AutoResultSize.class) == null)
+ throw new RuntimeException(method + " is annotated with CachedResult but misses an AutoResultSize annotation");
+ }
+ validateTypes(method, method.getAnnotationMirrors(), method.getReturnType());
+ }
+
+ private void validateType(MethodDeclaration method, Class annotation_type, Class type) {
+ Class[] valid_types = type_map.getValidAnnotationTypes(type);
+ for (int i = 0; i < valid_types.length; i++)
+ if (valid_types[i].equals(annotation_type))
+ return;
+ throw new RuntimeException(type + " is annotated with invalid native type " + annotation_type +
+ " in method " + method);
+ }
+
+ private void validateTypes(MethodDeclaration method, Collection annotations, TypeMirror type_mirror) {
+ for (AnnotationMirror annotation : annotations) {
+ NativeType native_type_annotation = NativeTypeTranslator.getAnnotation(annotation, NativeType.class);
+ if (native_type_annotation != null) {
+ Class annotation_type = NativeTypeTranslator.getClassFromType(annotation.getAnnotationType());
+ Class type = Utils.getJavaType(type_mirror);
+ if (Buffer.class.equals(type))
+ continue;
+ validateType(method, annotation_type, type);
+ }
+ }
+ }
+
+ private void validateParameters(MethodDeclaration method) {
+ for (ParameterDeclaration param : method.getParameters()) {
+ validateTypes(method, param.getAnnotationMirrors(), param.getType());
+ Class> param_type = Utils.getJavaType(param.getType());
+ if (Utils.getNIOBufferType(param.getType()) != null && param_type != CharSequence.class && param_type != CharSequence[].class) {
+ Check parameter_check_annotation = param.getAnnotation(Check.class);
+ NullTerminated null_terminated_annotation = param.getAnnotation(NullTerminated.class);
+ if (parameter_check_annotation == null && null_terminated_annotation == null) {
+ boolean found_auto_size_param = false;
+ for (ParameterDeclaration inner_param : method.getParameters()) {
+ AutoSize auto_size_annotation = inner_param.getAnnotation(AutoSize.class);
+ if (auto_size_annotation != null &&
+ auto_size_annotation.value().equals(param.getSimpleName())) {
+ found_auto_size_param = true;
+ break;
+ }
+ }
+ if (!found_auto_size_param
+ && param.getAnnotation(Result.class) == null
+ && param.getAnnotation(Constant.class) == null
+ && !Utils.isReturnParameter(method, param)
+ )
+ throw new RuntimeException(param + " has no Check, Result nor Constant annotation, is not the return parameter and no other parameter has" +
+ " an @AutoSize annotation on it in method " + method);
+ }
+ if (param.getAnnotation(CachedReference.class) != null && param.getAnnotation(Result.class) != null)
+ throw new RuntimeException(param + " can't be annotated with both CachedReference and Result");
+ if (param.getAnnotation(BufferObject.class) != null && param.getAnnotation(Result.class) != null)
+ throw new RuntimeException(param + " can't be annotated with both BufferObject and Result");
+ //if (param.getAnnotation(Constant.class) != null)
+ //throw new RuntimeException("Buffer parameter " + param + " cannot be Constant");
+ } else {
+ if (param.getAnnotation(BufferObject.class) != null)
+ throw new RuntimeException(param + " type is not a buffer, but annotated as a BufferObject");
+ if (param.getAnnotation(CachedReference.class) != null)
+ throw new RuntimeException(param + " type is not a buffer, but annotated as a CachedReference");
+ }
+ }
+ }
+
+ private static void generateMethodsNativePointers(PrintWriter writer, Collection extends MethodDeclaration> methods) {
+ for (MethodDeclaration method : methods) {
+ if ( method.getAnnotation(Alternate.class) == null )
+ generateMethodNativePointers(writer, method);
+ }
+ }
+
+ private static void generateMethodNativePointers(PrintWriter writer, MethodDeclaration method) {
+ writer.println("static " + Utils.getTypedefName(method) + " " + method.getSimpleName() + ";");
+ }
+
+ private void generateJavaSource(InterfaceDeclaration d, PrintWriter java_writer) throws IOException {
+ java_writer.println("/* MACHINE GENERATED FILE, DO NOT EDIT */");
+ java_writer.println();
+ java_writer.println("package " + d.getPackage().getQualifiedName() + ";");
+ java_writer.println();
+ java_writer.println("import org.lwjgl.LWJGLException;");
+ java_writer.println("import org.lwjgl.BufferChecks;");
+ // DISABLED: indirect buffer support
+ //java_writer.println("import org.lwjgl.NondirectBufferWrapper;");
+ java_writer.println("import java.nio.*;");
+ java_writer.println();
+ Utils.printDocComment(java_writer, d);
+ java_writer.print("public ");
+ boolean is_final = Utils.isFinal(d);
+ if (is_final)
+ java_writer.write("final ");
+ java_writer.print("class " + Utils.getSimpleClassName(d));
+ Collection super_interfaces = d.getSuperinterfaces();
+ if (super_interfaces.size() > 1)
+ throw new RuntimeException(d + " extends more than one interface");
+ if (super_interfaces.size() == 1) {
+ InterfaceDeclaration super_interface = super_interfaces.iterator().next().getDeclaration();
+ java_writer.print(" extends " + Utils.getSimpleClassName(super_interface));
+ }
+ java_writer.println(" {");
+ FieldsGenerator.generateFields(java_writer, d.getFields());
+ java_writer.println();
+ if (is_final) {
+ // Write private constructor to avoid instantiation
+ java_writer.println("\tprivate " + Utils.getSimpleClassName(d) + "() {");
+ java_writer.println("\t}");
+ java_writer.println();
+ }
+ if (d.getMethods().size() > 0 && !context_specific)
+ java_writer.println("\tstatic native void " + Utils.STUB_INITIALIZER_NAME + "() throws LWJGLException;");
+ JavaMethodsGenerator.generateMethodsJava(env, type_map, java_writer, d, generate_error_checks, context_specific);
+ java_writer.println("}");
+ java_writer.close();
+ String qualified_interface_name = Utils.getQualifiedClassName(d);
+ env.getMessager().printNotice("Generated class " + qualified_interface_name);
+ }
+
+ private void generateNativeSource(InterfaceDeclaration d) throws IOException {
+ String qualified_interface_name = Utils.getQualifiedClassName(d);
+ String qualified_native_name = Utils.getNativeQualifiedName(qualified_interface_name)+ ".c";
+ PrintWriter native_writer = env.getFiler().createTextFile(Filer.Location.CLASS_TREE, "", new File(qualified_native_name), "UTF-8");
+ native_writer.println("/* MACHINE GENERATED FILE, DO NOT EDIT */");
+ native_writer.println();
+ native_writer.println("#include ");
+ type_map.printNativeIncludes(native_writer);
+ native_writer.println();
+ TypedefsGenerator.generateNativeTypedefs(type_map, native_writer, d.getMethods());
+ native_writer.println();
+ if (!context_specific) {
+ generateMethodsNativePointers(native_writer, d.getMethods());
+ native_writer.println();
+ }
+ NativeMethodStubsGenerator.generateNativeMethodStubs(env, type_map, native_writer, d, generate_error_checks, context_specific);
+ if (!context_specific) {
+ native_writer.print("JNIEXPORT void JNICALL " + Utils.getQualifiedNativeMethodName(qualified_interface_name, Utils.STUB_INITIALIZER_NAME));
+ native_writer.println("(JNIEnv *env, jclass clazz) {");
+ native_writer.println("\tJavaMethodAndExtFunction functions[] = {");
+ RegisterStubsGenerator.generateMethodsNativeStubBind(native_writer, d, generate_error_checks, context_specific);
+ native_writer.println("\t};");
+ native_writer.println("\tint num_functions = NUMFUNCTIONS(functions);");
+ native_writer.print("\t");
+ native_writer.print(type_map.getRegisterNativesFunctionName());
+ native_writer.println("(env, clazz, num_functions, functions);");
+ native_writer.println("}");
+ }
+ native_writer.close();
+ env.getMessager().printNotice("Generated C source " + qualified_interface_name);
+ }
+
+ public void visitInterfaceDeclaration(InterfaceDeclaration d) {
+ File input = d.getPosition().file();
+ File output = new File(env.getOptions().get("-s") + '/' + d.getPackage().getQualifiedName().replace('.', '/'), Utils.getSimpleClassName(d) + ".java");
+
+ PrintWriter java_writer = null;
+
+ try {
+ // Skip this class if the output exists and the input has not been modified.
+ if ( output.exists() && Math.max(input.lastModified(), generatorLM) < output.lastModified() )
+ return;
+
+ if (d.getMethods().size() > 0 || d.getFields().size() > 0) {
+ validateMethods(d);
+ java_writer = env.getFiler().createTextFile(Filer.Location.SOURCE_TREE, d.getPackage().getQualifiedName(), new File(Utils.getSimpleClassName(d) + ".java"), null);
+ generateJavaSource(d, java_writer);
+ }
+ if (d.getMethods().size() > 0)
+ generateNativeSource(d);
+ } catch (Exception e) {
+ // If anything goes wrong mid-gen, delete output to allow regen next time we run.
+ if ( java_writer != null ) java_writer.close();
+ if ( output.exists() ) output.delete();
+
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/util/generator/Indirect.java b/src/java/org/lwjgl/util/generator/Indirect.java
new file mode 100644
index 0000000..4bbbc01
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/Indirect.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * Implies that a parameter is indirect, and forces the native
+ * stub to use the indirection operator '&' on it.
+ *
+ * @author elias_naur
+ * @version $Revision: 2983 $
+ * $Id: Indirect.java 2983 2008-04-07 18:36:09Z matzon $
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target(ElementType.PARAMETER)
+public @interface Indirect {
+}
diff --git a/src/java/org/lwjgl/util/generator/JNITypeTranslator.java b/src/java/org/lwjgl/util/generator/JNITypeTranslator.java
new file mode 100644
index 0000000..c5d72bb
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/JNITypeTranslator.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+import com.sun.mirror.type.*;
+import com.sun.mirror.util.*;
+
+/**
+ *
+ * A TypeVisitor that translates TypeMirrors to JNI
+ * type strings.
+ *
+ * @author elias_naur
+ * @version $Revision: 3281 $
+ * $Id: JNITypeTranslator.java 3281 2010-03-12 21:55:13Z spasi $
+ */
+public class JNITypeTranslator implements TypeVisitor {
+ private final StringBuilder signature = new StringBuilder();
+
+ public String getSignature() {
+ return signature.toString();
+ }
+
+ public void visitAnnotationType(AnnotationType t) {
+ throw new RuntimeException(t + " is not allowed");
+ }
+
+ public void visitArrayType(ArrayType t) {
+ if ( "java.lang.CharSequence".equals(t.getComponentType().toString()) )
+ signature.append("jobject");
+ else
+ throw new RuntimeException(t + " is not allowed");
+ }
+
+ public void visitClassType(ClassType t) {
+ signature.append("jobject");
+ }
+
+ public void visitDeclaredType(DeclaredType t) {
+ throw new RuntimeException(t + " is not allowed");
+ }
+
+ public void visitEnumType(EnumType t) {
+ throw new RuntimeException(t + " is not allowed");
+ }
+
+ public void visitInterfaceType(InterfaceType t) {
+ throw new RuntimeException(t + " is not allowed");
+ }
+
+ public void visitPrimitiveType(PrimitiveType t) {
+ String type;
+ switch (t.getKind()) {
+ case LONG:
+ type = "jlong";
+ break;
+ case INT:
+ type = "jint";
+ break;
+ case FLOAT:
+ type = "jfloat";
+ break;
+ case SHORT:
+ type = "jshort";
+ break;
+ case BYTE:
+ type = "jbyte";
+ break;
+ case DOUBLE:
+ type = "jdouble";
+ break;
+ case BOOLEAN:
+ type = "jboolean";
+ break;
+ default:
+ throw new RuntimeException(t + " is not allowed");
+ }
+ signature.append(type);
+ }
+
+ public void visitReferenceType(ReferenceType t) {
+ throw new RuntimeException(t + " is not allowed");
+ }
+
+ public void visitTypeMirror(TypeMirror t) {
+ throw new RuntimeException(t + " is not allowed");
+ }
+
+ public void visitTypeVariable(TypeVariable t) {
+ throw new RuntimeException(t + " is not allowed");
+ }
+
+ public void visitVoidType(VoidType t) {
+ signature.append(t.toString());
+ }
+
+ public void visitWildcardType(WildcardType t) {
+ throw new RuntimeException(t + " is not allowed");
+ }
+}
diff --git a/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java b/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java
new file mode 100644
index 0000000..5f86429
--- /dev/null
+++ b/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 2002-2008 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.util.generator;
+
+/**
+ *
+ * This class generates the methods in the generated java source files.
+ *
+ * @author elias_naur
+ * @version $Revision: 3293 $
+ * $Id: JavaMethodsGenerator.java 3293 2010-03-23 12:43:44Z spasi $
+ */
+
+import com.sun.mirror.apt.*;
+import com.sun.mirror.declaration.*;
+import com.sun.mirror.type.*;
+
+import java.io.*;
+import java.util.*;
+import java.nio.*;
+
+public class JavaMethodsGenerator {
+ private final static String SAVED_PARAMETER_POSTFIX = "_saved";
+
+ public static void generateMethodsJava(AnnotationProcessorEnvironment env, TypeMap type_map, PrintWriter writer, InterfaceDeclaration interface_decl, boolean generate_error_checks, boolean context_specific) {
+ for (MethodDeclaration method : interface_decl.getMethods())
+ generateMethodJava(env, type_map, writer, interface_decl, method, generate_error_checks, context_specific);
+ }
+
+ private static void generateMethodJava(AnnotationProcessorEnvironment env, TypeMap type_map, PrintWriter writer, InterfaceDeclaration interface_decl, MethodDeclaration method, boolean generate_error_checks, boolean context_specific) {
+ writer.println();
+ if (Utils.isMethodIndirect(generate_error_checks, context_specific, method)) {
+ if (method.getAnnotation(GenerateAutos.class) != null) {
+ printMethodWithMultiType(env, type_map, writer, interface_decl, method, TypeInfo.getDefaultTypeInfoMap(method), Mode.AUTOS, generate_error_checks, context_specific);
+ }
+ Collection