diff --git a/build.xml b/build.xml index 995daae7..442ea159 100644 --- a/build.xml +++ b/build.xml @@ -71,10 +71,43 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + @@ -97,29 +130,6 @@ - - - - - - - - - - - - - - - - - - - - - - - @@ -456,11 +466,11 @@ - - + + - + @@ -528,7 +538,7 @@ - + @@ -597,24 +607,24 @@ - + - + - + - + - + diff --git a/platform_build/build-definitions.xml b/platform_build/build-definitions.xml index 691d1721..426ab048 100644 --- a/platform_build/build-definitions.xml +++ b/platform_build/build-definitions.xml @@ -185,7 +185,7 @@ - + diff --git a/run-test.sh b/run-test.sh new file mode 100755 index 00000000..e9dc09b8 --- /dev/null +++ b/run-test.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -e + +java -cp res:target/jars/lwjgl.jar:target/jars/lwjgl_util.jar:target/jars/lwjgl_test.jar:lib/jinput.jar -Dorg.lwjgl.util.Debug=true -Djava.library.path=target/natives "$@" diff --git a/src/java/org/lwjgl/input/Cursor.java b/src/java/org/lwjgl/input/Cursor.java index e352b572..ed0d9275 100644 --- a/src/java/org/lwjgl/input/Cursor.java +++ b/src/java/org/lwjgl/input/Cursor.java @@ -119,11 +119,9 @@ public class Cursor { * @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(); - } + if (!Mouse.isCreated()) + throw new IllegalStateException("Mouse must be created."); + return Mouse.getImplementation().getMinCursorSize(); } /** @@ -134,11 +132,9 @@ public class Cursor { * @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(); - } + if (!Mouse.isCreated()) + throw new IllegalStateException("Mouse must be created."); + return Mouse.getImplementation().getMaxCursorSize(); } /** @@ -150,11 +146,10 @@ public class Cursor { * @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(); + if (Mouse.getImplementation() != null) { + return Mouse.getImplementation().getNativeCursorCapabilities(); + } else { + return OpenGLPackageAccess.createImplementation().getNativeCursorCapabilities(); } } diff --git a/src/java/org/lwjgl/input/Keyboard.java b/src/java/org/lwjgl/input/Keyboard.java index 00c7652b..a10d546b 100644 --- a/src/java/org/lwjgl/input/Keyboard.java +++ b/src/java/org/lwjgl/input/Keyboard.java @@ -323,11 +323,9 @@ public class Keyboard { * @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."); + if (!Display.isCreated()) throw new IllegalStateException("Display must be created."); - create(OpenGLPackageAccess.createImplementation()); - } + create(OpenGLPackageAccess.createImplementation()); } private static void reset() { @@ -341,22 +339,19 @@ public class Keyboard { * @return true if the keyboard has been created */ public static boolean isCreated() { - synchronized (OpenGLPackageAccess.global_lock) { - return created; - } + return created; } /** * "Destroy" the keyboard */ public static void destroy() { - synchronized (OpenGLPackageAccess.global_lock) { - if (!created) - return; - created = false; - implementation.destroyKeyboard(); - reset(); + if (!created) { + return; } + created = false; + implementation.destroyKeyboard(); + reset(); } /** @@ -381,12 +376,11 @@ public class Keyboard { * @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(); + if (!created) { + throw new IllegalStateException("Keyboard must be created before you can poll the device"); } + implementation.pollKeyboard(keyDownBuffer); + read(); } private static void read() { @@ -401,11 +395,10 @@ public class Keyboard { * @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; + if (!created) { + throw new IllegalStateException("Keyboard must be created before you can query key state"); } + return keyDownBuffer.get(key) != 0; } /** @@ -425,7 +418,7 @@ public class Keyboard { * @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) { + public static String getKeyName(int key) { return keyName[key]; } @@ -433,12 +426,13 @@ public class Keyboard { * 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) { + public static int getKeyIndex(String keyName) { Integer ret = keyMap.get(keyName); - if (ret == null) + if (ret == null) { return KEY_NONE; - else + } else { return ret; + } } /** @@ -446,16 +440,14 @@ public class Keyboard { * @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; - } + 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; } /** @@ -470,15 +462,12 @@ public class Keyboard { * @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"); + 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; - } + boolean result; + while ((result = readNext(current_event)) && current_event.repeat && !repeat_enabled) {} + return result; } /** @@ -490,9 +479,7 @@ public class Keyboard { * @see org.lwjgl.input.Keyboard#getEventKey() */ public static void enableRepeatEvents(boolean enable) { - synchronized (OpenGLPackageAccess.global_lock) { - repeat_enabled = enable; - } + repeat_enabled = enable; } /** @@ -502,9 +489,7 @@ public class Keyboard { * @see org.lwjgl.input.Keyboard#getEventKey() */ public static boolean areRepeatEventsEnabled() { - synchronized (OpenGLPackageAccess.global_lock) { - return repeat_enabled; - } + return repeat_enabled; } private static boolean readNext(KeyEvent event) { @@ -530,9 +515,7 @@ public class Keyboard { * @return The character from the current event */ public static char getEventCharacter() { - synchronized (OpenGLPackageAccess.global_lock) { - return (char)current_event.character; - } + return (char)current_event.character; } /** @@ -543,9 +526,7 @@ public class Keyboard { * @return The key from the current event */ public static int getEventKey() { - synchronized (OpenGLPackageAccess.global_lock) { - return current_event.key; - } + return current_event.key; } /** @@ -555,9 +536,7 @@ public class Keyboard { * @return True if key was down, or false if released */ public static boolean getEventKeyState() { - synchronized (OpenGLPackageAccess.global_lock) { - return current_event.state; - } + return current_event.state; } /** @@ -568,9 +547,7 @@ public class Keyboard { * @return The time in nanoseconds of the current event */ public static long getEventNanoseconds() { - synchronized (OpenGLPackageAccess.global_lock) { - return current_event.nanos; - } + return current_event.nanos; } /** @@ -579,9 +556,7 @@ public class Keyboard { * 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; - } + return current_event.repeat; } private static final class KeyEvent { diff --git a/src/java/org/lwjgl/input/Mouse.java b/src/java/org/lwjgl/input/Mouse.java index ee4e897c..0d396947 100644 --- a/src/java/org/lwjgl/input/Mouse.java +++ b/src/java/org/lwjgl/input/Mouse.java @@ -165,9 +165,7 @@ public class Mouse { * @return the currently bound native cursor, if any. */ public static Cursor getNativeCursor() { - synchronized (OpenGLPackageAccess.global_lock) { - return currentCursor; - } + return currentCursor; } /** @@ -183,21 +181,20 @@ public class Mouse { * @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; + 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; } public static boolean isClipMouseCoordinatesToWindow() { @@ -218,18 +215,16 @@ public class Mouse { * 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; - } + 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; } } @@ -293,34 +288,29 @@ public class Mouse { * @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."); + if (!Display.isCreated()) throw new IllegalStateException("Display must be created."); - create(OpenGLPackageAccess.createImplementation()); - } + create(OpenGLPackageAccess.createImplementation()); } /** * @return true if the mouse has been created */ public static boolean isCreated() { - synchronized (OpenGLPackageAccess.global_lock) { - return created; - } + return created; } /** * "Destroy" the mouse. */ public static void destroy() { - synchronized (OpenGLPackageAccess.global_lock) { - if (!created) return; - created = false; - buttons = null; - coord_buffer = null; + if (!created) return; - implementation.destroyMouse(); - } + created = false; + buttons = null; + coord_buffer = null; + + implementation.destroyMouse(); } /** @@ -348,38 +338,37 @@ public class Mouse { * @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 (!created) throw new IllegalStateException("Mouse must be created before you can poll it"); - /* 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); + implementation.pollMouse(coord_buffer, buttons); - if (isGrabbed()) { - dx += poll_coord1; - dy += poll_coord2; - x += poll_coord1; - y += poll_coord2; - absolute_x += poll_coord1; - absolute_y += poll_coord2; - } else { - dx = poll_coord1 - absolute_x; - dy = poll_coord2 - absolute_y; - absolute_x = x = poll_coord1; - absolute_y = y = poll_coord2; - } - - if(clipMouseCoordinatesToWindow) { - x = Math.min(Display.getWidth() - 1, Math.max(0, x)); - y = Math.min(Display.getHeight() - 1, Math.max(0, y)); - } - - dwheel += poll_dwheel; - read(); + /* 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; + absolute_x += poll_coord1; + absolute_y += poll_coord2; + } else { + dx = poll_coord1 - absolute_x; + dy = poll_coord2 - absolute_y; + absolute_x = x = poll_coord1; + absolute_y = y = poll_coord2; } + + if (clipMouseCoordinatesToWindow) { + x = Math.min(Display.getWidth() - 1, Math.max(0, x)); + y = Math.min(Display.getHeight() - 1, Math.max(0, y)); + } + + dwheel += poll_dwheel; + read(); } private static void read() { @@ -395,12 +384,11 @@ public class Mouse { * @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; + 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; } } @@ -410,11 +398,10 @@ public class Mouse { * @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]; + if (button >= buttonName.length || button < 0) { + return null; + } else { + return buttonName[button]; } } @@ -423,12 +410,11 @@ public class Mouse { * @param buttonName The button name */ public static int getButtonIndex(String buttonName) { - synchronized (OpenGLPackageAccess.global_lock) { - Integer ret = buttonMap.get(buttonName); - if (ret == null) - return -1; - else - return ret; + Integer ret = buttonMap.get(buttonName); + if (ret == null) { + return -1; + } else { + return ret; } } @@ -442,7 +428,6 @@ public class Mouse { * @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(); @@ -464,25 +449,23 @@ public class Mouse { last_event_raw_x = new_event_x; last_event_raw_y = new_event_y; } - if(clipMouseCoordinatesToWindow) { + if (clipMouseCoordinatesToWindow) { event_x = Math.min(Display.getWidth() - 1, Math.max(0, event_x)); event_y = Math.min(Display.getHeight() - 1, Math.max(0, event_y)); } event_dwheel = readBuffer.getInt(); event_nanos = readBuffer.getLong(); return true; - } else + } 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; - } + return eventButton; } /** @@ -490,54 +473,42 @@ public class Mouse { * @return Current events button state. */ public static boolean getEventButtonState() { - synchronized (OpenGLPackageAccess.global_lock) { - return eventState; - } + return eventState; } /** * @return Current events delta x. */ public static int getEventDX() { - synchronized (OpenGLPackageAccess.global_lock) { - return event_dx; - } + return event_dx; } /** * @return Current events delta y. */ public static int getEventDY() { - synchronized (OpenGLPackageAccess.global_lock) { - return event_dy; - } + return event_dy; } /** * @return Current events absolute x. */ public static int getEventX() { - synchronized (OpenGLPackageAccess.global_lock) { - return event_x; - } + return event_x; } /** * @return Current events absolute y. */ public static int getEventY() { - synchronized (OpenGLPackageAccess.global_lock) { - return event_y; - } + return event_y; } /** * @return Current events delta z */ public static int getEventDWheel() { - synchronized (OpenGLPackageAccess.global_lock) { - return event_dwheel; - } + return event_dwheel; } /** @@ -549,9 +520,7 @@ public class Mouse { * @return The time in nanoseconds of the current event */ public static long getEventNanoseconds() { - synchronized (OpenGLPackageAccess.global_lock) { - return event_nanos; - } + return event_nanos; } /** @@ -561,9 +530,7 @@ public class Mouse { * @return Absolute x axis position of mouse */ public static int getX() { - synchronized (OpenGLPackageAccess.global_lock) { - return x; - } + return x; } /** @@ -573,69 +540,55 @@ public class Mouse { * @return Absolute y axis position of mouse */ public static int getY() { - synchronized (OpenGLPackageAccess.global_lock) { - return y; - } + return y; } /** * @return Movement on the x axis since last time getDX() was called. */ public static int getDX() { - synchronized (OpenGLPackageAccess.global_lock) { - int result = dx; - dx = 0; - return result; - } + int result = dx; + dx = 0; + return result; } /** * @return Movement on the y axis since last time getDY() was called. */ public static int getDY() { - synchronized (OpenGLPackageAccess.global_lock) { - int result = dy; - dy = 0; - return result; - } + 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; - } + 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 buttonCount; } /** * @return Whether or not this mouse has wheel support */ public static boolean hasWheel() { - synchronized (OpenGLPackageAccess.global_lock) { - return hasWheel; - } + return hasWheel; } /** * @return whether or not the mouse has grabbed the cursor */ public static boolean isGrabbed() { - synchronized (OpenGLPackageAccess.global_lock) { - return isGrabbed; - } + return isGrabbed; } /** @@ -647,31 +600,31 @@ public class Mouse { * @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); - } + boolean grabbed = isGrabbed; + if (grabbed == grab) return; - implementation.grabMouse(grab); - // Get latest values from native side - poll(); - event_x = x; - event_y = y; - last_event_raw_x = x; - last_event_raw_y = y; - resetMouse(); - } + isGrabbed = grab; + + if (!isCreated()) return; + + 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; + last_event_raw_x = x; + last_event_raw_y = y; + resetMouse(); } /** @@ -680,25 +633,23 @@ public class Mouse { * 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(); - } + if (emulateCursorAnimation && currentCursor != null && currentCursor.hasTimedOut() && Mouse.isInsideWindow()) { + currentCursor.nextCursor(); + try { + setNativeCursor(currentCursor); + } catch (LWJGLException e) { + if (LWJGLUtil.DEBUG) e.printStackTrace(); } } } - /** - * 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(); - } + /** + * 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/openal/ALC10.java b/src/java/org/lwjgl/openal/ALC10.java index bd6f5dd5..2de0e633 100644 --- a/src/java/org/lwjgl/openal/ALC10.java +++ b/src/java/org/lwjgl/openal/ALC10.java @@ -224,7 +224,7 @@ public final class ALC10 { boolean result = nalcCloseDevice(getDevice(device)); synchronized (devices) { device.setInvalid(); - devices.remove(new Long(device.device)); + devices.remove(Long.valueOf(device.device)); } return result; diff --git a/src/java/org/lwjgl/openal/ALC11.java b/src/java/org/lwjgl/openal/ALC11.java index ae849a9e..50d04b0e 100644 --- a/src/java/org/lwjgl/openal/ALC11.java +++ b/src/java/org/lwjgl/openal/ALC11.java @@ -118,7 +118,7 @@ public final class ALC11 { boolean result = nalcCaptureCloseDevice(ALC10.getDevice(device)); synchronized (ALC10.devices) { device.setInvalid(); - ALC10.devices.remove(new Long(device.device)); + ALC10.devices.remove(Long.valueOf(device.device)); } return result; } diff --git a/src/java/org/lwjgl/opengl/Display.java b/src/java/org/lwjgl/opengl/Display.java index ce63dac9..396fc2c0 100644 --- a/src/java/org/lwjgl/opengl/Display.java +++ b/src/java/org/lwjgl/opengl/Display.java @@ -60,6 +60,7 @@ import java.nio.FloatBuffer; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; +import java.util.Objects; import java.util.HashSet; import static org.lwjgl.LWJGLUtil.getPrivilegedBoolean; @@ -127,9 +128,7 @@ public final class Display { private static final ComponentListener component_listener = new ComponentAdapter() { public void componentResized(ComponentEvent e) { - synchronized ( GlobalLock.lock ) { - parent_resized = true; - } + parent_resized = true; } }; @@ -186,24 +185,28 @@ public final class Display { * @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(); + 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; + if (unfilteredModes == null) { + return new DisplayMode[0]; } + if (unfilteredModes.length <= 1) { + return unfilteredModes; + } + + // We'll use a HashSet to filter out the duplicated modes + HashSet modes = new HashSet<>(unfilteredModes.length); + + for (DisplayMode mode : unfilteredModes) { + modes.add(mode); + } + DisplayMode[] filteredModes = new DisplayMode[modes.size()]; + modes.toArray(filteredModes); + + int n = unfilteredModes.length - filteredModes.length; + LWJGLUtil.logger().log(() -> "Removed " + n + " duplicate displaymodes"); + + return filteredModes; } /** @@ -236,27 +239,29 @@ public final class Display { * @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() || parent != null ) - return; - 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) { - drawable.destroy(); + Objects.requireNonNull(mode, "mode must be non-null"); + + if (mode == current_mode) return; + + boolean was_fullscreen = isFullscreen(); + current_mode = mode; + + if (!isCreated() || parent != null) return; + + destroyWindow(); + + // If mode is not fullscreen capable, make sure we are in windowed mode + try { + if ( was_fullscreen && !isFullscreen() ) display_impl.resetDisplayMode(); - throw e; - } + else if ( isFullscreen() ) + switchDisplayMode(); + createWindow(); + makeCurrentAndSetSwapInterval(); + } catch (LWJGLException e) { + drawable.destroy(); + display_impl.resetDisplayMode(); + throw e; } } @@ -370,37 +375,35 @@ public final class Display { * @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); + 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); } /** @@ -434,25 +437,23 @@ public final class Display { * 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) { - drawable.destroy(); + if ( Display.parent != parent ) { + Display.parent = parent; + if ( !isCreated() ) + return; + destroyWindow(); + try { + if ( isFullscreen() ) { + switchDisplayMode(); + } else { display_impl.resetDisplayMode(); - throw e; } + createWindow(); + makeCurrentAndSetSwapInterval(); + } catch (LWJGLException e) { + drawable.destroy(); + display_impl.resetDisplayMode(); + throw e; } } } @@ -489,30 +490,27 @@ public final class Display { } 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) { - drawable.destroy(); + 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(); - throw e; } + createWindow(); + makeCurrentAndSetSwapInterval(); + } catch (LWJGLException e) { + drawable.destroy(); + display_impl.resetDisplayMode(); + throw e; } } } @@ -528,41 +526,37 @@ public final class Display { * @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); + 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(); + 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(); + 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(); + if (!isCreated()) { + throw new IllegalStateException("Cannot determine focused state of uncreated window"); } + return display_impl.isActive(); } /** @@ -576,11 +570,10 @@ public final class Display { * 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(); + if (!isCreated()) { + throw new IllegalStateException("Cannot determine dirty state of uncreated window"); } + return display_impl.isDirty(); } /** @@ -589,12 +582,11 @@ public final class Display { * 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(); + if (!isCreated()) { + throw new IllegalStateException("Display not created"); } + + display_impl.update(); pollDevices(); } @@ -605,14 +597,15 @@ public final class Display { * @throws OpenGLException if an OpenGL error has occured since the last call to glGetError() */ public static void swapBuffers() throws LWJGLException { - synchronized ( GlobalLock.lock ) { - if ( !isCreated() ) - throw new IllegalStateException("Display not created"); - - if ( LWJGLUtil.DEBUG ) - drawable.checkGLError(); - drawable.swapBuffers(); + if (!isCreated()) { + throw new IllegalStateException("Display not created"); } + + if (LWJGLUtil.DEBUG) { + drawable.checkGLError(); + } + + drawable.swapBuffers(); } /** @@ -632,49 +625,49 @@ public final class Display { * @param processMessages Poll input devices if true */ public static void update(boolean processMessages) { - synchronized ( GlobalLock.lock ) { - if ( !isCreated() ) - throw new IllegalStateException("Display not created"); + 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); - } + // 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); } + } - window_resized = !isFullscreen() && parent == null && display_impl.wasResized(); + window_resized = !isFullscreen() && parent == null && display_impl.wasResized(); - if ( window_resized ) { - width = display_impl.getWidth(); - height = display_impl.getHeight(); - } + if (window_resized) { + width = display_impl.getWidth(); + height = display_impl.getHeight(); + } - if ( parent_resized ) { - reshape(); - parent_resized = false; - window_resized = true; - } + if (parent_resized) { + reshape(); + parent_resized = false; + window_resized = true; + } - if ( processMessages ) - processMessages(); + if (processMessages) { + processMessages(); } } static void pollDevices() { // Poll the input devices while we're here - if ( Mouse.isCreated() ) { + if (Mouse.isCreated()) { Mouse.poll(); Mouse.updateCursor(); } - if ( Keyboard.isCreated() ) { + if (Keyboard.isCreated()) { Keyboard.poll(); } - if ( Controllers.isCreated() ) { + if (Controllers.isCreated()) { Controllers.poll(); } } @@ -703,20 +696,16 @@ public final class Display { } private static void removeShutdownHook() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - Runtime.getRuntime().removeShutdownHook(shutdown_hook); - return null; - } + AccessController.doPrivileged((PrivilegedAction) () -> { + 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; - } + AccessController.doPrivileged((PrivilegedAction) () -> { + Runtime.getRuntime().addShutdownHook(shutdown_hook); + return null; }); } @@ -749,9 +738,7 @@ public final class Display { * @throws LWJGLException */ public static void create(PixelFormat pixel_format) throws LWJGLException { - synchronized ( GlobalLock.lock ) { - create(pixel_format, null, (ContextAttribs)null); - } + create(pixel_format, null, (ContextAttribs)null); } /** @@ -769,9 +756,7 @@ public final class Display { * @throws LWJGLException */ public static void create(PixelFormat pixel_format, Drawable shared_drawable) throws LWJGLException { - synchronized ( GlobalLock.lock ) { - create(pixel_format, shared_drawable, (ContextAttribs)null); - } + create(pixel_format, shared_drawable, (ContextAttribs)null); } /** @@ -789,9 +774,7 @@ public final class Display { * @throws LWJGLException */ public static void create(PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException { - synchronized ( GlobalLock.lock ) { - create(pixel_format, null, attribs); - } + create(pixel_format, null, attribs); } /** @@ -881,9 +864,7 @@ public final class Display { */ public static void create(PixelFormatLWJGL pixel_format) throws LWJGLException { - synchronized ( GlobalLock.lock ) { - create(pixel_format, null, null); - } + create(pixel_format, null, null); } /** @@ -901,9 +882,7 @@ public final class Display { * @throws LWJGLException */ public static void create(PixelFormatLWJGL pixel_format, Drawable shared_drawable) throws LWJGLException { - synchronized ( GlobalLock.lock ) { - create(pixel_format, shared_drawable, null); - } + create(pixel_format, shared_drawable, null); } /** @@ -921,9 +900,7 @@ public final class Display { * @throws LWJGLException */ public static void create(PixelFormatLWJGL pixel_format, org.lwjgl.opengles.ContextAttribs attribs) throws LWJGLException { - synchronized ( GlobalLock.lock ) { - create(pixel_format, null, attribs); - } + create(pixel_format, null, attribs); } /** @@ -1038,15 +1015,15 @@ public final class Display { 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") ) { + if (!getPrivilegedBoolean("org.lwjgl.opengl.Display.noinput")) { + if (!Mouse.isCreated() && !getPrivilegedBoolean("org.lwjgl.opengl.Display.nomouse")) { try { Mouse.create(); } catch (LWJGLException e) { LWJGLUtil.logger().log("Failed to create Mouse", e); } } - if ( !Keyboard.isCreated() && !getPrivilegedBoolean("org.lwjgl.opengl.Display.nokeyboard") ) { + if (!Keyboard.isCreated() && !getPrivilegedBoolean("org.lwjgl.opengl.Display.nokeyboard")) { try { Keyboard.create(); } catch (LWJGLException e) { @@ -1091,11 +1068,11 @@ public final class Display { * @param value The swap interval in frames, 0 to disable */ public static void setSwapInterval(int value) throws LWJGLException { - synchronized ( GlobalLock.lock ) { + if (value != swap_interval) { swap_interval = value; - if ( isCreated() ) - drawable.setSwapInterval(swap_interval); - + if (isCreated()) { + drawable.setSwapInterval(value); + } } } @@ -1120,15 +1097,13 @@ public final class Display { * @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; + // cache position + x = new_x; + y = new_y; - // offset if already created - if ( isCreated() && !isFullscreen() ) { - reshape(); - } + // offset if already created + if ( isCreated() && !isFullscreen() ) { + reshape(); } } @@ -1175,25 +1150,23 @@ public final class Display { * @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(); - } + // 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; - } + if (Display.isCreated() && parent == null) { + return display_impl.setIcon(cached_icons); + } else { + return 0; } } @@ -1204,9 +1177,11 @@ public final class Display { * false to disable resizing on the Display window. */ public static void setResizable(boolean resizable) { - window_resizable = resizable; - if ( isCreated() ) { - display_impl.setResizable(resizable); + if (window_resizable != resizable) { + window_resizable = resizable; + if (isCreated()) { + display_impl.setResizable(resizable); + } } } @@ -1235,7 +1210,6 @@ public final class Display { * the parent will be returned. */ public static int getX() { - if (Display.isFullscreen()) { return 0; } @@ -1255,7 +1229,6 @@ public final class Display { * the parent will be returned. */ public static int getY() { - if (Display.isFullscreen()) { return 0; } @@ -1277,7 +1250,6 @@ public final class Display { * This value will be updated after a call to Display.update(). */ public static int getWidth() { - if (Display.isFullscreen()) { return Display.getDisplayMode().getWidth(); } @@ -1299,7 +1271,6 @@ public final class Display { * This value will be updated after a call to Display.update(). */ public static int getHeight() { - if (Display.isFullscreen()) { return Display.getDisplayMode().getHeight(); } diff --git a/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoadTest.java b/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoadTest.java index bf2326cf..4d05633d 100644 --- a/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoadTest.java +++ b/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoadTest.java @@ -81,10 +81,10 @@ public final class BackgroundLoadTest { Util.checkGLError(); - while ( run ) { - if ( !Display.isVisible() ) + while (run) { + if (!Display.isVisible()) { Thread.yield(); - else { + } else { handleIO(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -100,8 +100,9 @@ public final class BackgroundLoadTest { Display.update(); - if ( Display.isCloseRequested() ) + if (Display.isCloseRequested()) { break; + } } cleanup(); @@ -115,7 +116,8 @@ public final class BackgroundLoadTest { DisplayMode displayMode = null; try { - DisplayMode[] modes = Display.getAvailableDisplayModes(); + displayMode = Display.getDisplayMode(); + /*DisplayMode[] modes = Display.getAvailableDisplayModes(); displayMode = chooseMode(modes, 1024, 768); if ( displayMode == null ) @@ -126,7 +128,7 @@ public final class BackgroundLoadTest { kill("Failed to set an appropriate display mode."); System.out.println("Setting display mode to: " + displayMode); - Display.setDisplayMode(displayMode); + Display.setDisplayMode(displayMode);*/ Display.setTitle("Background Loading Test"); Display.create(new PixelFormat(8, 24, 0)); } catch (LWJGLException e) { @@ -189,18 +191,10 @@ public final class BackgroundLoadTest { sphere = new Sphere(); - if ( "PB".equalsIgnoreCase(args[0]) ) { - backgroundLoader = new BackgroundLoader() { - Drawable getDrawable() throws LWJGLException { - return new Pbuffer(2, 2, new PixelFormat(8, 24, 0), Display.getDrawable()); - } - }; - } else if ( "SD".equalsIgnoreCase(args[0]) ) { - backgroundLoader = new BackgroundLoader() { - Drawable getDrawable() throws LWJGLException { - return new SharedDrawable(Display.getDrawable()); - } - }; + if ("PB".equalsIgnoreCase(args[0])) { + backgroundLoader = new BackgroundLoader(() -> new Pbuffer(2, 2, new PixelFormat(8, 24, 0), Display.getDrawable())); + } else if ("SD".equalsIgnoreCase(args[0])) { + backgroundLoader = new BackgroundLoader(() -> new SharedDrawable(Display.getDrawable())); } else { argsError(); } @@ -227,7 +221,7 @@ public final class BackgroundLoadTest { glColor3f(1.0f, 1.0f, 1.0f); int texID = backgroundLoader.getTexID(); - if ( texID == 0 ) { + if (texID == 0) { sphere.setTextureFlag(false); glDisable(GL_TEXTURE_2D); } else { @@ -238,7 +232,8 @@ public final class BackgroundLoadTest { sphere.draw(1.0f, 32, 32); - if ( texID != 0 ) { // Unbind so we can update from the background thread. + if (texID != 0) { + // Unbind so we can update from the background thread. glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); } @@ -247,9 +242,9 @@ public final class BackgroundLoadTest { private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) { DisplayMode bestMode = null; - for ( DisplayMode mode : modes ) { - if ( mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85 ) { - if ( bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) ) + for (DisplayMode mode : modes) { + if (mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85) { + if (bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) ) bestMode = mode; } } @@ -258,7 +253,9 @@ public final class BackgroundLoadTest { } private static void cleanup() { - backgroundLoader.cleanup(); + if (backgroundLoader != null) { + backgroundLoader.cleanup(); + } Thread.yield(); // Let background thread finish. @@ -294,4 +291,4 @@ public final class BackgroundLoadTest { System.exit(-1); } -} \ No newline at end of file +} diff --git a/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java b/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java index c32f8d5d..c3baefe7 100644 --- a/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java +++ b/src/java/org/lwjgl/test/opengl/multithread/BackgroundLoader.java @@ -46,55 +46,57 @@ import org.lwjgl.util.Color; import org.lwjgl.util.ReadableColor; import java.nio.ByteBuffer; -import java.util.concurrent.locks.ReentrantLock; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL32.*; -abstract class BackgroundLoader { +final class BackgroundLoader { - private static final int WIDTH = 32; - private static final int HEIGHT = 32; + private static final int WIDTH = 64; + private static final int HEIGHT = 64; - // CPU synchronization - private final ReentrantLock lock = new ReentrantLock(); // GPU synchronization private GLSync fence; - private Drawable drawable; + private final DrawableSupplier drawableSupplier; + private Drawable drawable; + private int texID; private boolean running; - private ByteBuffer texture; - private int texID; - - protected BackgroundLoader() { - running = true; - texture = BufferUtils.createByteBuffer(WIDTH * HEIGHT * 3); + protected BackgroundLoader(DrawableSupplier drawableSupplier) { + this.drawableSupplier = drawableSupplier; + this.running = true; } - abstract Drawable getDrawable() throws LWJGLException; - void cleanup() { running = false; } + private void uploadTexture(int texID, ByteBuffer texture, boolean useFences) { + glBindTexture(GL_TEXTURE_2D, texID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, 0); + + if (useFences) { + //while (fence != null) {} + fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } else { + // Best we can do without fences. This will force rendering on the main thread to happen after we upload the texture. + glFlush(); + } + } + void start() throws LWJGLException { - // The shared context must be created on the main thread. - drawable = getDrawable(); + this.drawable = this.drawableSupplier.get(); - new Thread(new Runnable() { - public void run() { + new Thread(() -> { System.out.println("-- Background Thread started --"); - System.out.println("** Sleeping, no texture created yet **"); - - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - try { // Make the shared context current in the worker thread drawable.makeCurrent(); @@ -104,69 +106,57 @@ abstract class BackgroundLoader { System.out.println("** Drawable created **"); - // Create a "dummy" texture while we wait for texture IO - createCheckerTexture(Color.RED, Color.WHITE, 2); - - lock.lock(); - - texID = glGenTextures(); - glBindTexture(GL_TEXTURE_2D, texID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glBindTexture(GL_TEXTURE_2D, 0); - // OpenGL commands from different contexts may be executed in any order. So we need a way to synchronize final boolean useFences = GLContext.getCapabilities().OpenGL32; + System.out.println("Using fences: " + useFences); - if ( useFences ) - fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - else - glFlush(); // Best we can do without fences. This will force rendering on the main thread to happen after we upload the texture. + System.out.println("** Sleeping, no texture created yet **"); - lock.unlock(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + ByteBuffer texture = BufferUtils.createByteBuffer(WIDTH * HEIGHT * 3); + + // Create a "dummy" texture while we wait for texture IO + createCheckerTexture(texture, Color.RED, Color.WHITE, 2); + + texID = glGenTextures(); + uploadTexture(texID, texture, useFences); System.out.println("** Dummy texture created **"); + long avgGenTime = 0L; + long avgUploadTime = 0L; + long lastUploadTime = 0L; + long lastTextureCreated = System.currentTimeMillis(); // Delay first texture creation int count = 0; while ( running ) { - long time = System.currentTimeMillis(); - if ( time - lastTextureCreated < 5000 ) { // Update the texture every 5 seconds - try { - Thread.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); - } + /*long time = System.currentTimeMillis(); + if (time - lastTextureCreated < 2) { // Update the texture every 5 seconds continue; - } + }*/ // Create the "true" texture - if ( count % 2 == 0 ) - createGradientTexture(Color.RED, Color.BLUE); - else - createGradientTexture(Color.GREEN, Color.YELLOW); + long start = System.nanoTime(); + if ( count % 2 == 0 ) { + createGradientTexture(texture, Color.RED, Color.BLUE); + } else { + createGradientTexture(texture, Color.GREEN, Color.YELLOW); + } + long elapsed = System.nanoTime() - start; + avgGenTime = (avgGenTime + elapsed) >> 1; - lock.lock(); + start = System.nanoTime(); + uploadTexture(texID, texture, useFences); + lastUploadTime = System.nanoTime() - start; + avgUploadTime = (avgUploadTime + lastUploadTime) >> 1; + //System.out.println("Uploaded texture in " + elapsed + " ns."); - glBindTexture(GL_TEXTURE_2D, texID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glBindTexture(GL_TEXTURE_2D, 0); - - if ( useFences ) - fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - else - glFlush(); - - lock.unlock(); - - System.out.println("** Created new gradient texture **"); + //System.out.println("** Created new gradient texture **"); lastTextureCreated = System.currentTimeMillis(); count++; @@ -175,24 +165,26 @@ abstract class BackgroundLoader { drawable.destroy(); System.out.println("-- Background Thread finished --"); - } + System.out.println("Generated textures in " + avgGenTime + " ns on average."); + System.out.println("Uploaded textures in " + avgUploadTime + " ns on average."); + System.out.println("Most recently uploaded textures in " + lastUploadTime + " ns."); }).start(); } - int getTexID() { - lock.lock(); + public final int getTexID() { + //lock.lock(); try { - if ( fence != null ) { + if (fence != null) { glWaitSync(fence, 0, GL_TIMEOUT_IGNORED); fence = null; } return texID; } finally { - lock.unlock(); + //lock.unlock(); } } - private void createCheckerTexture(final ReadableColor a, final ReadableColor b, final int size) { + private static void createCheckerTexture(ByteBuffer texture, final ReadableColor a, final ReadableColor b, final int size) { int i = 0; for ( int y = 0; y < HEIGHT; y++ ) { for ( int x = 0; x < WIDTH; x++ ) { @@ -205,7 +197,7 @@ abstract class BackgroundLoader { } } - private void createGradientTexture(final ReadableColor a, final ReadableColor b) { + private static void createGradientTexture(ByteBuffer texture, final ReadableColor a, final ReadableColor b) { float l = 0.0f; int i = 0; for ( int y = 0; y < HEIGHT; y++ ) { @@ -223,4 +215,4 @@ abstract class BackgroundLoader { return (byte)Math.round(((1.0f - l) * a + l * b)); } -} \ No newline at end of file +} diff --git a/src/java/org/lwjgl/test/opengl/multithread/DrawableSupplier.java b/src/java/org/lwjgl/test/opengl/multithread/DrawableSupplier.java new file mode 100644 index 00000000..bdfb1521 --- /dev/null +++ b/src/java/org/lwjgl/test/opengl/multithread/DrawableSupplier.java @@ -0,0 +1,9 @@ +package org.lwjgl.test.opengl.multithread; + +import org.lwjgl.LWJGLException; +import org.lwjgl.opengl.Drawable; + +@FunctionalInterface +interface DrawableSupplier { + Drawable get() throws LWJGLException; +}