Remove a lot of synchronization

This commit is contained in:
Michael Pfaff 2022-08-14 13:21:03 -04:00
parent 68d112adec
commit 4f7fee2ed4
Signed by: michael
GPG Key ID: CF402C4A012AA9D4
12 changed files with 552 additions and 647 deletions

View File

@ -71,10 +71,43 @@
<antcall target="-distribute" /> <antcall target="-distribute" />
</target> </target>
<target name="all" description="Creates the Java archives and the natives for the current platform" depends="jars, compile_native"/> <target name="all" description="Creates the Java archives and the natives for the current platform">
<parallel>
<antcall target="jars" />
<antcall target="compile_native" />
</parallel>
</target>
<target name="jars+lwjgl+NoDeps" depends="-initialize">
<jar destfile="${lwjgl.target.jars}/lwjgl.jar" taskname="lwjgl.jar">
<fileset refid="lwjgl.fileset" />
<fileset refid="lwjgl.fileset.dependencies"/>
<manifest>
<attribute name="Sealed" value="true"/>
</manifest>
</jar>
</target>
<target name="jars+lwjgl_util+NoDeps" depends="-initialize">
<jar destfile="${lwjgl.target.jars}/lwjgl_util.jar" taskname="lwjgl_util.jar">
<fileset refid="lwjgl_util.fileset" />
</jar>
</target>
<target name="jars+lwjgl_test+NoDeps" depends="-initialize">
<jar destfile="${lwjgl.target.jars}/lwjgl_test.jar" taskname="lwjgl_test.jar">
<fileset refid="lwjgl_test.fileset" />
<fileset refid="lwjgl_test_extra.fileset" />
</jar>
</target>
<!-- Create ONLY the jar archives --> <!-- Create ONLY the jar archives -->
<target name="jars+NoDeps" description="Creates the Java archives ONLY and places them in libs/" depends="-createjars"> <target name="jars+NoDeps" description="Creates the Java archives ONLY and places them in libs/" depends="-initialize">
<parallel>
<antcall target="jars+lwjgl+NoDeps" />
<antcall target="jars+lwjgl_util+NoDeps" />
<antcall target="jars+lwjgl_test+NoDeps" />
</parallel>
</target> </target>
<target name="jars" description="Creates the Java archives ONLY and places them in libs/" depends="generate-all, compile, jars+NoDeps"> <target name="jars" description="Creates the Java archives ONLY and places them in libs/" depends="generate-all, compile, jars+NoDeps">
@ -97,29 +130,6 @@
</jar> </jar>
</target> </target>
<!-- Packages the java files -->
<target name="-createjars" depends="-initialize">
<!-- Create lwjgl.jar -->
<jar destfile="${lwjgl.target.jars}/lwjgl.jar" taskname="lwjgl.jar">
<fileset refid="lwjgl.fileset" />
<fileset refid="lwjgl.fileset.dependencies"/>
<manifest>
<attribute name="Sealed" value="true"/>
</manifest>
</jar>
<!-- Create lwjgl_test.jar -->
<jar destfile="${lwjgl.target.jars}/lwjgl_test.jar" taskname="lwjgl_test.jar">
<fileset refid="lwjgl_test.fileset" />
<fileset refid="lwjgl_test_extra.fileset" />
</jar>
<!-- Create lwjgl_util.jar -->
<jar destfile="${lwjgl.target.jars}/lwjgl_util.jar" taskname="lwjgl_util.jar">
<fileset refid="lwjgl_util.fileset" />
</jar>
</target>
<!-- Packages the java files for the ES build --> <!-- Packages the java files for the ES build -->
<target name="-createjars_es"> <target name="-createjars_es">
<!-- ================================================================== --> <!-- ================================================================== -->
@ -456,11 +466,11 @@
<src path="${lwjgl.target.gen.java}"/> <src path="${lwjgl.target.gen.java}"/>
<exclude name="org/lwjgl/util/generator/**"/> <exclude name="org/lwjgl/util/generator/**"/>
</javac> </javac>
<javac debug="yes" srcdir="${lwjgl.src.java}" destdir="${lwjgl.target.gen.classes}" includes="org/lwjgl/test/**" source="1.8" target="1.8" taskname="test" /> <!--<javac debug="yes" srcdir="${lwjgl.src.java}" destdir="${lwjgl.target.gen.classes}" includes="org/lwjgl/test/**" source="1.8" target="1.8" taskname="test" />-->
<javac debug="yes" srcdir="${lwjgl.src.java}" destdir="${lwjgl.target.gen.classes}" includes="org/lwjgl/examples/**" source="1.8" target="1.8" taskname="examples" /> <!--<javac debug="yes" srcdir="${lwjgl.src.java}" destdir="${lwjgl.target.gen.classes}" includes="org/lwjgl/examples/**" source="1.8" target="1.8" taskname="examples" />-->
</target> </target>
<target name="compile_native" depends="-initialize, compile, touch-version, version-mismatch" description="Compiles the native files"> <target name="compile_native" depends="-initialize, generate-all, touch-version, version-mismatch" description="Compiles the native files">
<condition property="lwjgl.platform.windows"> <condition property="lwjgl.platform.windows">
<os family="windows" /> <os family="windows" />
</condition> </condition>
@ -528,7 +538,7 @@
<version-check platform="macosx"/> <version-check platform="macosx"/>
</target> </target>
<target name="compile_native_es" depends="-initialize, compile, touch-version, version-mismatch" description="Compiles the native files"> <target name="compile_native_es" depends="-initialize, generate-all, touch-version, version-mismatch" description="Compiles the native files">
<condition property="lwjgl.platform.windows"> <condition property="lwjgl.platform.windows">
<os family="windows"/> <os family="windows"/>
</condition> </condition>
@ -597,24 +607,24 @@
</antcall> </antcall>
</target> </target>
<target name="runtest" depends="all"> <target name="runtest">
<fail message="test.mainclass is not set. Use 'ant -Dtest.mainclass=&lt;main-class&gt; runtest'" unless="test.mainclass"/> <fail message="test.mainclass is not set. Use 'ant -Dtest.mainclass=&lt;main-class&gt; runtest'" unless="test.mainclass"/>
<condition property="native_path" value="libs/windows"> <condition property="native_path" value="${lwjgl.target.natives}">
<os family="windows" /> <os family="windows" />
</condition> </condition>
<condition property="native_path" value="libs/linux"> <condition property="native_path" value="${lwjgl.target.natives}">
<or> <or>
<os name="Linux" /> <os name="Linux" />
<os name="SunOS" /> <os name="SunOS" />
</or> </or>
</condition> </condition>
<condition property="native_path" value="libs/macosx"> <condition property="native_path" value="${lwjgl.target.natives}">
<os name="Mac OS X" /> <os name="Mac OS X" />
</condition> </condition>
<property name="native_path_expanded" location="${native_path}"/> <property name="native_path_expanded" location="${native_path}"/>
<java classname="${test.mainclass}" classpath="res:${lwjgl.lib}/lwjgl.jar:${lwjgl.lib}/lwjgl_util.jar:${lwjgl.lib}/lwjgl_test.jar:${lwjgl.lib}/jinput.jar" fork="true"> <java classname="${test.mainclass}" classpath="res:${lwjgl.target.jars}/lwjgl.jar:${lwjgl.target.jars}/lwjgl_util.jar:${lwjgl.target.jars}/lwjgl_test.jar:${lwjgl.lib}/jinput.jar" fork="true">
<sysproperty key="org.lwjgl.util.Debug" value="true"/> <sysproperty key="org.lwjgl.util.Debug" value="true"/>
<sysproperty key="java.library.path" value="${native_path_expanded}"/> <sysproperty key="java.library.path" value="${native_path_expanded}"/>
<arg line="${args}"/> <arg line="${args}"/>

View File

@ -185,7 +185,7 @@
<include name="doc/README" /> <include name="doc/README" />
</patternset> </patternset>
<uptodate property="lwjgl.main.built" targetfile="${lwjgl.lib}/windows/lwjgl.dll" > <uptodate property="lwjgl.main.built" targetfile="${lwjgl.target.natives}/lwjgl.dll" >
<srcfiles dir= "${lwjgl.src.native}/common" includes="*.c*"/> <srcfiles dir= "${lwjgl.src.native}/common" includes="*.c*"/>
<srcfiles dir= "${lwjgl.src.native}/windows" includes="*.c"/> <srcfiles dir= "${lwjgl.src.native}/windows" includes="*.c"/>
</uptodate> </uptodate>

5
run-test.sh Executable file
View File

@ -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 "$@"

View File

@ -119,12 +119,10 @@ public class Cursor {
* @return the maximum size of a native cursor * @return the maximum size of a native cursor
*/ */
public static int getMinCursorSize() { public static int getMinCursorSize() {
synchronized (OpenGLPackageAccess.global_lock) {
if (!Mouse.isCreated()) if (!Mouse.isCreated())
throw new IllegalStateException("Mouse must be created."); throw new IllegalStateException("Mouse must be created.");
return Mouse.getImplementation().getMinCursorSize(); return Mouse.getImplementation().getMinCursorSize();
} }
}
/** /**
* Gets the maximum size of a native cursor. Can only be called if * Gets the maximum size of a native cursor. Can only be called if
@ -134,12 +132,10 @@ public class Cursor {
* @return the maximum size of a native cursor * @return the maximum size of a native cursor
*/ */
public static int getMaxCursorSize() { public static int getMaxCursorSize() {
synchronized (OpenGLPackageAccess.global_lock) {
if (!Mouse.isCreated()) if (!Mouse.isCreated())
throw new IllegalStateException("Mouse must be created."); throw new IllegalStateException("Mouse must be created.");
return Mouse.getImplementation().getMaxCursorSize(); return Mouse.getImplementation().getMaxCursorSize();
} }
}
/** /**
* Get the capabilities of the native cursor. Return a bit mask of the native cursor capabilities. * Get the capabilities of the native cursor. Return a bit mask of the native cursor capabilities.
@ -150,10 +146,9 @@ public class Cursor {
* @return A bit mask with native cursor capabilities. * @return A bit mask with native cursor capabilities.
*/ */
public static int getCapabilities() { public static int getCapabilities() {
synchronized (OpenGLPackageAccess.global_lock) { if (Mouse.getImplementation() != null) {
if (Mouse.getImplementation() != null)
return Mouse.getImplementation().getNativeCursorCapabilities(); return Mouse.getImplementation().getNativeCursorCapabilities();
else } else {
return OpenGLPackageAccess.createImplementation().getNativeCursorCapabilities(); return OpenGLPackageAccess.createImplementation().getNativeCursorCapabilities();
} }
} }

View File

@ -323,12 +323,10 @@ public class Keyboard {
* @throws LWJGLException if the keyboard could not be created for any reason * @throws LWJGLException if the keyboard could not be created for any reason
*/ */
public static void create() throws LWJGLException { 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() { private static void reset() {
readBuffer.limit(0); readBuffer.limit(0);
@ -341,23 +339,20 @@ public class Keyboard {
* @return true if the keyboard has been created * @return true if the keyboard has been created
*/ */
public static boolean isCreated() { public static boolean isCreated() {
synchronized (OpenGLPackageAccess.global_lock) {
return created; return created;
} }
}
/** /**
* "Destroy" the keyboard * "Destroy" the keyboard
*/ */
public static void destroy() { public static void destroy() {
synchronized (OpenGLPackageAccess.global_lock) { if (!created) {
if (!created)
return; return;
}
created = false; created = false;
implementation.destroyKeyboard(); implementation.destroyKeyboard();
reset(); reset();
} }
}
/** /**
* Polls the keyboard for its current state. Access the polled values using the * Polls the keyboard for its current state. Access the polled values using the
@ -381,13 +376,12 @@ public class Keyboard {
* @see org.lwjgl.input.Keyboard#getEventCharacter() * @see org.lwjgl.input.Keyboard#getEventCharacter()
*/ */
public static void poll() { public static void poll() {
synchronized (OpenGLPackageAccess.global_lock) { if (!created) {
if (!created)
throw new IllegalStateException("Keyboard must be created before you can poll the device"); throw new IllegalStateException("Keyboard must be created before you can poll the device");
}
implementation.pollKeyboard(keyDownBuffer); implementation.pollKeyboard(keyDownBuffer);
read(); read();
} }
}
private static void read() { private static void read() {
readBuffer.compact(); readBuffer.compact();
@ -401,11 +395,10 @@ public class Keyboard {
* @return true if the key is down according to the last poll() * @return true if the key is down according to the last poll()
*/ */
public static boolean isKeyDown(int key) { public static boolean isKeyDown(int key) {
synchronized (OpenGLPackageAccess.global_lock) { if (!created) {
if (!created)
throw new IllegalStateException("Keyboard must be created before you can query key state"); throw new IllegalStateException("Keyboard must be created before you can query key state");
return keyDownBuffer.get(key) != 0;
} }
return keyDownBuffer.get(key) != 0;
} }
/** /**
@ -425,7 +418,7 @@ public class Keyboard {
* @param key The key * @param key The key
* @return a String with the key's human readable name in it or null if the key is unnamed * @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]; return keyName[key];
} }
@ -433,20 +426,20 @@ public class Keyboard {
* Get's a key's index. If the key is unrecognised then KEY_NONE is returned. * Get's a key's index. If the key is unrecognised then KEY_NONE is returned.
* @param keyName The key name * @param keyName The key name
*/ */
public static synchronized int getKeyIndex(String keyName) { public static int getKeyIndex(String keyName) {
Integer ret = keyMap.get(keyName); Integer ret = keyMap.get(keyName);
if (ret == null) if (ret == null) {
return KEY_NONE; return KEY_NONE;
else } else {
return ret; return ret;
} }
}
/** /**
* Gets the number of keyboard events waiting after doing a buffer enabled poll(). * Gets the number of keyboard events waiting after doing a buffer enabled poll().
* @return the number of keyboard events * @return the number of keyboard events
*/ */
public static int getNumKeyboardEvents() { public static int getNumKeyboardEvents() {
synchronized (OpenGLPackageAccess.global_lock) {
if (!created) if (!created)
throw new IllegalStateException("Keyboard must be created before you can read events"); throw new IllegalStateException("Keyboard must be created before you can read events");
int old_position = readBuffer.position(); int old_position = readBuffer.position();
@ -456,7 +449,6 @@ public class Keyboard {
readBuffer.position(old_position); readBuffer.position(old_position);
return num_events; return num_events;
} }
}
/** /**
* Gets the next keyboard event. You can query which key caused the event by using * Gets the next keyboard event. You can query which key caused the event by using
@ -470,16 +462,13 @@ public class Keyboard {
* @return true if a keyboard event was read, false otherwise * @return true if a keyboard event was read, false otherwise
*/ */
public static boolean next() { public static boolean next() {
synchronized (OpenGLPackageAccess.global_lock) {
if (!created) if (!created)
throw new IllegalStateException("Keyboard must be created before you can read events"); throw new IllegalStateException("Keyboard must be created before you can read events");
boolean result; boolean result;
while ((result = readNext(current_event)) && current_event.repeat && !repeat_enabled) while ((result = readNext(current_event)) && current_event.repeat && !repeat_enabled) {}
;
return result; return result;
} }
}
/** /**
* Controls whether repeat events are reported or not. If repeat events * Controls whether repeat events are reported or not. If repeat events
@ -490,10 +479,8 @@ public class Keyboard {
* @see org.lwjgl.input.Keyboard#getEventKey() * @see org.lwjgl.input.Keyboard#getEventKey()
*/ */
public static void enableRepeatEvents(boolean enable) { public static void enableRepeatEvents(boolean enable) {
synchronized (OpenGLPackageAccess.global_lock) {
repeat_enabled = enable; repeat_enabled = enable;
} }
}
/** /**
* Check whether repeat events are currently reported or not. * Check whether repeat events are currently reported or not.
@ -502,10 +489,8 @@ public class Keyboard {
* @see org.lwjgl.input.Keyboard#getEventKey() * @see org.lwjgl.input.Keyboard#getEventKey()
*/ */
public static boolean areRepeatEventsEnabled() { public static boolean areRepeatEventsEnabled() {
synchronized (OpenGLPackageAccess.global_lock) {
return repeat_enabled; return repeat_enabled;
} }
}
private static boolean readNext(KeyEvent event) { private static boolean readNext(KeyEvent event) {
if (readBuffer.hasRemaining()) { if (readBuffer.hasRemaining()) {
@ -530,10 +515,8 @@ public class Keyboard {
* @return The character from the current event * @return The character from the current event
*/ */
public static char getEventCharacter() { public static char getEventCharacter() {
synchronized (OpenGLPackageAccess.global_lock) {
return (char)current_event.character; return (char)current_event.character;
} }
}
/** /**
* Please note that the key code returned is NOT valid against the * Please note that the key code returned is NOT valid against the
@ -543,10 +526,8 @@ public class Keyboard {
* @return The key from the current event * @return The key from the current event
*/ */
public static int getEventKey() { public static int getEventKey() {
synchronized (OpenGLPackageAccess.global_lock) {
return current_event.key; return current_event.key;
} }
}
/** /**
* Gets the state of the key that generated the * Gets the state of the key that generated the
@ -555,10 +536,8 @@ public class Keyboard {
* @return True if key was down, or false if released * @return True if key was down, or false if released
*/ */
public static boolean getEventKeyState() { public static boolean getEventKeyState() {
synchronized (OpenGLPackageAccess.global_lock) {
return current_event.state; return current_event.state;
} }
}
/** /**
* Gets the time in nanoseconds of the current event. * Gets the time in nanoseconds of the current event.
@ -568,10 +547,8 @@ public class Keyboard {
* @return The time in nanoseconds of the current event * @return The time in nanoseconds of the current event
*/ */
public static long getEventNanoseconds() { public static long getEventNanoseconds() {
synchronized (OpenGLPackageAccess.global_lock) {
return current_event.nanos; return current_event.nanos;
} }
}
/** /**
* @see org.lwjgl.input.Keyboard#enableRepeatEvents(boolean) * @see org.lwjgl.input.Keyboard#enableRepeatEvents(boolean)
@ -579,10 +556,8 @@ public class Keyboard {
* the current event is not a repeat even or if repeat events are disabled. * the current event is not a repeat even or if repeat events are disabled.
*/ */
public static boolean isRepeatEvent() { public static boolean isRepeatEvent() {
synchronized (OpenGLPackageAccess.global_lock) {
return current_event.repeat; return current_event.repeat;
} }
}
private static final class KeyEvent { private static final class KeyEvent {
/** The current keyboard character being examined */ /** The current keyboard character being examined */

View File

@ -165,10 +165,8 @@ public class Mouse {
* @return the currently bound native cursor, if any. * @return the currently bound native cursor, if any.
*/ */
public static Cursor getNativeCursor() { public static Cursor getNativeCursor() {
synchronized (OpenGLPackageAccess.global_lock) {
return currentCursor; return currentCursor;
} }
}
/** /**
* Binds a native cursor. If the cursor argument is null, any * Binds a native cursor. If the cursor argument is null, any
@ -183,9 +181,9 @@ public class Mouse {
* @throws LWJGLException if the cursor could not be set for any reason * @throws LWJGLException if the cursor could not be set for any reason
*/ */
public static Cursor setNativeCursor(Cursor cursor) throws LWJGLException { public static Cursor setNativeCursor(Cursor cursor) throws LWJGLException {
synchronized (OpenGLPackageAccess.global_lock) { if ((Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) == 0) {
if ((Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) == 0)
throw new IllegalStateException("Mouse doesn't support native cursors"); throw new IllegalStateException("Mouse doesn't support native cursors");
}
Cursor oldCursor = currentCursor; Cursor oldCursor = currentCursor;
currentCursor = cursor; currentCursor = cursor;
if (isCreated()) { if (isCreated()) {
@ -198,7 +196,6 @@ public class Mouse {
} }
return oldCursor; return oldCursor;
} }
}
public static boolean isClipMouseCoordinatesToWindow() { public static boolean isClipMouseCoordinatesToWindow() {
return clipMouseCoordinatesToWindow; return clipMouseCoordinatesToWindow;
@ -218,20 +215,18 @@ public class Mouse {
* to the window origin. * to the window origin.
*/ */
public static void setCursorPosition(int new_x, int new_y) { public static void setCursorPosition(int new_x, int new_y) {
synchronized (OpenGLPackageAccess.global_lock) { if (!isCreated()) {
if (!isCreated())
throw new IllegalStateException("Mouse is not created"); throw new IllegalStateException("Mouse is not created");
}
x = event_x = new_x; x = event_x = new_x;
y = event_y = new_y; y = event_y = new_y;
if (!isGrabbed() && (Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) != 0) { if (!isGrabbed() && (Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) != 0) {
implementation.setCursorPosition(x, y); implementation.setCursorPosition(x, y);
} } else {
else {
grab_x = new_x; grab_x = new_x;
grab_y = new_y; grab_y = new_y;
} }
} }
}
/** /**
* Static initialization * Static initialization
@ -293,35 +288,30 @@ public class Mouse {
* @throws LWJGLException if the mouse could not be created for any reason * @throws LWJGLException if the mouse could not be created for any reason
*/ */
public static void create() throws LWJGLException { 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 * @return true if the mouse has been created
*/ */
public static boolean isCreated() { public static boolean isCreated() {
synchronized (OpenGLPackageAccess.global_lock) {
return created; return created;
} }
}
/** /**
* "Destroy" the mouse. * "Destroy" the mouse.
*/ */
public static void destroy() { public static void destroy() {
synchronized (OpenGLPackageAccess.global_lock) {
if (!created) return; if (!created) return;
created = false; created = false;
buttons = null; buttons = null;
coord_buffer = null; coord_buffer = null;
implementation.destroyMouse(); implementation.destroyMouse();
} }
}
/** /**
* Polls the mouse for its current state. Access the polled values using the * Polls the mouse for its current state. Access the polled values using the
@ -348,8 +338,8 @@ public class Mouse {
* @see org.lwjgl.input.Mouse#getDWheel() * @see org.lwjgl.input.Mouse#getDWheel()
*/ */
public static void poll() { public static void poll() {
synchronized (OpenGLPackageAccess.global_lock) {
if (!created) throw new IllegalStateException("Mouse must be created before you can poll it"); if (!created) throw new IllegalStateException("Mouse must be created before you can poll it");
implementation.pollMouse(coord_buffer, buttons); implementation.pollMouse(coord_buffer, buttons);
/* If we're grabbed, poll returns mouse deltas, if not it returns absolute coordinates */ /* If we're grabbed, poll returns mouse deltas, if not it returns absolute coordinates */
@ -372,7 +362,7 @@ public class Mouse {
absolute_y = y = poll_coord2; absolute_y = y = poll_coord2;
} }
if(clipMouseCoordinatesToWindow) { if (clipMouseCoordinatesToWindow) {
x = Math.min(Display.getWidth() - 1, Math.max(0, x)); x = Math.min(Display.getWidth() - 1, Math.max(0, x));
y = Math.min(Display.getHeight() - 1, Math.max(0, y)); y = Math.min(Display.getHeight() - 1, Math.max(0, y));
} }
@ -380,7 +370,6 @@ public class Mouse {
dwheel += poll_dwheel; dwheel += poll_dwheel;
read(); read();
} }
}
private static void read() { private static void read() {
readBuffer.compact(); readBuffer.compact();
@ -395,11 +384,10 @@ public class Mouse {
* @return true if the specified button is down * @return true if the specified button is down
*/ */
public static boolean isButtonDown(int button) { 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 (!created) throw new IllegalStateException("Mouse must be created before you can poll the button state");
if (button >= buttonCount || button < 0) if (button >= buttonCount || button < 0) {
return false; return false;
else } else {
return buttons.get(button) == 1; return buttons.get(button) == 1;
} }
} }
@ -410,10 +398,9 @@ public class Mouse {
* @return a String with the button's human readable name in it or null if the button is unnamed * @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) { public static String getButtonName(int button) {
synchronized (OpenGLPackageAccess.global_lock) { if (button >= buttonName.length || button < 0) {
if (button >= buttonName.length || button < 0)
return null; return null;
else } else {
return buttonName[button]; return buttonName[button];
} }
} }
@ -423,11 +410,10 @@ public class Mouse {
* @param buttonName The button name * @param buttonName The button name
*/ */
public static int getButtonIndex(String buttonName) { public static int getButtonIndex(String buttonName) {
synchronized (OpenGLPackageAccess.global_lock) {
Integer ret = buttonMap.get(buttonName); Integer ret = buttonMap.get(buttonName);
if (ret == null) if (ret == null) {
return -1; return -1;
else } else {
return ret; return ret;
} }
} }
@ -442,7 +428,6 @@ public class Mouse {
* @return true if a mouse event was read, false otherwise * @return true if a mouse event was read, false otherwise
*/ */
public static boolean next() { public static boolean next() {
synchronized (OpenGLPackageAccess.global_lock) {
if (!created) throw new IllegalStateException("Mouse must be created before you can read events"); if (!created) throw new IllegalStateException("Mouse must be created before you can read events");
if (readBuffer.hasRemaining()) { if (readBuffer.hasRemaining()) {
eventButton = readBuffer.get(); eventButton = readBuffer.get();
@ -464,14 +449,14 @@ public class Mouse {
last_event_raw_x = new_event_x; last_event_raw_x = new_event_x;
last_event_raw_y = new_event_y; last_event_raw_y = new_event_y;
} }
if(clipMouseCoordinatesToWindow) { if (clipMouseCoordinatesToWindow) {
event_x = Math.min(Display.getWidth() - 1, Math.max(0, event_x)); 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_y = Math.min(Display.getHeight() - 1, Math.max(0, event_y));
} }
event_dwheel = readBuffer.getInt(); event_dwheel = readBuffer.getInt();
event_nanos = readBuffer.getLong(); event_nanos = readBuffer.getLong();
return true; return true;
} else } else {
return false; return false;
} }
} }
@ -480,65 +465,51 @@ public class Mouse {
* @return Current events button. Returns -1 if no button state was changed * @return Current events button. Returns -1 if no button state was changed
*/ */
public static int getEventButton() { public static int getEventButton() {
synchronized (OpenGLPackageAccess.global_lock) {
return eventButton; return eventButton;
} }
}
/** /**
* Get the current events button state. * Get the current events button state.
* @return Current events button state. * @return Current events button state.
*/ */
public static boolean getEventButtonState() { public static boolean getEventButtonState() {
synchronized (OpenGLPackageAccess.global_lock) {
return eventState; return eventState;
} }
}
/** /**
* @return Current events delta x. * @return Current events delta x.
*/ */
public static int getEventDX() { public static int getEventDX() {
synchronized (OpenGLPackageAccess.global_lock) {
return event_dx; return event_dx;
} }
}
/** /**
* @return Current events delta y. * @return Current events delta y.
*/ */
public static int getEventDY() { public static int getEventDY() {
synchronized (OpenGLPackageAccess.global_lock) {
return event_dy; return event_dy;
} }
}
/** /**
* @return Current events absolute x. * @return Current events absolute x.
*/ */
public static int getEventX() { public static int getEventX() {
synchronized (OpenGLPackageAccess.global_lock) {
return event_x; return event_x;
} }
}
/** /**
* @return Current events absolute y. * @return Current events absolute y.
*/ */
public static int getEventY() { public static int getEventY() {
synchronized (OpenGLPackageAccess.global_lock) {
return event_y; return event_y;
} }
}
/** /**
* @return Current events delta z * @return Current events delta z
*/ */
public static int getEventDWheel() { public static int getEventDWheel() {
synchronized (OpenGLPackageAccess.global_lock) {
return event_dwheel; return event_dwheel;
} }
}
/** /**
* Gets the time in nanoseconds of the current event. * Gets the time in nanoseconds of the current event.
@ -549,10 +520,8 @@ public class Mouse {
* @return The time in nanoseconds of the current event * @return The time in nanoseconds of the current event
*/ */
public static long getEventNanoseconds() { public static long getEventNanoseconds() {
synchronized (OpenGLPackageAccess.global_lock) {
return event_nanos; return event_nanos;
} }
}
/** /**
* Retrieves the absolute position. It will be clamped to * Retrieves the absolute position. It will be clamped to
@ -561,10 +530,8 @@ public class Mouse {
* @return Absolute x axis position of mouse * @return Absolute x axis position of mouse
*/ */
public static int getX() { public static int getX() {
synchronized (OpenGLPackageAccess.global_lock) {
return x; return x;
} }
}
/** /**
* Retrieves the absolute position. It will be clamped to * Retrieves the absolute position. It will be clamped to
@ -573,70 +540,56 @@ public class Mouse {
* @return Absolute y axis position of mouse * @return Absolute y axis position of mouse
*/ */
public static int getY() { public static int getY() {
synchronized (OpenGLPackageAccess.global_lock) {
return y; return y;
} }
}
/** /**
* @return Movement on the x axis since last time getDX() was called. * @return Movement on the x axis since last time getDX() was called.
*/ */
public static int getDX() { public static int getDX() {
synchronized (OpenGLPackageAccess.global_lock) {
int result = dx; int result = dx;
dx = 0; dx = 0;
return result; return result;
} }
}
/** /**
* @return Movement on the y axis since last time getDY() was called. * @return Movement on the y axis since last time getDY() was called.
*/ */
public static int getDY() { public static int getDY() {
synchronized (OpenGLPackageAccess.global_lock) {
int result = dy; int result = dy;
dy = 0; dy = 0;
return result; return result;
} }
}
/** /**
* @return Movement of the wheel since last time getDWheel() was called * @return Movement of the wheel since last time getDWheel() was called
*/ */
public static int getDWheel() { public static int getDWheel() {
synchronized (OpenGLPackageAccess.global_lock) {
int result = dwheel; int result = dwheel;
dwheel = 0; dwheel = 0;
return result; return result;
} }
}
/** /**
* @return Number of buttons on this mouse * @return Number of buttons on this mouse
*/ */
public static int getButtonCount() { public static int getButtonCount() {
synchronized (OpenGLPackageAccess.global_lock) {
return buttonCount; return buttonCount;
} }
}
/** /**
* @return Whether or not this mouse has wheel support * @return Whether or not this mouse has wheel support
*/ */
public static boolean hasWheel() { public static boolean hasWheel() {
synchronized (OpenGLPackageAccess.global_lock) {
return hasWheel; return hasWheel;
} }
}
/** /**
* @return whether or not the mouse has grabbed the cursor * @return whether or not the mouse has grabbed the cursor
*/ */
public static boolean isGrabbed() { public static boolean isGrabbed() {
synchronized (OpenGLPackageAccess.global_lock) {
return isGrabbed; return isGrabbed;
} }
}
/** /**
* Sets whether or not the mouse has grabbed the cursor * Sets whether or not the mouse has grabbed the cursor
@ -647,16 +600,18 @@ public class Mouse {
* @param grab whether the mouse should be grabbed * @param grab whether the mouse should be grabbed
*/ */
public static void setGrabbed(boolean grab) { public static void setGrabbed(boolean grab) {
synchronized (OpenGLPackageAccess.global_lock) {
boolean grabbed = isGrabbed; boolean grabbed = isGrabbed;
if (grabbed == grab) return;
isGrabbed = grab; isGrabbed = grab;
if (isCreated()) {
if (!isCreated()) return;
if (grab && !grabbed) { if (grab && !grabbed) {
// store location mouse was grabbed // store location mouse was grabbed
grab_x = x; grab_x = x;
grab_y = y; grab_y = y;
} } else if (!grab && grabbed) {
else if (!grab && grabbed) {
// move mouse back to location it was grabbed before ungrabbing // move mouse back to location it was grabbed before ungrabbing
if ((Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) != 0) if ((Cursor.getCapabilities() & Cursor.CURSOR_ONE_BIT_TRANSPARENCY) != 0)
implementation.setCursorPosition(grab_x, grab_y); implementation.setCursorPosition(grab_x, grab_y);
@ -671,8 +626,6 @@ public class Mouse {
last_event_raw_y = y; last_event_raw_y = y;
resetMouse(); resetMouse();
} }
}
}
/** /**
* Updates the cursor, so that animation can be changed if needed. * Updates the cursor, so that animation can be changed if needed.
@ -680,7 +633,6 @@ public class Mouse {
* shouldn't be called otherwise * shouldn't be called otherwise
*/ */
public static void updateCursor() { public static void updateCursor() {
synchronized (OpenGLPackageAccess.global_lock) {
if (emulateCursorAnimation && currentCursor != null && currentCursor.hasTimedOut() && Mouse.isInsideWindow()) { if (emulateCursorAnimation && currentCursor != null && currentCursor.hasTimedOut() && Mouse.isInsideWindow()) {
currentCursor.nextCursor(); currentCursor.nextCursor();
try { try {
@ -690,7 +642,6 @@ public class Mouse {
} }
} }
} }
}
/** /**
* Retrieves whether or not the mouse cursor is within the bounds of the window. * Retrieves whether or not the mouse cursor is within the bounds of the window.

View File

@ -224,7 +224,7 @@ public final class ALC10 {
boolean result = nalcCloseDevice(getDevice(device)); boolean result = nalcCloseDevice(getDevice(device));
synchronized (devices) { synchronized (devices) {
device.setInvalid(); device.setInvalid();
devices.remove(new Long(device.device)); devices.remove(Long.valueOf(device.device));
} }
return result; return result;

View File

@ -118,7 +118,7 @@ public final class ALC11 {
boolean result = nalcCaptureCloseDevice(ALC10.getDevice(device)); boolean result = nalcCaptureCloseDevice(ALC10.getDevice(device));
synchronized (ALC10.devices) { synchronized (ALC10.devices) {
device.setInvalid(); device.setInvalid();
ALC10.devices.remove(new Long(device.device)); ALC10.devices.remove(Long.valueOf(device.device));
} }
return result; return result;
} }

View File

@ -60,6 +60,7 @@ import java.nio.FloatBuffer;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects;
import java.util.HashSet; import java.util.HashSet;
import static org.lwjgl.LWJGLUtil.getPrivilegedBoolean; import static org.lwjgl.LWJGLUtil.getPrivilegedBoolean;
@ -127,10 +128,8 @@ public final class Display {
private static final ComponentListener component_listener = new ComponentAdapter() { private static final ComponentListener component_listener = new ComponentAdapter() {
public void componentResized(ComponentEvent e) { public void componentResized(ComponentEvent e) {
synchronized ( GlobalLock.lock ) {
parent_resized = true; parent_resized = true;
} }
}
}; };
static { static {
@ -186,25 +185,29 @@ public final class Display {
* @return an array of all display modes the system reckons it can handle. * @return an array of all display modes the system reckons it can handle.
*/ */
public static DisplayMode[] getAvailableDisplayModes() throws LWJGLException { public static DisplayMode[] getAvailableDisplayModes() throws LWJGLException {
synchronized ( GlobalLock.lock ) {
DisplayMode[] unfilteredModes = display_impl.getAvailableDisplayModes(); DisplayMode[] unfilteredModes = display_impl.getAvailableDisplayModes();
if ( unfilteredModes == null ) { if (unfilteredModes == null) {
return new DisplayMode[0]; return new DisplayMode[0];
} }
if (unfilteredModes.length <= 1) {
return unfilteredModes;
}
// We'll use a HashSet to filter out the duplicated modes // We'll use a HashSet to filter out the duplicated modes
HashSet<DisplayMode> modes = new HashSet<DisplayMode>(unfilteredModes.length); HashSet<DisplayMode> modes = new HashSet<>(unfilteredModes.length);
modes.addAll(Arrays.asList(unfilteredModes)); for (DisplayMode mode : unfilteredModes) {
modes.add(mode);
}
DisplayMode[] filteredModes = new DisplayMode[modes.size()]; DisplayMode[] filteredModes = new DisplayMode[modes.size()];
modes.toArray(filteredModes); modes.toArray(filteredModes);
LWJGLUtil.log("Removed " + (unfilteredModes.length - filteredModes.length) + " duplicate displaymodes"); int n = unfilteredModes.length - filteredModes.length;
LWJGLUtil.logger().log(() -> "Removed " + n + " duplicate displaymodes");
return filteredModes; return filteredModes;
} }
}
/** /**
* Return the initial desktop display mode. * Return the initial desktop display mode.
@ -236,14 +239,17 @@ public final class Display {
* @throws LWJGLException if the display mode could not be set * @throws LWJGLException if the display mode could not be set
*/ */
public static void setDisplayMode(DisplayMode mode) throws LWJGLException { public static void setDisplayMode(DisplayMode mode) throws LWJGLException {
synchronized ( GlobalLock.lock ) { Objects.requireNonNull(mode, "mode must be non-null");
if ( mode == null )
throw new NullPointerException("mode must be non-null"); if (mode == current_mode) return;
boolean was_fullscreen = isFullscreen(); boolean was_fullscreen = isFullscreen();
current_mode = mode; current_mode = mode;
if ( !isCreated() || parent != null )
return; if (!isCreated() || parent != null) return;
destroyWindow(); destroyWindow();
// If mode is not fullscreen capable, make sure we are in windowed mode // If mode is not fullscreen capable, make sure we are in windowed mode
try { try {
if ( was_fullscreen && !isFullscreen() ) if ( was_fullscreen && !isFullscreen() )
@ -258,7 +264,6 @@ public final class Display {
throw e; throw e;
} }
} }
}
private static DisplayMode getEffectiveMode() { private static DisplayMode getEffectiveMode() {
return !isFullscreen() && parent != null ? new DisplayMode(parent.getWidth(), parent.getHeight()) : current_mode; return !isFullscreen() && parent != null ? new DisplayMode(parent.getWidth(), parent.getHeight()) : current_mode;
@ -370,7 +375,6 @@ public final class Display {
* @param contrast The contrast, larger than 0.0. * @param contrast The contrast, larger than 0.0.
*/ */
public static void setDisplayConfiguration(float gamma, float brightness, float contrast) throws LWJGLException { public static void setDisplayConfiguration(float gamma, float brightness, float contrast) throws LWJGLException {
synchronized ( GlobalLock.lock ) {
if ( !isCreated() ) { if ( !isCreated() ) {
throw new LWJGLException("Display not yet created."); throw new LWJGLException("Display not yet created.");
} }
@ -401,7 +405,6 @@ public final class Display {
display_impl.setGammaRamp(gammaRamp); display_impl.setGammaRamp(gammaRamp);
LWJGLUtil.log("Gamma set, gamma = " + gamma + ", brightness = " + brightness + ", contrast = " + contrast); LWJGLUtil.log("Gamma set, gamma = " + gamma + ", brightness = " + brightness + ", contrast = " + contrast);
} }
}
/** /**
* An accurate sync method that will attempt to run at a constant frame rate. * An accurate sync method that will attempt to run at a constant frame rate.
@ -434,7 +437,6 @@ public final class Display {
* the Dispaly will inherit the size of the parent, disregarding the currently set display mode.<p> * the Dispaly will inherit the size of the parent, disregarding the currently set display mode.<p>
*/ */
public static void setParent(Canvas parent) throws LWJGLException { public static void setParent(Canvas parent) throws LWJGLException {
synchronized ( GlobalLock.lock ) {
if ( Display.parent != parent ) { if ( Display.parent != parent ) {
Display.parent = parent; Display.parent = parent;
if ( !isCreated() ) if ( !isCreated() )
@ -455,7 +457,6 @@ public final class Display {
} }
} }
} }
}
/** /**
* Set the fullscreen mode of the context. If no context has been created through create(), * Set the fullscreen mode of the context. If no context has been created through create(),
@ -489,16 +490,14 @@ public final class Display {
} }
private static void setDisplayModeAndFullscreenInternal(boolean fullscreen, DisplayMode mode) throws LWJGLException { private static void setDisplayModeAndFullscreenInternal(boolean fullscreen, DisplayMode mode) throws LWJGLException {
synchronized ( GlobalLock.lock ) {
if ( mode == null ) if ( mode == null )
throw new NullPointerException("mode must be non-null"); throw new NullPointerException("mode must be non-null");
DisplayMode old_mode = current_mode; DisplayMode old_mode = current_mode;
current_mode = mode; current_mode = mode;
boolean was_fullscreen = isFullscreen(); boolean was_fullscreen = isFullscreen();
Display.fullscreen = fullscreen; Display.fullscreen = fullscreen;
if ( was_fullscreen != isFullscreen() || !mode.equals(old_mode) ) { if (was_fullscreen != isFullscreen() || !mode.equals(old_mode)) {
if ( !isCreated() ) if (!isCreated()) return;
return;
destroyWindow(); destroyWindow();
try { try {
if ( isFullscreen() ) { if ( isFullscreen() ) {
@ -515,7 +514,6 @@ public final class Display {
} }
} }
} }
}
/** @return whether the Display is in fullscreen mode */ /** @return whether the Display is in fullscreen mode */
public static boolean isFullscreen() { public static boolean isFullscreen() {
@ -528,41 +526,37 @@ public final class Display {
* @param newTitle The new window title * @param newTitle The new window title
*/ */
public static void setTitle(String newTitle) { public static void setTitle(String newTitle) {
synchronized ( GlobalLock.lock ) {
if ( newTitle == null ) { if ( newTitle == null ) {
newTitle = ""; newTitle = "";
} }
title = newTitle; title = newTitle;
if ( isCreated() ) if (isCreated()) {
display_impl.setTitle(title); display_impl.setTitle(title);
} }
} }
/** @return true if the user or operating system has asked the window to close */ /** @return true if the user or operating system has asked the window to close */
public static boolean isCloseRequested() { public static boolean isCloseRequested() {
synchronized ( GlobalLock.lock ) { if (!isCreated()) {
if ( !isCreated() )
throw new IllegalStateException("Cannot determine close requested state of uncreated window"); throw new IllegalStateException("Cannot determine close requested state of uncreated window");
return display_impl.isCloseRequested();
} }
return display_impl.isCloseRequested();
} }
/** @return true if the window is visible, false if not */ /** @return true if the window is visible, false if not */
public static boolean isVisible() { public static boolean isVisible() {
synchronized ( GlobalLock.lock ) { if (!isCreated()) {
if ( !isCreated() )
throw new IllegalStateException("Cannot determine minimized state of uncreated window"); throw new IllegalStateException("Cannot determine minimized state of uncreated window");
return display_impl.isVisible();
} }
return display_impl.isVisible();
} }
/** @return true if window is active, that is, the foreground display of the operating system. */ /** @return true if window is active, that is, the foreground display of the operating system. */
public static boolean isActive() { public static boolean isActive() {
synchronized ( GlobalLock.lock ) { if (!isCreated()) {
if ( !isCreated() )
throw new IllegalStateException("Cannot determine focused state of uncreated window"); throw new IllegalStateException("Cannot determine focused state of uncreated window");
return display_impl.isActive();
} }
return display_impl.isActive();
} }
/** /**
@ -576,11 +570,10 @@ public final class Display {
* and needs to repaint itself * and needs to repaint itself
*/ */
public static boolean isDirty() { public static boolean isDirty() {
synchronized ( GlobalLock.lock ) { if (!isCreated()) {
if ( !isCreated() )
throw new IllegalStateException("Cannot determine dirty state of uncreated window"); throw new IllegalStateException("Cannot determine dirty state of uncreated window");
return display_impl.isDirty();
} }
return display_impl.isDirty();
} }
/** /**
@ -589,12 +582,11 @@ public final class Display {
* this method if update() is called periodically. * this method if update() is called periodically.
*/ */
public static void processMessages() { public static void processMessages() {
synchronized ( GlobalLock.lock ) { if (!isCreated()) {
if ( !isCreated() )
throw new IllegalStateException("Display not created"); throw new IllegalStateException("Display not created");
}
display_impl.update(); display_impl.update();
}
pollDevices(); pollDevices();
} }
@ -605,14 +597,15 @@ public final class Display {
* @throws OpenGLException if an OpenGL error has occured since the last call to glGetError() * @throws OpenGLException if an OpenGL error has occured since the last call to glGetError()
*/ */
public static void swapBuffers() throws LWJGLException { public static void swapBuffers() throws LWJGLException {
synchronized ( GlobalLock.lock ) { if (!isCreated()) {
if ( !isCreated() )
throw new IllegalStateException("Display not created"); throw new IllegalStateException("Display not created");
if ( LWJGLUtil.DEBUG )
drawable.checkGLError();
drawable.swapBuffers();
} }
if (LWJGLUtil.DEBUG) {
drawable.checkGLError();
}
drawable.swapBuffers();
} }
/** /**
@ -632,12 +625,12 @@ public final class Display {
* @param processMessages Poll input devices if true * @param processMessages Poll input devices if true
*/ */
public static void update(boolean processMessages) { public static void update(boolean processMessages) {
synchronized ( GlobalLock.lock ) { if (!isCreated()) {
if ( !isCreated() )
throw new IllegalStateException("Display not created"); throw new IllegalStateException("Display not created");
}
// We paint only when the window is visible or dirty // We paint only when the window is visible or dirty
if ( display_impl.isVisible() || display_impl.isDirty() ) { if (display_impl.isVisible() || display_impl.isDirty()) {
try { try {
swapBuffers(); swapBuffers();
} catch (LWJGLException e) { } catch (LWJGLException e) {
@ -647,34 +640,34 @@ public final class Display {
window_resized = !isFullscreen() && parent == null && display_impl.wasResized(); window_resized = !isFullscreen() && parent == null && display_impl.wasResized();
if ( window_resized ) { if (window_resized) {
width = display_impl.getWidth(); width = display_impl.getWidth();
height = display_impl.getHeight(); height = display_impl.getHeight();
} }
if ( parent_resized ) { if (parent_resized) {
reshape(); reshape();
parent_resized = false; parent_resized = false;
window_resized = true; window_resized = true;
} }
if ( processMessages ) if (processMessages) {
processMessages(); processMessages();
} }
} }
static void pollDevices() { static void pollDevices() {
// Poll the input devices while we're here // Poll the input devices while we're here
if ( Mouse.isCreated() ) { if (Mouse.isCreated()) {
Mouse.poll(); Mouse.poll();
Mouse.updateCursor(); Mouse.updateCursor();
} }
if ( Keyboard.isCreated() ) { if (Keyboard.isCreated()) {
Keyboard.poll(); Keyboard.poll();
} }
if ( Controllers.isCreated() ) { if (Controllers.isCreated()) {
Controllers.poll(); Controllers.poll();
} }
} }
@ -703,20 +696,16 @@ public final class Display {
} }
private static void removeShutdownHook() { private static void removeShutdownHook() {
AccessController.doPrivileged(new PrivilegedAction<Object>() { AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
public Object run() {
Runtime.getRuntime().removeShutdownHook(shutdown_hook); Runtime.getRuntime().removeShutdownHook(shutdown_hook);
return null; return null;
}
}); });
} }
private static void registerShutdownHook() { private static void registerShutdownHook() {
AccessController.doPrivileged(new PrivilegedAction<Object>() { AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
public Object run() {
Runtime.getRuntime().addShutdownHook(shutdown_hook); Runtime.getRuntime().addShutdownHook(shutdown_hook);
return null; return null;
}
}); });
} }
@ -749,10 +738,8 @@ public final class Display {
* @throws LWJGLException * @throws LWJGLException
*/ */
public static void create(PixelFormat pixel_format) 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);
} }
}
/** /**
* Create the OpenGL context with the given minimum parameters. If isFullscreen() is true or if windowed * Create the OpenGL context with the given minimum parameters. If isFullscreen() is true or if windowed
@ -769,10 +756,8 @@ public final class Display {
* @throws LWJGLException * @throws LWJGLException
*/ */
public static void create(PixelFormat pixel_format, Drawable shared_drawable) 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);
} }
}
/** /**
* Create the OpenGL context with the given minimum parameters. If isFullscreen() is true or if windowed * Create the OpenGL context with the given minimum parameters. If isFullscreen() is true or if windowed
@ -789,10 +774,8 @@ public final class Display {
* @throws LWJGLException * @throws LWJGLException
*/ */
public static void create(PixelFormat pixel_format, ContextAttribs attribs) 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);
} }
}
/** /**
* Create the OpenGL context with the given minimum parameters. If isFullscreen() is true or if windowed * Create the OpenGL context with the given minimum parameters. If isFullscreen() is true or if windowed
@ -881,10 +864,8 @@ public final class Display {
*/ */
public static void create(PixelFormatLWJGL pixel_format) throws LWJGLException { public static void create(PixelFormatLWJGL pixel_format) throws LWJGLException {
synchronized ( GlobalLock.lock ) {
create(pixel_format, null, null); create(pixel_format, null, null);
} }
}
/** /**
* Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed * Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed
@ -901,10 +882,8 @@ public final class Display {
* @throws LWJGLException * @throws LWJGLException
*/ */
public static void create(PixelFormatLWJGL pixel_format, Drawable shared_drawable) 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);
} }
}
/** /**
* Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed * Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed
@ -921,10 +900,8 @@ public final class Display {
* @throws LWJGLException * @throws LWJGLException
*/ */
public static void create(PixelFormatLWJGL pixel_format, org.lwjgl.opengles.ContextAttribs attribs) 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);
} }
}
/** /**
* Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed * Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed
@ -1038,15 +1015,15 @@ public final class Display {
private static void initControls() { private static void initControls() {
// Automatically create mouse, keyboard and controller // Automatically create mouse, keyboard and controller
if ( !getPrivilegedBoolean("org.lwjgl.opengl.Display.noinput") ) { if (!getPrivilegedBoolean("org.lwjgl.opengl.Display.noinput")) {
if ( !Mouse.isCreated() && !getPrivilegedBoolean("org.lwjgl.opengl.Display.nomouse") ) { if (!Mouse.isCreated() && !getPrivilegedBoolean("org.lwjgl.opengl.Display.nomouse")) {
try { try {
Mouse.create(); Mouse.create();
} catch (LWJGLException e) { } catch (LWJGLException e) {
LWJGLUtil.logger().log("Failed to create Mouse", 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 { try {
Keyboard.create(); Keyboard.create();
} catch (LWJGLException e) { } catch (LWJGLException e) {
@ -1091,11 +1068,11 @@ public final class Display {
* @param value The swap interval in frames, 0 to disable * @param value The swap interval in frames, 0 to disable
*/ */
public static void setSwapInterval(int value) throws LWJGLException { public static void setSwapInterval(int value) throws LWJGLException {
synchronized ( GlobalLock.lock ) { if (value != swap_interval) {
swap_interval = value; swap_interval = value;
if ( isCreated() ) if (isCreated()) {
drawable.setSwapInterval(swap_interval); drawable.setSwapInterval(value);
}
} }
} }
@ -1120,7 +1097,6 @@ public final class Display {
* @param new_y The new window location on the y axis * @param new_y The new window location on the y axis
*/ */
public static void setLocation(int new_x, int new_y) { public static void setLocation(int new_x, int new_y) {
synchronized ( GlobalLock.lock ) {
// cache position // cache position
x = new_x; x = new_x;
y = new_y; y = new_y;
@ -1130,7 +1106,6 @@ public final class Display {
reshape(); reshape();
} }
} }
}
private static void reshape() { private static void reshape() {
DisplayMode mode = getEffectiveMode(); DisplayMode mode = getEffectiveMode();
@ -1175,10 +1150,9 @@ public final class Display {
* @return number of icons used, or 0 if display hasn't been created * @return number of icons used, or 0 if display hasn't been created
*/ */
public static int setIcon(ByteBuffer[] icons) { public static int setIcon(ByteBuffer[] icons) {
synchronized ( GlobalLock.lock ) {
// make deep copy so we dont rely on the supplied buffers later on // make deep copy so we dont rely on the supplied buffers later on
// don't recache! // don't recache!
if ( cached_icons != icons ) { if (cached_icons != icons) {
cached_icons = new ByteBuffer[icons.length]; cached_icons = new ByteBuffer[icons.length];
for ( int i = 0; i < icons.length; i++ ) { for ( int i = 0; i < icons.length; i++ ) {
cached_icons[i] = BufferUtils.createByteBuffer(icons[i].capacity()); cached_icons[i] = BufferUtils.createByteBuffer(icons[i].capacity());
@ -1189,13 +1163,12 @@ public final class Display {
} }
} }
if ( Display.isCreated() && parent == null ) { if (Display.isCreated() && parent == null) {
return display_impl.setIcon(cached_icons); return display_impl.setIcon(cached_icons);
} else { } else {
return 0; return 0;
} }
} }
}
/** /**
* Enable or disable the Display window to be resized. * Enable or disable the Display window to be resized.
@ -1204,11 +1177,13 @@ public final class Display {
* false to disable resizing on the Display window. * false to disable resizing on the Display window.
*/ */
public static void setResizable(boolean resizable) { public static void setResizable(boolean resizable) {
if (window_resizable != resizable) {
window_resizable = resizable; window_resizable = resizable;
if ( isCreated() ) { if (isCreated()) {
display_impl.setResizable(resizable); display_impl.setResizable(resizable);
} }
} }
}
/** /**
* @return true if the Display window is resizable. * @return true if the Display window is resizable.
@ -1235,7 +1210,6 @@ public final class Display {
* the parent will be returned. * the parent will be returned.
*/ */
public static int getX() { public static int getX() {
if (Display.isFullscreen()) { if (Display.isFullscreen()) {
return 0; return 0;
} }
@ -1255,7 +1229,6 @@ public final class Display {
* the parent will be returned. * the parent will be returned.
*/ */
public static int getY() { public static int getY() {
if (Display.isFullscreen()) { if (Display.isFullscreen()) {
return 0; return 0;
} }
@ -1277,7 +1250,6 @@ public final class Display {
* This value will be updated after a call to Display.update(). * This value will be updated after a call to Display.update().
*/ */
public static int getWidth() { public static int getWidth() {
if (Display.isFullscreen()) { if (Display.isFullscreen()) {
return Display.getDisplayMode().getWidth(); return Display.getDisplayMode().getWidth();
} }
@ -1299,7 +1271,6 @@ public final class Display {
* This value will be updated after a call to Display.update(). * This value will be updated after a call to Display.update().
*/ */
public static int getHeight() { public static int getHeight() {
if (Display.isFullscreen()) { if (Display.isFullscreen()) {
return Display.getDisplayMode().getHeight(); return Display.getDisplayMode().getHeight();
} }

View File

@ -81,10 +81,10 @@ public final class BackgroundLoadTest {
Util.checkGLError(); Util.checkGLError();
while ( run ) { while (run) {
if ( !Display.isVisible() ) if (!Display.isVisible()) {
Thread.yield(); Thread.yield();
else { } else {
handleIO(); handleIO();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -100,9 +100,10 @@ public final class BackgroundLoadTest {
Display.update(); Display.update();
if ( Display.isCloseRequested() ) if (Display.isCloseRequested()) {
break; break;
} }
}
cleanup(); cleanup();
System.exit(0); System.exit(0);
@ -115,7 +116,8 @@ public final class BackgroundLoadTest {
DisplayMode displayMode = null; DisplayMode displayMode = null;
try { try {
DisplayMode[] modes = Display.getAvailableDisplayModes(); displayMode = Display.getDisplayMode();
/*DisplayMode[] modes = Display.getAvailableDisplayModes();
displayMode = chooseMode(modes, 1024, 768); displayMode = chooseMode(modes, 1024, 768);
if ( displayMode == null ) if ( displayMode == null )
@ -126,7 +128,7 @@ public final class BackgroundLoadTest {
kill("Failed to set an appropriate display mode."); kill("Failed to set an appropriate display mode.");
System.out.println("Setting display mode to: " + displayMode); System.out.println("Setting display mode to: " + displayMode);
Display.setDisplayMode(displayMode); Display.setDisplayMode(displayMode);*/
Display.setTitle("Background Loading Test"); Display.setTitle("Background Loading Test");
Display.create(new PixelFormat(8, 24, 0)); Display.create(new PixelFormat(8, 24, 0));
} catch (LWJGLException e) { } catch (LWJGLException e) {
@ -189,18 +191,10 @@ public final class BackgroundLoadTest {
sphere = new Sphere(); sphere = new Sphere();
if ( "PB".equalsIgnoreCase(args[0]) ) { if ("PB".equalsIgnoreCase(args[0])) {
backgroundLoader = new BackgroundLoader() { backgroundLoader = new BackgroundLoader(() -> new Pbuffer(2, 2, new PixelFormat(8, 24, 0), Display.getDrawable()));
Drawable getDrawable() throws LWJGLException { } else if ("SD".equalsIgnoreCase(args[0])) {
return new Pbuffer(2, 2, new PixelFormat(8, 24, 0), Display.getDrawable()); backgroundLoader = new BackgroundLoader(() -> new SharedDrawable(Display.getDrawable()));
}
};
} else if ( "SD".equalsIgnoreCase(args[0]) ) {
backgroundLoader = new BackgroundLoader() {
Drawable getDrawable() throws LWJGLException {
return new SharedDrawable(Display.getDrawable());
}
};
} else { } else {
argsError(); argsError();
} }
@ -227,7 +221,7 @@ public final class BackgroundLoadTest {
glColor3f(1.0f, 1.0f, 1.0f); glColor3f(1.0f, 1.0f, 1.0f);
int texID = backgroundLoader.getTexID(); int texID = backgroundLoader.getTexID();
if ( texID == 0 ) { if (texID == 0) {
sphere.setTextureFlag(false); sphere.setTextureFlag(false);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} else { } else {
@ -238,7 +232,8 @@ public final class BackgroundLoadTest {
sphere.draw(1.0f, 32, 32); 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); glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} }
@ -247,9 +242,9 @@ public final class BackgroundLoadTest {
private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) { private static DisplayMode chooseMode(DisplayMode[] modes, int width, int height) {
DisplayMode bestMode = null; DisplayMode bestMode = null;
for ( DisplayMode mode : modes ) { for (DisplayMode mode : modes) {
if ( mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85 ) { if (mode.getWidth() == width && mode.getHeight() == height && mode.getFrequency() <= 85) {
if ( bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) ) if (bestMode == null || (mode.getBitsPerPixel() >= bestMode.getBitsPerPixel() && mode.getFrequency() > bestMode.getFrequency()) )
bestMode = mode; bestMode = mode;
} }
} }
@ -258,7 +253,9 @@ public final class BackgroundLoadTest {
} }
private static void cleanup() { private static void cleanup() {
if (backgroundLoader != null) {
backgroundLoader.cleanup(); backgroundLoader.cleanup();
}
Thread.yield(); // Let background thread finish. Thread.yield(); // Let background thread finish.

View File

@ -46,54 +46,56 @@ import org.lwjgl.util.Color;
import org.lwjgl.util.ReadableColor; import org.lwjgl.util.ReadableColor;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.concurrent.locks.ReentrantLock;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL32.*; import static org.lwjgl.opengl.GL32.*;
abstract class BackgroundLoader { final class BackgroundLoader {
private static final int WIDTH = 32; private static final int WIDTH = 64;
private static final int HEIGHT = 32; private static final int HEIGHT = 64;
// CPU synchronization
private final ReentrantLock lock = new ReentrantLock();
// GPU synchronization // GPU synchronization
private GLSync fence; private GLSync fence;
private Drawable drawable; private final DrawableSupplier drawableSupplier;
private Drawable drawable;
private int texID;
private boolean running; private boolean running;
private ByteBuffer texture; protected BackgroundLoader(DrawableSupplier drawableSupplier) {
private int texID; this.drawableSupplier = drawableSupplier;
this.running = true;
protected BackgroundLoader() {
running = true;
texture = BufferUtils.createByteBuffer(WIDTH * HEIGHT * 3);
} }
abstract Drawable getDrawable() throws LWJGLException;
void cleanup() { void cleanup() {
running = false; running = false;
} }
void start() throws LWJGLException { private void uploadTexture(int texID, ByteBuffer texture, boolean useFences) {
// The shared context must be created on the main thread. glBindTexture(GL_TEXTURE_2D, texID);
drawable = getDrawable(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
new Thread(new Runnable() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
public void run() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
System.out.println("-- Background Thread started --");
System.out.println("** Sleeping, no texture created yet **"); glBindTexture(GL_TEXTURE_2D, 0);
try { if (useFences) {
Thread.sleep(2000); //while (fence != null) {}
} catch (InterruptedException e) { fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
e.printStackTrace(); } 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 {
this.drawable = this.drawableSupplier.get();
new Thread(() -> {
System.out.println("-- Background Thread started --");
try { try {
// Make the shared context current in the worker thread // Make the shared context current in the worker thread
@ -104,69 +106,57 @@ abstract class BackgroundLoader {
System.out.println("** Drawable created **"); 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 // OpenGL commands from different contexts may be executed in any order. So we need a way to synchronize
final boolean useFences = GLContext.getCapabilities().OpenGL32; final boolean useFences = GLContext.getCapabilities().OpenGL32;
System.out.println("Using fences: " + useFences);
if ( useFences ) System.out.println("** Sleeping, no texture created yet **");
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.
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 **"); System.out.println("** Dummy texture created **");
long avgGenTime = 0L;
long avgUploadTime = 0L;
long lastUploadTime = 0L;
long lastTextureCreated = System.currentTimeMillis(); // Delay first texture creation long lastTextureCreated = System.currentTimeMillis(); // Delay first texture creation
int count = 0; int count = 0;
while ( running ) { while ( running ) {
long time = System.currentTimeMillis(); /*long time = System.currentTimeMillis();
if ( time - lastTextureCreated < 5000 ) { // Update the texture every 5 seconds if (time - lastTextureCreated < 2) { // Update the texture every 5 seconds
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue; continue;
} }*/
// Create the "true" texture // Create the "true" texture
if ( count % 2 == 0 ) long start = System.nanoTime();
createGradientTexture(Color.RED, Color.BLUE); if ( count % 2 == 0 ) {
else createGradientTexture(texture, Color.RED, Color.BLUE);
createGradientTexture(Color.GREEN, Color.YELLOW); } 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); //System.out.println("** Created new gradient texture **");
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 **");
lastTextureCreated = System.currentTimeMillis(); lastTextureCreated = System.currentTimeMillis();
count++; count++;
@ -175,24 +165,26 @@ abstract class BackgroundLoader {
drawable.destroy(); drawable.destroy();
System.out.println("-- Background Thread finished --"); 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(); }).start();
} }
int getTexID() { public final int getTexID() {
lock.lock(); //lock.lock();
try { try {
if ( fence != null ) { if (fence != null) {
glWaitSync(fence, 0, GL_TIMEOUT_IGNORED); glWaitSync(fence, 0, GL_TIMEOUT_IGNORED);
fence = null; fence = null;
} }
return texID; return texID;
} finally { } 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; int i = 0;
for ( int y = 0; y < HEIGHT; y++ ) { for ( int y = 0; y < HEIGHT; y++ ) {
for ( int x = 0; x < WIDTH; x++ ) { 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; float l = 0.0f;
int i = 0; int i = 0;
for ( int y = 0; y < HEIGHT; y++ ) { for ( int y = 0; y < HEIGHT; y++ ) {

View File

@ -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;
}