- * @version $Revision: 3418 $
- * $Id: AL.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
public final class AL {
/** ALCdevice instance. */
@@ -115,8 +115,13 @@
String[] library_names;
switch (LWJGLUtil.getPlatform()) {
case LWJGLUtil.PLATFORM_WINDOWS:
- libname = "OpenAL32";
- library_names = new String[]{"OpenAL64.dll", "OpenAL32.dll"};
+ if ( Sys.is64Bit() ) {
+ libname = "OpenAL64";
+ library_names = new String[]{"OpenAL64.dll"};
+ } else {
+ libname = "OpenAL32";
+ library_names = new String[]{"OpenAL32.dll"};
+ }
break;
case LWJGLUtil.PLATFORM_LINUX:
libname = "openal";
diff --git a/src/java/org/lwjgl/openal/ALC10.java b/src/java/org/lwjgl/openal/ALC10.java
index 5ad66bd..f88bdf2 100644
--- a/src/java/org/lwjgl/openal/ALC10.java
+++ b/src/java/org/lwjgl/openal/ALC10.java
@@ -31,12 +31,13 @@
*/
package org.lwjgl.openal;
-import java.nio.Buffer;
+import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import org.lwjgl.BufferChecks;
import org.lwjgl.LWJGLException;
+import org.lwjgl.MemoryUtil;
/**
*
@@ -151,12 +152,11 @@
* @return String property from device
*/
public static String alcGetString(ALCdevice device, int pname) {
- String result;
- result = nalcGetString(getDevice(device), pname);
+ ByteBuffer buffer = nalcGetString(getDevice(device), pname);
Util.checkALCError(device);
- return result;
- }
- static native String nalcGetString(long device, int pname);
+ return MemoryUtil.decodeUTF8(buffer);
+ }
+ static native ByteBuffer nalcGetString(long device, int pname);
/**
* The application can query ALC for information using an integer query function.
@@ -180,10 +180,10 @@
*/
public static void alcGetInteger(ALCdevice device, int pname, IntBuffer integerdata) {
BufferChecks.checkDirect(integerdata);
- nalcGetIntegerv(getDevice(device), pname, integerdata.remaining(), integerdata, integerdata.position());
+ nalcGetIntegerv(getDevice(device), pname, integerdata.remaining(), MemoryUtil.getAddress(integerdata));
Util.checkALCError(device);
}
- static native void nalcGetIntegerv(long device, int pname, int size, Buffer integerdata, int offset);
+ static native void nalcGetIntegerv(long device, int pname, int size, long integerdata);
/**
* The alcOpenDevice
function allows the application (i.e. the client program) to
@@ -198,7 +198,8 @@
* @return opened device, or null
*/
public static ALCdevice alcOpenDevice(String devicename) {
- long device_address = nalcOpenDevice(devicename);
+ ByteBuffer buffer = MemoryUtil.encodeUTF8(devicename);
+ long device_address = nalcOpenDevice(MemoryUtil.getAddressSafe(buffer));
if(device_address != 0) {
ALCdevice device = new ALCdevice(device_address);
synchronized (ALC10.devices) {
@@ -208,7 +209,7 @@
}
return null;
}
- static native long nalcOpenDevice(String devicename);
+ static native long nalcOpenDevice(long devicename);
/**
* The alcCloseDevice
function allows the application (i.e. the client program) to
@@ -246,7 +247,7 @@
* @return New context, or null if creation failed
*/
public static ALCcontext alcCreateContext(ALCdevice device, IntBuffer attrList) {
- long context_address = nalcCreateContext(getDevice(device), attrList);
+ long context_address = nalcCreateContext(getDevice(device), MemoryUtil.getAddressSafe(attrList));
Util.checkALCError(device);
if(context_address != 0) {
@@ -259,7 +260,7 @@
}
return null;
}
- static native long nalcCreateContext(long device, IntBuffer attrList);
+ static native long nalcCreateContext(long device, long attrList);
/**
* To make a Context current with respect to AL Operation (state changes by issueing
@@ -394,11 +395,12 @@
* @return true if extension is available, false if not
*/
public static boolean alcIsExtensionPresent(ALCdevice device, String extName) {
- boolean result = nalcIsExtensionPresent(getDevice(device), extName);
+ ByteBuffer buffer = MemoryUtil.encodeASCII(extName);
+ boolean result = nalcIsExtensionPresent(getDevice(device), MemoryUtil.getAddress(buffer));
Util.checkALCError(device);
return result;
}
- static native boolean nalcIsExtensionPresent(long device, String extName);
+ private static native boolean nalcIsExtensionPresent(long device, long extName);
/**
* Enumeration/token values are device independend, but tokens defined for
@@ -411,11 +413,12 @@
* @return value of enumeration
*/
public static int alcGetEnumValue(ALCdevice device, String enumName) {
- int result = nalcGetEnumValue(getDevice(device), enumName);
+ ByteBuffer buffer = MemoryUtil.encodeASCII(enumName);
+ int result = nalcGetEnumValue(getDevice(device), MemoryUtil.getAddress(buffer));
Util.checkALCError(device);
return result;
}
- static native int nalcGetEnumValue(long device, String enumName);
+ private static native int nalcGetEnumValue(long device, long enumName);
static long getDevice(ALCdevice device) {
if(device != null) {
diff --git a/src/java/org/lwjgl/openal/ALC11.java b/src/java/org/lwjgl/openal/ALC11.java
index a1708cd..13374a5 100644
--- a/src/java/org/lwjgl/openal/ALC11.java
+++ b/src/java/org/lwjgl/openal/ALC11.java
@@ -37,7 +37,7 @@
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
-
+import org.lwjgl.MemoryUtil;
/**
*
@@ -92,7 +92,8 @@
* @return ALCdevice if it was possible to open a device
*/
public static ALCdevice alcCaptureOpenDevice(String devicename, int frequency, int format, int buffersize) {
- long device_address = nalcCaptureOpenDevice(devicename, frequency, format, buffersize);
+ ByteBuffer buffer = MemoryUtil.encodeASCII(devicename);
+ long device_address = nalcCaptureOpenDevice(MemoryUtil.getAddressSafe(buffer), frequency, format, buffersize);
if(device_address != 0) {
ALCdevice device = new ALCdevice(device_address);
synchronized (ALC10.devices) {
@@ -102,7 +103,7 @@
}
return null;
}
- static native long nalcCaptureOpenDevice( String devicename, int frequency, int format, int buffersize);
+ private static native long nalcCaptureOpenDevice(long devicename, int frequency, int format, int buffersize);
/**
* The alcCaptureCloseDevice function allows the application to disconnect from a capture
@@ -162,9 +163,9 @@
* @param samples Number of samples to request
*/
public static void alcCaptureSamples(ALCdevice device, ByteBuffer buffer, int samples ) {
- nalcCaptureSamples(ALC10.getDevice(device), buffer, buffer.position(), samples);
- }
- static native void nalcCaptureSamples(long device, ByteBuffer buffer, int position, int samples );
+ nalcCaptureSamples(ALC10.getDevice(device), MemoryUtil.getAddress(buffer), samples);
+ }
+ static native void nalcCaptureSamples(long device, long buffer, int samples );
static native void initNativeStubs() throws LWJGLException;
diff --git a/src/java/org/lwjgl/openal/ALCcontext.java b/src/java/org/lwjgl/openal/ALCcontext.java
index 2dabd18..f317420 100644
--- a/src/java/org/lwjgl/openal/ALCcontext.java
+++ b/src/java/org/lwjgl/openal/ALCcontext.java
@@ -46,8 +46,8 @@
* AL and ALC are threadsafe.
*
* @author Brian Matzon
- * @version $Revision: 3418 $
- * $Id: ALCcontext.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
public final class ALCcontext {
@@ -82,7 +82,7 @@
* @param contextFrequency Frequency to add
* @param contextRefresh Refresh rate to add
* @param contextSynchronized Whether to synchronize the context
- * @return
+ * @return attribute list
*/
static IntBuffer createAttributeList(int contextFrequency, int contextRefresh, int contextSynchronized) {
IntBuffer attribList = BufferUtils.createIntBuffer(7);
diff --git a/src/java/org/lwjgl/openal/ALCdevice.java b/src/java/org/lwjgl/openal/ALCdevice.java
index 3329770..73bc98f 100644
--- a/src/java/org/lwjgl/openal/ALCdevice.java
+++ b/src/java/org/lwjgl/openal/ALCdevice.java
@@ -45,8 +45,8 @@
* which has to map the available backends to unique device specifiers.
*
* @author Brian Matzon
- * @version $Revision: 3418 $
- * $Id: ALCdevice.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
public final class ALCdevice {
diff --git a/src/java/org/lwjgl/openal/OpenALException.java b/src/java/org/lwjgl/openal/OpenALException.java
index 830ed49..59b88e7 100644
--- a/src/java/org/lwjgl/openal/OpenALException.java
+++ b/src/java/org/lwjgl/openal/OpenALException.java
@@ -37,8 +37,8 @@
* causes an error.
*
* @author Brian Matzon
- * @version $Revision: 2983 $
- * $Id: OpenALException.java 2983 2008-04-07 18:36:09Z matzon $
+ * @version $Revision$
+ * $Id$
*/
public class OpenALException extends RuntimeException {
diff --git a/src/java/org/lwjgl/openal/Util.java b/src/java/org/lwjgl/openal/Util.java
index 43b9b0d..310b7fd 100644
--- a/src/java/org/lwjgl/openal/Util.java
+++ b/src/java/org/lwjgl/openal/Util.java
@@ -37,7 +37,7 @@
*
* @author cix_foo
* @author Brian Matzon
- * @version $Revision: 2983 $
+ * @version $Revision$
*/
public final class Util {
diff --git a/src/java/org/lwjgl/opencl/APIUtil.java b/src/java/org/lwjgl/opencl/APIUtil.java
index c40010a..3c19c30 100644
--- a/src/java/org/lwjgl/opencl/APIUtil.java
+++ b/src/java/org/lwjgl/opencl/APIUtil.java
@@ -31,9 +31,7 @@
*/
package org.lwjgl.opencl;
-import org.lwjgl.BufferUtils;
-import org.lwjgl.LWJGLUtil;
-import org.lwjgl.PointerBuffer;
+import org.lwjgl.*;
import org.lwjgl.opencl.FastLongMap.Entry;
import java.nio.*;
@@ -53,7 +51,7 @@
*/
final class APIUtil {
- private static final int INITIAL_BUFFER_SIZE = 256;
+ private static final int INITIAL_BUFFER_SIZE = 256;
private static final int INITIAL_LENGTHS_SIZE = 4;
private static final int BUFFERS_SIZE = 32;
@@ -223,10 +221,10 @@
*
* @return the String as a ByteBuffer
*/
- static ByteBuffer getBuffer(final CharSequence string) {
+ static long getBuffer(final CharSequence string) {
final ByteBuffer buffer = encode(getBufferByte(string.length()), string);
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress0(buffer);
}
/**
@@ -236,10 +234,10 @@
*
* @return the String as a ByteBuffer
*/
- static ByteBuffer getBuffer(final CharSequence string, final int offset) {
+ static long getBuffer(final CharSequence string, final int offset) {
final ByteBuffer buffer = encode(getBufferByteOffset(offset + string.length()), string);
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress(buffer);
}
/**
@@ -249,11 +247,11 @@
*
* @return the String as a ByteBuffer
*/
- static ByteBuffer getBufferNT(final CharSequence string) {
+ static long getBufferNT(final CharSequence string) {
final ByteBuffer buffer = encode(getBufferByte(string.length() + 1), string);
buffer.put((byte)0);
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress0(buffer);
}
static int getTotalLength(final CharSequence[] strings) {
@@ -271,14 +269,14 @@
*
* @return the Strings as a ByteBuffer
*/
- static ByteBuffer getBuffer(final CharSequence[] strings) {
+ static long getBuffer(final CharSequence[] strings) {
final ByteBuffer buffer = getBufferByte(getTotalLength(strings));
for ( CharSequence string : strings )
encode(buffer, string);
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress0(buffer);
}
/**
@@ -288,7 +286,7 @@
*
* @return the Strings as a ByteBuffer
*/
- static ByteBuffer getBufferNT(final CharSequence[] strings) {
+ static long getBufferNT(final CharSequence[] strings) {
final ByteBuffer buffer = getBufferByte(getTotalLength(strings) + strings.length);
for ( CharSequence string : strings ) {
@@ -297,7 +295,7 @@
}
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress0(buffer);
}
/**
@@ -307,14 +305,14 @@
*
* @return the String lengths in a PointerBuffer
*/
- static PointerBuffer getLengths(final CharSequence[] strings) {
+ static long getLengths(final CharSequence[] strings) {
PointerBuffer buffer = getLengths(strings.length);
for ( CharSequence string : strings )
buffer.put(string.length());
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress0(buffer);
}
/**
@@ -324,14 +322,14 @@
*
* @return the buffer lengths in a PointerBuffer
*/
- static PointerBuffer getLengths(final ByteBuffer[] buffers) {
+ static long getLengths(final ByteBuffer[] buffers) {
PointerBuffer lengths = getLengths(buffers.length);
for ( ByteBuffer buffer : buffers )
lengths.put(buffer.remaining());
lengths.flip();
- return lengths;
+ return MemoryUtil.getAddress0(lengths);
}
static int getSize(final PointerBuffer lengths) {
@@ -342,14 +340,22 @@
return (int)size;
}
+ static long getPointer(final PointerWrapper pointer) {
+ return MemoryUtil.getAddress0(getBufferPointer().put(0, pointer));
+ }
+
+ static long getPointerSafe(final PointerWrapper pointer) {
+ return MemoryUtil.getAddress0(getBufferPointer().put(0, pointer == null ? 0L : pointer.getPointer()));
+ }
+
private static class Buffers {
final ShortBuffer shorts;
- final IntBuffer ints;
- final IntBuffer intsDebug;
- final LongBuffer longs;
-
- final FloatBuffer floats;
+ final IntBuffer ints;
+ final IntBuffer intsDebug;
+ final LongBuffer longs;
+
+ final FloatBuffer floats;
final DoubleBuffer doubles;
final PointerBuffer pointers;
@@ -453,7 +459,7 @@
*/
static void releaseObjects(final CLDevice device) {
// Release objects only if we're about to hit 0.
- if ( device.getReferenceCount() > 1 )
+ if ( !device.isValid() || device.getReferenceCount() > 1 )
return;
releaseObjects(device.getSubCLDeviceRegistry(), DESTRUCTOR_CLSubDevice);
@@ -466,7 +472,7 @@
*/
static void releaseObjects(final CLContext context) {
// Release objects only if we're about to hit 0.
- if ( context.getReferenceCount() > 1 )
+ if ( !context.isValid() || context.getReferenceCount() > 1 )
return;
releaseObjects(context.getCLEventRegistry(), DESTRUCTOR_CLEvent);
@@ -483,7 +489,7 @@
*/
static void releaseObjects(final CLProgram program) {
// Release objects only if we're about to hit 0.
- if ( program.getReferenceCount() > 1 )
+ if ( !program.isValid() || program.getReferenceCount() > 1 )
return;
releaseObjects(program.getCLKernelRegistry(), DESTRUCTOR_CLKernel);
@@ -496,7 +502,7 @@
*/
static void releaseObjects(final CLCommandQueue queue) {
// Release objects only if we're about to hit 0.
- if ( queue.getReferenceCount() > 1 )
+ if ( !queue.isValid() || queue.getReferenceCount() > 1 )
return;
releaseObjects(queue.getCLEventRegistry(), DESTRUCTOR_CLEvent);
@@ -513,25 +519,25 @@
}
}
- private static final ObjectDestructor DESTRUCTOR_CLSubDevice = new ObjectDestructor() {
+ private static final ObjectDestructor DESTRUCTOR_CLSubDevice = new ObjectDestructor() {
public void release(final CLDevice object) { clReleaseDeviceEXT(object); }
};
- private static final ObjectDestructor DESTRUCTOR_CLMem = new ObjectDestructor() {
+ private static final ObjectDestructor DESTRUCTOR_CLMem = new ObjectDestructor() {
public void release(final CLMem object) { clReleaseMemObject(object); }
};
private static final ObjectDestructor DESTRUCTOR_CLCommandQueue = new ObjectDestructor() {
public void release(final CLCommandQueue object) { clReleaseCommandQueue(object); }
};
- private static final ObjectDestructor DESTRUCTOR_CLSampler = new ObjectDestructor() {
+ private static final ObjectDestructor DESTRUCTOR_CLSampler = new ObjectDestructor() {
public void release(final CLSampler object) { clReleaseSampler(object); }
};
- private static final ObjectDestructor DESTRUCTOR_CLProgram = new ObjectDestructor() {
+ private static final ObjectDestructor DESTRUCTOR_CLProgram = new ObjectDestructor() {
public void release(final CLProgram object) { clReleaseProgram(object); }
};
- private static final ObjectDestructor DESTRUCTOR_CLKernel = new ObjectDestructor() {
+ private static final ObjectDestructor DESTRUCTOR_CLKernel = new ObjectDestructor() {
public void release(final CLKernel object) { clReleaseKernel(object); }
};
- private static final ObjectDestructor DESTRUCTOR_CLEvent = new ObjectDestructor() {
+ private static final ObjectDestructor DESTRUCTOR_CLEvent = new ObjectDestructor() {
public void release(final CLEvent object) { clReleaseEvent(object); }
};
diff --git a/src/java/org/lwjgl/opencl/CL.java b/src/java/org/lwjgl/opencl/CL.java
index 794da74..0876a3d 100644
--- a/src/java/org/lwjgl/opencl/CL.java
+++ b/src/java/org/lwjgl/opencl/CL.java
@@ -33,6 +33,7 @@
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
+import org.lwjgl.MemoryUtil;
import org.lwjgl.Sys;
import java.nio.ByteBuffer;
@@ -143,7 +144,12 @@
return 0;
}
- static native long getFunctionAddress(String name);
+ /** Helper method to get a pointer to a named function in the OpenCL library. */
+ static long getFunctionAddress(String name) {
+ ByteBuffer buffer = MemoryUtil.encodeASCII(name);
+ return ngetFunctionAddress(MemoryUtil.getAddress(buffer));
+ }
+ private static native long ngetFunctionAddress(long name);
static native ByteBuffer getHostBuffer(final long address, final int size);
diff --git a/src/java/org/lwjgl/opencl/CLBuildProgramCallback.java b/src/java/org/lwjgl/opencl/CLBuildProgramCallback.java
index 4056357..aef9129 100644
--- a/src/java/org/lwjgl/opencl/CLBuildProgramCallback.java
+++ b/src/java/org/lwjgl/opencl/CLBuildProgramCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2010 LWJGL Project
+ * Copyright (c) 2002-2011 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,29 +33,11 @@
/**
* Instances of this class can be used to receive OpenCL program build notifications.
+ * A single CLBuildProgramCallback instance should only be used with programs created
+ * in the same CLContext.
*
* @author Spasi
*/
-public abstract class CLBuildProgramCallback extends CLCallback {
-
- protected CLBuildProgramCallback() {
- super(CallbackUtil.getBuildProgramCallback());
- }
-
- /**
- * Called from native code.
- *
- * @param program_address the CLProgram object pointer
- */
- private void handleMessage(long program_address) {
- handleMessage(CLContext.getCLProgramGlobal(program_address));
- }
-
- /**
- * The callback method.
- *
- * @param program the CLProgram object that was built
- */
- protected abstract void handleMessage(CLProgram program);
+public abstract class CLBuildProgramCallback extends CLProgramCallback {
}diff --git a/src/java/org/lwjgl/opencl/CLCallback.java b/src/java/org/lwjgl/opencl/CLCallback.java
deleted file mode 100644
index 48aa024..0000000
--- a/src/java/org/lwjgl/opencl/CLCallback.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2002-2010 LWJGL Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.lwjgl.opencl;
-
-import org.lwjgl.PointerWrapperAbstract;
-
-/**
- * Base class for OpenCL callback objects.
- *
- * @author Spasi
- */
-abstract class CLCallback extends PointerWrapperAbstract {
-
- private final boolean custom;
-
- protected CLCallback(final long pointer) {
- this(pointer, false);
- }
-
- protected CLCallback(final long pointer, final boolean custom) {
- super(pointer);
-
- this.custom = custom;
- }
-
- final boolean isCustom() {
- return custom;
- }
-
-}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opencl/CLChecks.java b/src/java/org/lwjgl/opencl/CLChecks.java
index bb60836..090ad43 100644
--- a/src/java/org/lwjgl/opencl/CLChecks.java
+++ b/src/java/org/lwjgl/opencl/CLChecks.java
@@ -53,23 +53,23 @@
/**
* Calculates the number of bytes in the specified cl_mem buffer rectangle region.
*
- * @param origin the host origin
+ * @param offset the host offset
* @param region the rectangle region
* @param row_pitch the host row pitch
* @param slice_pitch the host slice pitch
*
* @return the region size in bytes
*/
- static int calculateBufferRectSize(final PointerBuffer origin, final PointerBuffer region, long row_pitch, long slice_pitch) {
- if ( !LWJGLUtil.CHECKS )
- return 0;
-
- final long x = origin.get(0);
- final long y = origin.get(1);
- final long z = origin.get(2);
+ static int calculateBufferRectSize(final PointerBuffer offset, final PointerBuffer region, long row_pitch, long slice_pitch) {
+ if ( !LWJGLUtil.CHECKS )
+ return 0;
+
+ final long x = offset.get(0);
+ final long y = offset.get(1);
+ final long z = offset.get(2);
if ( LWJGLUtil.DEBUG && (x < 0 || y < 0 || z < 0) )
- throw new IllegalArgumentException("Invalid cl_mem host origin: " + x + ", " + y + ", " + z);
+ throw new IllegalArgumentException("Invalid cl_mem host offset: " + x + ", " + y + ", " + z);
final long w = region.get(0);
final long h = region.get(1);
diff --git a/src/java/org/lwjgl/opencl/CLCommandQueue.java b/src/java/org/lwjgl/opencl/CLCommandQueue.java
index f4e02ed..36e2a08 100644
--- a/src/java/org/lwjgl/opencl/CLCommandQueue.java
+++ b/src/java/org/lwjgl/opencl/CLCommandQueue.java
@@ -50,7 +50,7 @@
super(pointer, context);
if ( isValid() ) {
this.device = device;
- this.clEvents = new CLObjectRegistryGlobal(CLContext.clEventsGlobal);
+ this.clEvents = new CLObjectRegistry();
context.getCLCommandQueueRegistry().registerObject(this);
} else {
this.device = null;
diff --git a/src/java/org/lwjgl/opencl/CLCompileProgramCallback.java b/src/java/org/lwjgl/opencl/CLCompileProgramCallback.java
new file mode 100644
index 0000000..8b0c493
--- /dev/null
+++ b/src/java/org/lwjgl/opencl/CLCompileProgramCallback.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opencl;
+
+/**
+ * Instances of this class can be used to receive OpenCL program compilation notifications.
+ * A single CLCompileProgramCallback instance should only be used with programs created
+ * in the same CLContext.
+ *
+ * @author Spasi
+ */
+public abstract class CLCompileProgramCallback extends CLProgramCallback {
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opencl/CLContext.java b/src/java/org/lwjgl/opencl/CLContext.java
index 346a23c..f2828b3 100644
--- a/src/java/org/lwjgl/opencl/CLContext.java
+++ b/src/java/org/lwjgl/opencl/CLContext.java
@@ -49,16 +49,14 @@
private static final CLContextUtil util = (CLContextUtil)CLPlatform.getInfoUtilInstance(CLContext.class, "CL_CONTEXT_UTIL");
private final CLObjectRegistry clCommandQueues;
- private final CLObjectRegistry clMems;
- private final CLObjectRegistry clSamplers;
- private final CLObjectRegistry clPrograms;
- private final CLObjectRegistry clEvents;
-
- /** Global registry for build callbacks. */
- static final FastLongMap clProgramsGlobal = new FastLongMap();
-
- /** Global registry for event callbacks. */
- static final FastLongMap clEventsGlobal = new FastLongMap();
+ private final CLObjectRegistry clMems;
+ private final CLObjectRegistry clSamplers;
+ private final CLObjectRegistry clPrograms;
+ private final CLObjectRegistry clEvents;
+
+ private long
+ contextCallback,
+ printfCallback;
CLContext(final long pointer, final CLPlatform platform) {
super(pointer, platform);
@@ -70,8 +68,8 @@
clCommandQueues = new CLObjectRegistry();
clMems = new CLObjectRegistry();
clSamplers = new CLObjectRegistry();
- clPrograms = new CLObjectRegistryGlobal(clProgramsGlobal);
- clEvents = new CLObjectRegistryGlobal(clEventsGlobal);
+ clPrograms = new CLObjectRegistry();
+ clEvents = new CLObjectRegistry();
} else {
clCommandQueues = null;
clMems = null;
@@ -275,8 +273,50 @@
CLObjectRegistry getCLEventRegistry() { return clEvents; }
- static CLProgram getCLProgramGlobal(final long id) { return clProgramsGlobal.get(id); }
-
- static CLEvent getCLEventGlobal(final long id) { return clEventsGlobal.get(id); }
+ private boolean checkCallback(final long callback, final int result) {
+ if ( result == 0 && (callback == 0 || isValid()) )
+ return true;
+
+ if ( callback != 0 )
+ CallbackUtil.deleteGlobalRef(callback);
+ return false;
+ }
+
+ /**
+ * Associates this context with the specified context callback reference. If the context
+ * is invalid, the callback reference is deleted. NO-OP if user_data is 0.
+ *
+ * @param callback the context callback pointer
+ */
+ void setContextCallback(final long callback) {
+ if ( checkCallback(callback, 0) )
+ this.contextCallback = callback;
+ }
+
+ /**
+ * Associates this context with the specified printf callback reference. If the context
+ * is invalid, the callback reference is deleted. NO-OP if user_data is 0.
+ *
+ * @param callback the printf callback pointer
+ */
+ void setPrintfCallback(final long callback, final int result) {
+ if ( checkCallback(callback, result) )
+ this.printfCallback = callback;
+ }
+
+ /**
+ * Decrements the context's reference count. If the reference
+ * count hits zero, it also deletes
+ * any callback objects associated with it.
+ */
+ void releaseImpl() {
+ if ( release() > 0 )
+ return;
+
+ if ( contextCallback != 0 )
+ CallbackUtil.deleteGlobalRef(contextCallback);
+ if ( printfCallback != 0 )
+ CallbackUtil.deleteGlobalRef(printfCallback);
+ }
}diff --git a/src/java/org/lwjgl/opencl/CLEvent.java b/src/java/org/lwjgl/opencl/CLEvent.java
index 9e98acd..f8f4a19 100644
--- a/src/java/org/lwjgl/opencl/CLEvent.java
+++ b/src/java/org/lwjgl/opencl/CLEvent.java
@@ -108,6 +108,13 @@
// -------[ IMPLEMENTATION STUFF BELOW ]-------
+ CLObjectRegistry getParentRegistry() {
+ if ( queue == null )
+ return getParent().getCLEventRegistry();
+ else
+ return queue.getCLEventRegistry();
+ }
+
int release() {
try {
return super.release();
diff --git a/src/java/org/lwjgl/opencl/CLEventCallback.java b/src/java/org/lwjgl/opencl/CLEventCallback.java
index 43bb665..30b8013 100644
--- a/src/java/org/lwjgl/opencl/CLEventCallback.java
+++ b/src/java/org/lwjgl/opencl/CLEventCallback.java
@@ -31,15 +31,30 @@
*/
package org.lwjgl.opencl;
+import org.lwjgl.PointerWrapperAbstract;
+
/**
- * Instances of this class can be used to receive OpenCL memory object destruction notifications.
+ * Instances of this class can be used to handle OpenCL event callbacks. A single
+ * CLEventCallback instance should only be used on events generated from the same
+ * CLCommandQueue or on user events associated with the same CLContext.
*
* @author Spasi
*/
-public abstract class CLEventCallback extends CLCallback {
+public abstract class CLEventCallback extends PointerWrapperAbstract {
+
+ private CLObjectRegistry eventRegistry;
protected CLEventCallback() {
super(CallbackUtil.getEventCallback());
+ }
+
+ /**
+ * Sets the eventRegistry that contains the CLEvents to which we're registered.
+ *
+ * @param eventRegistry the CLEvent object registry
+ */
+ void setRegistry(final CLObjectRegistry eventRegistry) {
+ this.eventRegistry = eventRegistry;
}
/**
@@ -48,13 +63,14 @@
* @param event_address the CLEvent object pointer
*/
private void handleMessage(long event_address, int event_command_exec_status) {
- handleMessage(CLContext.getCLEventGlobal(event_address), event_command_exec_status);
+ handleMessage(eventRegistry.getObject(event_address), event_command_exec_status);
}
/**
* The callback method.
*
- * @param event the CLEvent object
+ * @param event the CLEvent object
+ * @param event_command_exec_status the execution status
*/
protected abstract void handleMessage(CLEvent event, int event_command_exec_status);
diff --git a/src/java/org/lwjgl/opencl/CLLinkProgramCallback.java b/src/java/org/lwjgl/opencl/CLLinkProgramCallback.java
new file mode 100644
index 0000000..d0e4f94
--- /dev/null
+++ b/src/java/org/lwjgl/opencl/CLLinkProgramCallback.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opencl;
+
+/**
+ * Instances of this class can be used to receive OpenCL program linkage notifications.
+ * A single CLLinkProgramCallback instance should only be used with programs created
+ * in the same CLContext.
+ *
+ * @author Spasi
+ */
+public abstract class CLLinkProgramCallback extends CLProgramCallback {
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opencl/CLMemObjectDestructorCallback.java b/src/java/org/lwjgl/opencl/CLMemObjectDestructorCallback.java
index 9e84fd2..ba65a71 100644
--- a/src/java/org/lwjgl/opencl/CLMemObjectDestructorCallback.java
+++ b/src/java/org/lwjgl/opencl/CLMemObjectDestructorCallback.java
@@ -31,12 +31,14 @@
*/
package org.lwjgl.opencl;
+import org.lwjgl.PointerWrapperAbstract;
+
/**
* Instances of this class can be used to receive OpenCL memory object destruction notifications.
*
* @author Spasi
*/
-public abstract class CLMemObjectDestructorCallback extends CLCallback {
+public abstract class CLMemObjectDestructorCallback extends PointerWrapperAbstract {
protected CLMemObjectDestructorCallback() {
super(CallbackUtil.getMemObjectDestructorCallback());
diff --git a/src/java/org/lwjgl/opencl/CLNativeKernel.java b/src/java/org/lwjgl/opencl/CLNativeKernel.java
index f137535..44cae39 100644
--- a/src/java/org/lwjgl/opencl/CLNativeKernel.java
+++ b/src/java/org/lwjgl/opencl/CLNativeKernel.java
@@ -31,6 +31,8 @@
*/
package org.lwjgl.opencl;
+import org.lwjgl.PointerWrapperAbstract;
+
import java.nio.ByteBuffer;
/**
@@ -43,7 +45,7 @@
* @see CL10#clEnqueueNativeKernel
* @see #execute(java.nio.ByteBuffer[])
*/
-public abstract class CLNativeKernel extends CLCallback {
+public abstract class CLNativeKernel extends PointerWrapperAbstract {
protected CLNativeKernel() {
super(CallbackUtil.getNativeKernelCallback());
diff --git a/src/java/org/lwjgl/opencl/CLObjectRegistryGlobal.java b/src/java/org/lwjgl/opencl/CLObjectRegistryGlobal.java
deleted file mode 100644
index 7c77f08..0000000
--- a/src/java/org/lwjgl/opencl/CLObjectRegistryGlobal.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2002-2010 LWJGL Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.lwjgl.opencl;
-
-/**
- * A CLObject registry that also registers/unregisters objects to/from a global registry.
- *
- * @author Spasi
- */
-final class CLObjectRegistryGlobal extends CLObjectRegistry {
-
- private final FastLongMap globalRegistry;
-
- CLObjectRegistryGlobal(final FastLongMap globalRegistry) {
- this.globalRegistry = globalRegistry;
- }
-
- void registerObject(final T object) {
- super.registerObject(object);
- globalRegistry.put(object.getPointer(), object);
- }
-
- void unregisterObject(final T object) {
- super.unregisterObject(object);
- globalRegistry.remove(object.getPointerUnsafe());
- }
-
-}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opencl/CLPlatform.java b/src/java/org/lwjgl/opencl/CLPlatform.java
index ea04a07..bf39941 100644
--- a/src/java/org/lwjgl/opencl/CLPlatform.java
+++ b/src/java/org/lwjgl/opencl/CLPlatform.java
@@ -53,9 +53,6 @@
private final CLObjectRegistry clDevices;
- /** Global registry for build callbacks. */
- static final FastLongMap clDevicesGlobal = new FastLongMap();
-
private Object caps;
CLPlatform(final long pointer) {
@@ -63,7 +60,7 @@
if ( isValid() ) {
clPlatforms.put(pointer, this);
- clDevices = new CLObjectRegistryGlobal(clDevicesGlobal);
+ clDevices = new CLObjectRegistry();
} else
clDevices = null;
}
@@ -195,8 +192,6 @@
CLObjectRegistry getCLDeviceRegistry() { return clDevices; }
- static CLDevice getCLDeviceGlobal(final long id) { return clDevicesGlobal.get(id); }
-
/**
* Called from clGetDeviceIDs
to register new devices.
*
diff --git a/src/java/org/lwjgl/opencl/CLPrintfCallback.java b/src/java/org/lwjgl/opencl/CLPrintfCallback.java
new file mode 100644
index 0000000..00dab6e
--- /dev/null
+++ b/src/java/org/lwjgl/opencl/CLPrintfCallback.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opencl;
+
+import org.lwjgl.PointerWrapperAbstract;
+
+/**
+ * Instances of this class can be used to receive OpenCL printf messages.
+ * Different CLContexts should use different CLPrintfCallback instances.
+ *
+ * @author Spasi
+ */
+public abstract class CLPrintfCallback extends PointerWrapperAbstract {
+
+ protected CLPrintfCallback() {
+ super(CallbackUtil.getPrintfCallback());
+ }
+
+ /** The callback method. */
+ protected abstract void handleMessage(String data);
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opencl/CLProgramCallback.java b/src/java/org/lwjgl/opencl/CLProgramCallback.java
new file mode 100644
index 0000000..5071916
--- /dev/null
+++ b/src/java/org/lwjgl/opencl/CLProgramCallback.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opencl;
+
+import org.lwjgl.PointerWrapperAbstract;
+
+/**
+ * Base class for OpenCL program action notifications.
+ *
+ * @author Spasi
+ */
+abstract class CLProgramCallback extends PointerWrapperAbstract {
+
+ private CLContext context;
+
+ protected CLProgramCallback() {
+ super(CallbackUtil.getProgramCallback());
+ }
+
+ /**
+ * Sets the context that contains the CLPrograms to which we're registered.
+ *
+ * @param context the CLContext object
+ */
+ final void setContext(final CLContext context) {
+ this.context = context;
+ }
+
+ /**
+ * Called from native code.
+ *
+ * @param program_address the CLProgram object pointer
+ */
+ private void handleMessage(long program_address) {
+ handleMessage(context.getCLProgram(program_address));
+ }
+
+ /**
+ * The callback method.
+ *
+ * @param program the CLProgram object affected
+ */
+ protected abstract void handleMessage(CLProgram program);
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opencl/CallbackUtil.java b/src/java/org/lwjgl/opencl/CallbackUtil.java
index 531e9bd..d70164a 100644
--- a/src/java/org/lwjgl/opencl/CallbackUtil.java
+++ b/src/java/org/lwjgl/opencl/CallbackUtil.java
@@ -70,7 +70,7 @@
*
* @param ref the GlobalRef memory address.
*/
- private static native void deleteGlobalRef(long ref);
+ static native void deleteGlobalRef(long ref);
/**
* Deletes the global reference represented by user_data if an OpenCL error occured.
@@ -99,41 +99,6 @@
*/
static native long getContextCallback();
- /**
- * Associates the specified CLContext with the specified global reference. If the context
- * is invalid, the global reference is deleted. NO-OP if user_data is 0.
- *
- * @param context the CLContext to register
- * @param user_data the global reference pointer
- */
- static void registerCallback(final CLContext context, final long user_data) {
- if ( context.getPointerUnsafe() == 0 ) {
- if ( user_data != 0 )
- deleteGlobalRef(user_data);
- return;
- }
-
- if ( user_data != 0 )
- contextUserData.put(context, user_data);
- }
-
- /**
- * Decrements the specified context's reference count, clears its association
- * with a CLContextCallback object if it exists and deletes the corresponding
- * global reference.
- *
- * @param context the CLContext to unregister
- */
- static void unregisterCallback(final CLContext context) {
- if ( context.release() > 0 )
- return;
-
- final Long user_data = contextUserData.remove(context);
-
- if ( user_data != null )
- deleteGlobalRef(user_data);
- }
-
/* [ Other callback functionality ]
The other callbacks are simpler. We create the GlobalRef before passing the callback,
we delete it when we receive the callback call.
@@ -151,7 +116,7 @@
*
* @return the callback function address
*/
- static native long getBuildProgramCallback();
+ static native long getProgramCallback();
/**
* Returns the memory address of the native function we pass to clEnqueueNativeKernel.
@@ -166,6 +131,13 @@
* @return the callback function address
*/
static native long getEventCallback();
+
+ /**
+ * Returns the memory address of the native function we pass to clSetPrintfCallback.
+ *
+ * @return the callback function address
+ */
+ static native long getPrintfCallback();
/**
* Returns the memory address of the native function we pass to clCreateContext(FromType),
diff --git a/src/java/org/lwjgl/opencl/InfoUtilFactory.java b/src/java/org/lwjgl/opencl/InfoUtilFactory.java
index c633ae7..b44fc9e 100644
--- a/src/java/org/lwjgl/opencl/InfoUtilFactory.java
+++ b/src/java/org/lwjgl/opencl/InfoUtilFactory.java
@@ -118,12 +118,12 @@
final long user_data = pfn_notify == null || pfn_notify.isCustom() ? 0 : CallbackUtil.createGlobalRef(pfn_notify);
CLContext __result = null;
try {
- __result = new CLContext(nclCreateContext(properties.getBuffer(), 0, devices.size(), properties.getBuffer(), propertyCount * PointerBuffer.getPointerSize(), pfn_notify == null ? 0 : pfn_notify.getPointer(), user_data, errcode_ret, errcode_ret != null ? errcode_ret.position() : 0, function_pointer), platform);
+ __result = new CLContext(nclCreateContext(MemoryUtil.getAddress0(properties.getBuffer()), devices.size(), MemoryUtil.getAddress(properties, propertyCount), pfn_notify == null ? 0 : pfn_notify.getPointer(), user_data, MemoryUtil.getAddressSafe(errcode_ret), function_pointer), platform);
if ( LWJGLUtil.DEBUG )
Util.checkCLError(errcode_ret.get(0));
return __result;
} finally {
- CallbackUtil.registerCallback(__result, user_data);
+ if ( __result != null ) __result.setContextCallback(user_data);
}
}
@@ -256,7 +256,7 @@
final int size;
switch ( param_name ) {
- case CL_KERNEL_WORK_GROUP_SIZE:
+ case CL_KERNEL_COMPILE_WORK_GROUP_SIZE:
size = 3;
break;
default:
@@ -304,9 +304,9 @@
else if ( LWJGLUtil.DEBUG )
errcode_ret = APIUtil.getBufferInt();
- CLMem __result = new CLMem(nclCreateImage2D(context.getPointer(), flags, formatBuffer, 0, image_width, image_height, image_row_pitch, host_ptr,
- host_ptr != null ? BufferChecks.checkBuffer(host_ptr, CLChecks.calculateImage2DSize(formatBuffer, image_width, image_height, image_row_pitch)) : 0,
- errcode_ret, errcode_ret != null ? errcode_ret.position() : 0, function_pointer), context);
+ CLMem __result = new CLMem(nclCreateImage2D(context.getPointer(), flags, MemoryUtil.getAddress(formatBuffer, 0), image_width, image_height, image_row_pitch, MemoryUtil.getAddress0Safe(host_ptr) +
+ (host_ptr != null ? BufferChecks.checkBuffer(host_ptr, CLChecks.calculateImage2DSize(formatBuffer, image_width, image_height, image_row_pitch)) : 0),
+ MemoryUtil.getAddressSafe(errcode_ret), function_pointer), context);
if ( LWJGLUtil.DEBUG )
Util.checkCLError(errcode_ret.get(0));
return __result;
@@ -324,9 +324,9 @@
else if ( LWJGLUtil.DEBUG )
errcode_ret = APIUtil.getBufferInt();
- CLMem __result = new CLMem(nclCreateImage3D(context.getPointer(), flags, formatBuffer, 0, image_width, image_height, image_depth, image_row_pitch, image_slice_pitch, host_ptr,
- host_ptr != null ? BufferChecks.checkBuffer(host_ptr, CLChecks.calculateImage3DSize(formatBuffer, image_width, image_height, image_depth, image_row_pitch, image_slice_pitch)) : 0,
- errcode_ret, errcode_ret != null ? errcode_ret.position() : 0, function_pointer), context);
+ CLMem __result = new CLMem(nclCreateImage3D(context.getPointer(), flags, MemoryUtil.getAddress(formatBuffer, 0), image_width, image_height, image_depth, image_row_pitch, image_slice_pitch, MemoryUtil.getAddress0Safe(host_ptr) +
+ (host_ptr != null ? BufferChecks.checkBuffer(host_ptr, CLChecks.calculateImage3DSize(formatBuffer, image_width, image_height, image_depth, image_row_pitch, image_slice_pitch)) : 0),
+ MemoryUtil.getAddressSafe(errcode_ret), function_pointer), context);
if ( LWJGLUtil.DEBUG )
Util.checkCLError(errcode_ret.get(0));
return __result;
@@ -547,7 +547,7 @@
target = new ByteBuffer[sizes.remaining()];
for ( int i = 0; i < sizes.remaining(); i++ )
- target[i] = BufferUtils.createByteBuffer((int)sizes.get(0));
+ target[i] = BufferUtils.createByteBuffer((int)sizes.get(i));
} else if ( LWJGLUtil.DEBUG ) {
final PointerBuffer sizes = getSizesBuffer(program, CL_PROGRAM_BINARY_SIZES);
diff --git a/src/java/org/lwjgl/opengl/AMDDebugOutputCallback.java b/src/java/org/lwjgl/opengl/AMDDebugOutputCallback.java
index 4fcaa65..6cf51fc 100644
--- a/src/java/org/lwjgl/opengl/AMDDebugOutputCallback.java
+++ b/src/java/org/lwjgl/opengl/AMDDebugOutputCallback.java
@@ -110,7 +110,7 @@
description = "OTHER";
break;
default:
- description = "Unknown (" + Integer.toHexString(category) + ")";
+ description = printUnknownToken(category);
}
System.err.println("\tCategory: " + description);
@@ -125,11 +125,15 @@
description = "LOW";
break;
default:
- description = "Unknown (" + Integer.toHexString(category) + ")";
+ description = printUnknownToken(severity);
}
System.err.println("\tSeverity: " + description);
System.err.println("\tMessage: " + message);
+ }
+
+ private String printUnknownToken(final int token) {
+ return "Unknown (0x" + Integer.toHexString(token).toUpperCase() + ")";
}
});
}
diff --git a/src/java/org/lwjgl/opengl/APIUtil.java b/src/java/org/lwjgl/opengl/APIUtil.java
index 2b0d521..86ef98c 100644
--- a/src/java/org/lwjgl/opengl/APIUtil.java
+++ b/src/java/org/lwjgl/opengl/APIUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2008 LWJGL Project
+ * Copyright (c) 2002-2011 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,38 +33,46 @@
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLUtil;
+import org.lwjgl.MemoryUtil;
import java.nio.*;
-/** @author spasi */
+/**
+ * Utility class for OpenGL API calls. Instances of APIUtil are created in ContextCapabilities,
+ * so we have an instance per OpenGL context.
+ *
+ * @author spasi
+ */
final class APIUtil {
- private static final int INITIAL_BUFFER_SIZE = 256;
+ private static final int INITIAL_BUFFER_SIZE = 256;
private static final int INITIAL_LENGTHS_SIZE = 4;
private static final int BUFFERS_SIZE = 32;
- private static final ThreadLocal arrayTL = new ThreadLocal() {
- protected char[] initialValue() { return new char[INITIAL_BUFFER_SIZE]; }
- };
-
- private static final ThreadLocal bufferTL = new ThreadLocal() {
- protected ByteBuffer initialValue() { return BufferUtils.createByteBuffer(INITIAL_BUFFER_SIZE); }
- };
-
- private static final ThreadLocal lengthsTL = new ThreadLocal() {
- protected IntBuffer initialValue() { return BufferUtils.createIntBuffer(INITIAL_LENGTHS_SIZE); }
- };
-
- private static final ThreadLocal buffersTL = new ThreadLocal() {
- protected Buffers initialValue() { return new Buffers(); }
- };
-
- private APIUtil() {
- }
-
- private static char[] getArray(final int size) {
- char[] array = arrayTL.get();
+ private char[] array;
+ private ByteBuffer buffer;
+ private IntBuffer lengths;
+
+ private final IntBuffer ints;
+ private final LongBuffer longs;
+ private final FloatBuffer floats;
+ private final DoubleBuffer doubles;
+
+ APIUtil() {
+ array = new char[INITIAL_BUFFER_SIZE];
+ buffer = BufferUtils.createByteBuffer(INITIAL_BUFFER_SIZE);
+ lengths = BufferUtils.createIntBuffer(INITIAL_LENGTHS_SIZE);
+
+ ints = BufferUtils.createIntBuffer(BUFFERS_SIZE);
+ longs = BufferUtils.createLongBuffer(BUFFERS_SIZE);
+
+ floats = BufferUtils.createFloatBuffer(BUFFERS_SIZE);
+ doubles = BufferUtils.createDoubleBuffer(BUFFERS_SIZE);
+ }
+
+ private static char[] getArray(final ContextCapabilities caps, final int size) {
+ char[] array = caps.util.array;
if ( array.length < size ) {
int sizeNew = array.length << 1;
@@ -72,14 +80,14 @@
sizeNew <<= 1;
array = new char[size];
- arrayTL.set(array);
+ caps.util.array = array;
}
return array;
}
- static ByteBuffer getBufferByte(final int size) {
- ByteBuffer buffer = bufferTL.get();
+ static ByteBuffer getBufferByte(final ContextCapabilities caps, final int size) {
+ ByteBuffer buffer = caps.util.buffer;
if ( buffer.capacity() < size ) {
int sizeNew = buffer.capacity() << 1;
@@ -87,15 +95,15 @@
sizeNew <<= 1;
buffer = BufferUtils.createByteBuffer(size);
- bufferTL.set(buffer);
+ caps.util.buffer = buffer;
} else
buffer.clear();
return buffer;
}
- private static ByteBuffer getBufferByteOffset(final int size) {
- ByteBuffer buffer = bufferTL.get();
+ private static ByteBuffer getBufferByteOffset(final ContextCapabilities caps, final int size) {
+ ByteBuffer buffer = caps.util.buffer;
if ( buffer.capacity() < size ) {
int sizeNew = buffer.capacity() << 1;
@@ -104,7 +112,7 @@
final ByteBuffer bufferNew = BufferUtils.createByteBuffer(size);
bufferNew.put(buffer);
- bufferTL.set(buffer = bufferNew);
+ caps.util.buffer = (buffer = bufferNew);
} else {
buffer.position(buffer.limit());
buffer.limit(buffer.capacity());
@@ -113,22 +121,20 @@
return buffer;
}
- static ShortBuffer getBufferShort() { return buffersTL.get().shorts; }
-
- static IntBuffer getBufferInt() { return buffersTL.get().ints; }
-
- static LongBuffer getBufferLong() { return buffersTL.get().longs; }
-
- static FloatBuffer getBufferFloat() { return buffersTL.get().floats; }
-
- static DoubleBuffer getBufferDouble() { return buffersTL.get().doubles; }
-
- static IntBuffer getLengths() {
- return getLengths(1);
- }
-
- static IntBuffer getLengths(final int size) {
- IntBuffer lengths = lengthsTL.get();
+ static IntBuffer getBufferInt(final ContextCapabilities caps) { return caps.util.ints; }
+
+ static LongBuffer getBufferLong(final ContextCapabilities caps) { return caps.util.longs; }
+
+ static FloatBuffer getBufferFloat(final ContextCapabilities caps) { return caps.util.floats; }
+
+ static DoubleBuffer getBufferDouble(final ContextCapabilities caps) { return caps.util.doubles; }
+
+ static IntBuffer getLengths(final ContextCapabilities caps) {
+ return getLengths(caps, 1);
+ }
+
+ static IntBuffer getLengths(final ContextCapabilities caps, final int size) {
+ IntBuffer lengths = caps.util.lengths;
if ( lengths.capacity() < size ) {
int sizeNew = lengths.capacity();
@@ -136,7 +142,7 @@
sizeNew <<= 1;
lengths = BufferUtils.createIntBuffer(size);
- lengthsTL.set(lengths);
+ caps.util.lengths = lengths;
} else
lengths.clear();
@@ -168,9 +174,9 @@
*
* @return the buffer as a String.
*/
- static String getString(final ByteBuffer buffer) {
+ static String getString(final ContextCapabilities caps, final ByteBuffer buffer) {
final int length = buffer.remaining();
- final char[] charArray = getArray(length);
+ final char[] charArray = getArray(caps, length);
for ( int i = buffer.position(); i < buffer.limit(); i++ )
charArray[i - buffer.position()] = (char)buffer.get(i);
@@ -185,10 +191,10 @@
*
* @return the String as a ByteBuffer
*/
- static ByteBuffer getBuffer(final CharSequence string) {
- final ByteBuffer buffer = encode(getBufferByte(string.length()), string);
- buffer.flip();
- return buffer;
+ static long getBuffer(final ContextCapabilities caps, final CharSequence string) {
+ final ByteBuffer buffer = encode(getBufferByte(caps, string.length()), string);
+ buffer.flip();
+ return MemoryUtil.getAddress0(buffer);
}
/**
@@ -198,10 +204,10 @@
*
* @return the String as a ByteBuffer
*/
- static ByteBuffer getBuffer(final CharSequence string, final int offset) {
- final ByteBuffer buffer = encode(getBufferByteOffset(offset + string.length()), string);
- buffer.flip();
- return buffer;
+ static long getBuffer(final ContextCapabilities caps, final CharSequence string, final int offset) {
+ final ByteBuffer buffer = encode(getBufferByteOffset(caps, offset + string.length()), string);
+ buffer.flip();
+ return MemoryUtil.getAddress(buffer);
}
/**
@@ -211,11 +217,11 @@
*
* @return the String as a ByteBuffer
*/
- static ByteBuffer getBufferNT(final CharSequence string) {
- final ByteBuffer buffer = encode(getBufferByte(string.length() + 1), string);
+ static long getBufferNT(final ContextCapabilities caps, final CharSequence string) {
+ final ByteBuffer buffer = encode(getBufferByte(caps, string.length() + 1), string);
buffer.put((byte)0);
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress0(buffer);
}
static int getTotalLength(final CharSequence[] strings) {
@@ -233,14 +239,14 @@
*
* @return the Strings as a ByteBuffer
*/
- static ByteBuffer getBuffer(final CharSequence[] strings) {
- final ByteBuffer buffer = getBufferByte(getTotalLength(strings));
+ static long getBuffer(final ContextCapabilities caps, final CharSequence[] strings) {
+ final ByteBuffer buffer = getBufferByte(caps, getTotalLength(strings));
for ( CharSequence string : strings )
encode(buffer, string);
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress0(buffer);
}
/**
@@ -250,8 +256,8 @@
*
* @return the Strings as a ByteBuffer
*/
- static ByteBuffer getBufferNT(final CharSequence[] strings) {
- final ByteBuffer buffer = getBufferByte(getTotalLength(strings) + strings.length);
+ static long getBufferNT(final ContextCapabilities caps, final CharSequence[] strings) {
+ final ByteBuffer buffer = getBufferByte(caps, getTotalLength(strings) + strings.length);
for ( CharSequence string : strings ) {
encode(buffer, string);
@@ -259,7 +265,7 @@
}
buffer.flip();
- return buffer;
+ return MemoryUtil.getAddress0(buffer);
}
/**
@@ -269,34 +275,22 @@
*
* @return the String lengths in an IntBuffer
*/
- static IntBuffer getLengths(final CharSequence[] strings) {
- IntBuffer buffer = getLengths(strings.length);
+ static long getLengths(final ContextCapabilities caps, final CharSequence[] strings) {
+ IntBuffer buffer = getLengths(caps, strings.length);
for ( CharSequence string : strings )
buffer.put(string.length());
buffer.flip();
- return buffer;
- }
-
- private static class Buffers {
-
- final ShortBuffer shorts;
- final IntBuffer ints;
- final LongBuffer longs;
-
- final FloatBuffer floats;
- final DoubleBuffer doubles;
-
- Buffers() {
- shorts = BufferUtils.createShortBuffer(BUFFERS_SIZE);
- ints = BufferUtils.createIntBuffer(BUFFERS_SIZE);
- longs = BufferUtils.createLongBuffer(BUFFERS_SIZE);
-
- floats = BufferUtils.createFloatBuffer(BUFFERS_SIZE);
- doubles = BufferUtils.createDoubleBuffer(BUFFERS_SIZE);
- }
-
+ return MemoryUtil.getAddress0(buffer);
+ }
+
+ static long getInt(final ContextCapabilities caps, final int value) {
+ return MemoryUtil.getAddress0(getBufferInt(caps).put(0, value));
+ }
+
+ static long getBufferByte0(final ContextCapabilities caps) {
+ return MemoryUtil.getAddress0(getBufferByte(caps, 0));
}
}diff --git a/src/java/org/lwjgl/opengl/ARBDebugOutputCallback.java b/src/java/org/lwjgl/opengl/ARBDebugOutputCallback.java
index e1b02dd..26935d8 100644
--- a/src/java/org/lwjgl/opengl/ARBDebugOutputCallback.java
+++ b/src/java/org/lwjgl/opengl/ARBDebugOutputCallback.java
@@ -113,7 +113,7 @@
description = "OTHER";
break;
default:
- description = "Unknown (" + Integer.toHexString(source) + ")";
+ description = printUnknownToken(source);
}
System.err.println("\tSource: " + description);
@@ -137,7 +137,7 @@
description = "OTHER";
break;
default:
- description = "Unknown (" + Integer.toHexString(source) + ")";
+ description = printUnknownToken(type);
}
System.err.println("\tType: " + description);
@@ -152,11 +152,15 @@
description = "LOW";
break;
default:
- description = "Unknown (" + Integer.toHexString(source) + ")";
+ description = printUnknownToken(severity);
}
System.err.println("\tSeverity: " + description);
System.err.println("\tMessage: " + message);
+ }
+
+ private String printUnknownToken(final int token) {
+ return "Unknown (0x" + Integer.toHexString(token).toUpperCase() + ")";
}
});
}
@@ -184,9 +188,9 @@
/**
* This method will be called when an ARB_debug_output message is generated.
*
- * @param id the message ID
* @param source the message source
* @param type the message type
+ * @param id the message ID
* @param severity the message severity
* @param message the string representation of the message.
*/
diff --git a/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java b/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java
index 5b2a8eb..a9faffd 100644
--- a/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java
+++ b/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java
@@ -40,14 +40,14 @@
/**
*
* @author elias_naur
- * @version $Revision: 3002 $
- * $Id: AWTCanvasImplementation.java 3002 2008-04-10 20:25:54Z elias_naur $
+ * @version $Revision$
+ * $Id$
*/
interface AWTCanvasImplementation {
/**
* Return an opaque handle to the canvas peer information required to create a context from it.
*/
- PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException;
+ PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException;
/**
* Find a proper GraphicsConfiguration from the given GraphicsDevice and PixelFormat.
diff --git a/src/java/org/lwjgl/opengl/AWTGLCanvas.java b/src/java/org/lwjgl/opengl/AWTGLCanvas.java
index 543da00..bf7ab1b 100644
--- a/src/java/org/lwjgl/opengl/AWTGLCanvas.java
+++ b/src/java/org/lwjgl/opengl/AWTGLCanvas.java
@@ -42,21 +42,23 @@
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
+import static org.lwjgl.opengl.GL11.*;
+
/**
*
* An AWT rendering context.
*
*
- * @author $Author: spasi $
- * $Id: AWTGLCanvas.java 3418 2010-09-28 21:11:35Z spasi $
- * @version $Revision: 3418 $
+ * @author $Author$
+ * $Id$
+ * @version $Revision$
*/
public class AWTGLCanvas extends Canvas implements DrawableLWJGL, ComponentListener, HierarchyListener {
private static final long serialVersionUID = 1L;
private static final AWTCanvasImplementation implementation;
- private boolean update_context;
+ private boolean update_context;
private Object SYNC_LOCK = new Object();
/** The requested pixel format */
@@ -69,8 +71,8 @@
private final ContextAttribs attribs;
/** Context handle */
- private PeerInfo peer_info;
- private Context context;
+ private PeerInfo peer_info;
+ private ContextGL context;
/**
* re-entry counter for support for re-entrant
@@ -105,18 +107,41 @@
}
}
+ public void setPixelFormat(final PixelFormatLWJGL pf) throws LWJGLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setPixelFormat(final PixelFormatLWJGL pf, final ContextAttribs attribs) throws LWJGLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public PixelFormatLWJGL getPixelFormat() {
+ return pixel_format;
+ }
+
/** This method should only be called internally. */
- public Context getContext() {
+ public ContextGL getContext() {
return context;
}
/** This method should only be called internally. */
- public Context createSharedContext() throws LWJGLException {
+ public ContextGL createSharedContext() throws LWJGLException {
synchronized ( SYNC_LOCK ) {
if ( context == null ) throw new IllegalStateException("Canvas not yet displayable");
- return new Context(peer_info, context.getContextAttribs(), context);
- }
+ return new ContextGL(peer_info, context.getContextAttribs(), context);
+ }
+ }
+
+ public void checkGLError() {
+ Util.checkGLError();
+ }
+
+ public void initContext(final float r, final float g, final float b) {
+ // set background clear color
+ glClearColor(r, g, b, 0.0f);
+ // Clear window to avoid the desktop "showing through"
+ glClear(GL_COLOR_BUFFER_BIT);
}
/** Constructor using the default PixelFormat. */
@@ -195,7 +220,7 @@
synchronized ( SYNC_LOCK ) {
if ( context == null )
throw new IllegalStateException("Canvas not yet displayable");
- Context.setSwapInterval(swap_interval);
+ ContextGL.setSwapInterval(swap_interval);
}
}
@@ -209,7 +234,7 @@
synchronized ( SYNC_LOCK ) {
if ( context == null )
throw new IllegalStateException("Canvas not yet displayable");
- Context.swapBuffers();
+ ContextGL.swapBuffers();
}
}
@@ -238,7 +263,7 @@
if ( context == null )
throw new IllegalStateException("Canvas not yet displayable");
if ( context.isCurrent() )
- Context.releaseCurrentContext();
+ context.releaseCurrent();
}
}
@@ -290,12 +315,12 @@
return;
try {
if ( peer_info == null ) {
- this.peer_info = implementation.createPeerInfo(this, pixel_format);
+ this.peer_info = implementation.createPeerInfo(this, pixel_format, attribs);
}
peer_info.lockAndGetHandle();
try {
if ( context == null ) {
- this.context = new Context(peer_info, attribs, drawable != null ? ((DrawableLWJGL)drawable).getContext() : null);
+ this.context = new ContextGL(peer_info, attribs, drawable != null ? (ContextGL)((DrawableLWJGL)drawable).getContext() : null);
first_run = true;
}
@@ -315,7 +340,7 @@
} finally {
reentry_count--;
if ( reentry_count == 0 )
- Context.releaseCurrentContext();
+ context.releaseCurrent();
}
} finally {
peer_info.unlock();
diff --git a/src/java/org/lwjgl/opengl/AWTSurfaceLock.java b/src/java/org/lwjgl/opengl/AWTSurfaceLock.java
index cc40960..b0935db 100644
--- a/src/java/org/lwjgl/opengl/AWTSurfaceLock.java
+++ b/src/java/org/lwjgl/opengl/AWTSurfaceLock.java
@@ -32,6 +32,8 @@
package org.lwjgl.opengl;
import java.awt.Canvas;
+import java.awt.Component;
+import java.applet.Applet;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedActionException;
@@ -43,8 +45,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3418 $
- * $Id: AWTSurfaceLock.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class AWTSurfaceLock {
@@ -78,7 +80,8 @@
// We need to elevate privileges because of an AWT bug. Please see
// http://192.18.37.44/forums/index.php?topic=10572 for a discussion.
// It is only needed on first call, so we avoid it on all subsequent calls
- // due to performance.
+ // due to performance..
+
if (firstLockSucceeded)
return lockAndInitHandle(lock_buffer, component);
else
diff --git a/src/java/org/lwjgl/opengl/AbstractDrawable.java b/src/java/org/lwjgl/opengl/AbstractDrawable.java
deleted file mode 100644
index 8823597..0000000
--- a/src/java/org/lwjgl/opengl/AbstractDrawable.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.lwjgl.opengl;
-
-import org.lwjgl.LWJGLException;
-import org.lwjgl.LWJGLUtil;
-import org.lwjgl.PointerBuffer;
-
-/**
- * @author Spasi
- */
-abstract class AbstractDrawable implements DrawableLWJGL {
-
- /** Handle to the native GL rendering context */
- protected PeerInfo peer_info;
-
- /** The OpenGL Context. */
- protected Context context;
-
- protected AbstractDrawable() {
- }
-
- public Context getContext() {
- synchronized ( GlobalLock.lock ) {
- return context;
- }
- }
-
- public Context createSharedContext() throws LWJGLException {
- synchronized ( GlobalLock.lock ) {
- checkDestroyed();
- return new Context(peer_info, context.getContextAttribs(), context);
- }
- }
-
- public boolean isCurrent() throws LWJGLException {
- synchronized ( GlobalLock.lock ) {
- checkDestroyed();
- return context.isCurrent();
- }
- }
-
- public void makeCurrent() throws LWJGLException {
- synchronized ( GlobalLock.lock ) {
- checkDestroyed();
- context.makeCurrent();
- }
- }
-
- public void releaseContext() throws LWJGLException {
- synchronized ( GlobalLock.lock ) {
- checkDestroyed();
- if ( context.isCurrent() )
- Context.releaseCurrentContext();
- }
- }
-
- public void destroy() {
- synchronized ( GlobalLock.lock ) {
- if ( context == null )
- return;
-
- try {
- releaseContext();
-
- context.forceDestroy();
- context = null;
-
- if ( peer_info != null ) {
- peer_info.destroy();
- peer_info = null;
- }
- } catch (LWJGLException e) {
- LWJGLUtil.log("Exception occurred while destroying Drawable: " + e);
- }
- }
- }
-
- public void setCLSharingProperties(final PointerBuffer properties) throws LWJGLException {
- synchronized ( GlobalLock.lock ) {
- checkDestroyed();
- context.setCLSharingProperties(properties);
- }
- }
-
- protected final void checkDestroyed() {
- if ( context == null )
- throw new IllegalStateException("The Drawable has no context available.");
- }
-
-}
diff --git a/src/java/org/lwjgl/opengl/CallbackUtil.java b/src/java/org/lwjgl/opengl/CallbackUtil.java
index 0c938e7..fa12171 100644
--- a/src/java/org/lwjgl/opengl/CallbackUtil.java
+++ b/src/java/org/lwjgl/opengl/CallbackUtil.java
@@ -42,9 +42,11 @@
final class CallbackUtil {
/** Context -> Long */
- private static final Map contextUserParamsARB = new HashMap();
+ private static final Map contextUserParamsARB = new HashMap();
/** Context -> Long */
- private static final Map contextUserParamsAMD = new HashMap();
+ private static final Map contextUserParamsAMD = new HashMap();
+ /** Context -> Long */
+ private static final Map contextUserParamsKHR = new HashMap();
private CallbackUtil() {}
@@ -84,19 +86,19 @@
*
* @param userParam the global reference pointer
*/
- private static void registerContextCallback(final long userParam, final Map contextUserData) {
- Context context = Context.getCurrentContext();
- if ( context == null ) {
+ private static void registerContextCallback(final long userParam, final Map contextUserData) {
+ ContextCapabilities caps = GLContext.getCapabilities();
+ if ( caps == null ) {
deleteGlobalRef(userParam);
throw new IllegalStateException("No context is current.");
}
- final Long userParam_old = contextUserData.remove(context);
+ final Long userParam_old = contextUserData.remove(caps);
if ( userParam_old != null )
deleteGlobalRef(userParam_old);
if ( userParam != 0 )
- contextUserData.put(context, userParam);
+ contextUserData.put(caps, userParam);
}
/**
@@ -104,12 +106,19 @@
*
* @param context the Context to unregister
*/
- static void unregisterCallbacks(final Context context) {
- Long userParam = contextUserParamsARB.remove(context);
+ static void unregisterCallbacks(final Object context) {
+ // TODO: This is never called for custom contexts. Need to fix for LWJGL 3.0
+ final ContextCapabilities caps = GLContext.getCapabilities(context);
+
+ Long userParam = contextUserParamsARB.remove(caps);
if ( userParam != null )
deleteGlobalRef(userParam);
- userParam = contextUserParamsAMD.remove(context);
+ userParam = contextUserParamsAMD.remove(caps);
+ if ( userParam != null )
+ deleteGlobalRef(userParam);
+
+ userParam = contextUserParamsKHR.remove(caps);
if ( userParam != null )
deleteGlobalRef(userParam);
}
@@ -154,4 +163,24 @@
registerContextCallback(userParam, contextUserParamsAMD);
}
+ // --------- [ KHR_debug ] ---------
+
+ /**
+ * Returns the memory address of the native function we pass to glDebugMessageCallback.
+ *
+ * @return the callback function address
+ */
+ static native long getDebugCallbackKHR();
+
+ /**
+ * Associates the current OpenGL context with the specified global reference. If there
+ * is no context current, the global reference is deleted and an exception is thrown.
+ * Any previous callback registrations will be cleared.
+ *
+ * @param userParam the global reference pointer
+ */
+ static void registerContextCallbackKHR(final long userParam) {
+ registerContextCallback(userParam, contextUserParamsKHR);
+ }
+
}diff --git a/src/java/org/lwjgl/opengl/Context.java b/src/java/org/lwjgl/opengl/Context.java
index e9e9833..15978e1 100644
--- a/src/java/org/lwjgl/opengl/Context.java
+++ b/src/java/org/lwjgl/opengl/Context.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2008 LWJGL Project
+ * Copyright (c) 2002-2011 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,255 +32,19 @@
package org.lwjgl.opengl;
import org.lwjgl.LWJGLException;
-import org.lwjgl.LWJGLUtil;
-import org.lwjgl.PointerBuffer;
-import org.lwjgl.Sys;
-import org.lwjgl.opencl.KHRGLSharing;
-
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-
-import static org.lwjgl.opengl.GL11.*;
/**
- *
- * Context encapsulates an OpenGL context.
- *
- *
- * This class is thread-safe.
- *
- * @author elias_naur
- * @version $Revision: 3418 $
- * $Id: Context.java 3418 2010-09-28 21:11:35Z spasi $
+ * @author Spasi
+ * @since 14/5/2011
*/
-final class Context {
+interface Context {
- /** The platform specific implementation of context methods */
- private static final ContextImplementation implementation;
+ boolean isCurrent() throws LWJGLException;
- /** The current Context */
- private static final ThreadLocal current_context_local = new ThreadLocal();
+ void makeCurrent() throws LWJGLException;
- /** Handle to the native GL rendering context */
- private final ByteBuffer handle;
- private final PeerInfo peer_info;
+ void releaseCurrent() throws LWJGLException;
- private final ContextAttribs contextAttribs;
- private final boolean forwardCompatible;
-
- /** Whether the context has been destroyed */
- private boolean destroyed;
-
- private boolean destroy_requested;
-
- /** The thread that has this context current, or null. */
- private Thread thread;
-
- static {
- Sys.initialize();
- implementation = createImplementation();
- }
-
- private static ContextImplementation createImplementation() {
- switch ( LWJGLUtil.getPlatform() ) {
- case LWJGLUtil.PLATFORM_LINUX:
- return new LinuxContextImplementation();
- case LWJGLUtil.PLATFORM_WINDOWS:
- return new WindowsContextImplementation();
- case LWJGLUtil.PLATFORM_MACOSX:
- return new MacOSXContextImplementation();
- default:
- throw new IllegalStateException("Unsupported platform");
- }
- }
-
- PeerInfo getPeerInfo() {
- return peer_info;
- }
-
- ContextAttribs getContextAttribs() {
- return contextAttribs;
- }
-
- static Context getCurrentContext() {
- return current_context_local.get();
- }
-
- /** Create a context with the specified peer info and shared context */
- Context(PeerInfo peer_info, ContextAttribs attribs, Context shared_context) throws LWJGLException {
- Context context_lock = shared_context != null ? shared_context : this;
- // If shared_context is not null, synchronize on it to make sure it is not deleted
- // while this context is created. Otherwise, simply synchronize on ourself to avoid NPE
- synchronized ( context_lock ) {
- if ( shared_context != null && shared_context.destroyed )
- throw new IllegalArgumentException("Shared context is destroyed");
- GLContext.loadOpenGLLibrary();
- try {
- this.peer_info = peer_info;
- this.contextAttribs = attribs;
-
- IntBuffer attribList;
- if ( attribs != null ) {
- attribList = attribs.getAttribList();
- forwardCompatible = attribs.isForwardCompatible();
- } else {
- attribList = null;
- forwardCompatible = false;
- }
-
- this.handle = implementation.create(peer_info, attribList, shared_context != null ? shared_context.handle : null);
- } catch (LWJGLException e) {
- GLContext.unloadOpenGLLibrary();
- throw e;
- }
- }
- }
-
- /** Release the current context (if any). After this call, no context is current. */
- public static void releaseCurrentContext() throws LWJGLException {
- Context current_context = getCurrentContext();
- if ( current_context != null ) {
- implementation.releaseCurrentContext();
- GLContext.useContext(null);
- current_context_local.set(null);
- synchronized ( current_context ) {
- current_context.thread = null;
- current_context.checkDestroy();
- }
- }
- }
-
- /**
- * Release the context from its drawable. This is necessary on some platforms,
- * like Mac OS X, where binding the context to a drawable and binding the context
- * for rendering are two distinct actions and where calling releaseDrawable
- * on every releaseCurrentContext results in artifacts.
- */
- public synchronized void releaseDrawable() throws LWJGLException {
- if ( destroyed )
- throw new IllegalStateException("Context is destroyed");
- implementation.releaseDrawable(getHandle());
- }
-
- /** Update the context. Should be called whenever it's drawable is moved or resized */
- public synchronized void update() {
- if ( destroyed )
- throw new IllegalStateException("Context is destroyed");
- implementation.update(getHandle());
- }
-
- /** Swap the buffers on the current context. Only valid for double-buffered contexts */
- public static void swapBuffers() throws LWJGLException {
- implementation.swapBuffers();
- }
-
- private boolean canAccess() {
- return thread == null || Thread.currentThread() == thread;
- }
-
- private void checkAccess() {
- if ( !canAccess() )
- throw new IllegalStateException("From thread " + Thread.currentThread() + ": " + thread + " already has the context current");
- }
-
- /** Make the context current */
- public synchronized void makeCurrent() throws LWJGLException {
- checkAccess();
- if ( destroyed )
- throw new IllegalStateException("Context is destroyed");
- thread = Thread.currentThread();
- current_context_local.set(this);
- implementation.makeCurrent(peer_info, handle);
- GLContext.useContext(this, forwardCompatible);
- }
-
- ByteBuffer getHandle() {
- return handle;
- }
-
- /** Query whether the context is current */
- public synchronized boolean isCurrent() throws LWJGLException {
- if ( destroyed )
- throw new IllegalStateException("Context is destroyed");
- return implementation.isCurrent(handle);
- }
-
- private void checkDestroy() {
- if ( !destroyed && destroy_requested ) {
- try {
- releaseDrawable();
- implementation.destroy(peer_info, handle);
- CallbackUtil.unregisterCallbacks(this);
- destroyed = true;
- thread = null;
- GLContext.unloadOpenGLLibrary();
- } catch (LWJGLException e) {
- LWJGLUtil.log("Exception occurred while destroying context: " + e);
- }
- }
- }
-
- /**
- * Set the buffer swap interval. This call is a best-attempt at changing
- * the monitor swap interval, which is the minimum periodicity of color buffer swaps,
- * measured in video frame periods, and is not guaranteed to be successful.
- *
- * A video frame period is the time required to display a full frame of video data.
- */
- public static void setSwapInterval(int value) {
- implementation.setSwapInterval(value);
- }
-
- /**
- * Destroy the context. This method behaves the same as destroy() with the extra
- * requirement that the context must be either current to the current thread or not
- * current at all.
- */
- public synchronized void forceDestroy() throws LWJGLException {
- checkAccess();
- destroy();
- }
-
- /**
- * Request destruction of the Context. If the context is current, no context will be current after this call.
- * The context is destroyed when no thread has it current.
- */
- public synchronized void destroy() throws LWJGLException {
- if ( destroyed )
- return;
- destroy_requested = true;
- boolean was_current = isCurrent();
- int error = GL_NO_ERROR;
- if ( was_current ) {
- if ( GLContext.getCapabilities() != null && GLContext.getCapabilities().OpenGL11 )
- error = glGetError();
- releaseCurrentContext();
- }
- checkDestroy();
- if ( was_current && error != GL_NO_ERROR )
- throw new OpenGLException(error);
- }
-
- public synchronized void setCLSharingProperties(final PointerBuffer properties) throws LWJGLException {
- final ByteBuffer peer_handle = peer_info.lockAndGetHandle();
- try {
- switch ( LWJGLUtil.getPlatform() ) {
- case LWJGLUtil.PLATFORM_WINDOWS:
- final WindowsContextImplementation implWindows = (WindowsContextImplementation)implementation;
- properties.put(KHRGLSharing.CL_GL_CONTEXT_KHR).put(implWindows.getHGLRC(handle));
- properties.put(KHRGLSharing.CL_WGL_HDC_KHR).put(implWindows.getHDC(peer_handle));
- break;
- case LWJGLUtil.PLATFORM_LINUX:
- final LinuxContextImplementation implLinux = (LinuxContextImplementation)implementation;
- properties.put(KHRGLSharing.CL_GL_CONTEXT_KHR).put(implLinux.getGLXContext(handle));
- properties.put(KHRGLSharing.CL_GLX_DISPLAY_KHR).put(implLinux.getDisplay(peer_handle));
- break;
- default:
- throw new UnsupportedOperationException("CL/GL context sharing is not supposed on this platform.");
- }
- } finally {
- peer_info.unlock();
- }
- }
+ void releaseDrawable() throws LWJGLException;
}diff --git a/src/java/org/lwjgl/opengl/ContextAttribs.java b/src/java/org/lwjgl/opengl/ContextAttribs.java
index 552a1bb..977d604 100644
--- a/src/java/org/lwjgl/opengl/ContextAttribs.java
+++ b/src/java/org/lwjgl/opengl/ContextAttribs.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2008 LWJGL Project
+ * Copyright (c) 2002-2014 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,269 +35,399 @@
import org.lwjgl.LWJGLUtil;
import java.nio.IntBuffer;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
/**
- * This class represents the context attributes passed to CreateContextAttribs of the ARB_create_context and
- * ARB_create_context_profile extensions.
- * These attributes can be used to indicate at context creation which OpenGL interface will be used. This includes the
- * OpenGL version, the layer plane on which rendering takes place and also optional debug and forward combatibility modes.
- * (read the ARB_create_context spec for details)
+ * This class represents the context attributes passed to CreateContextAttribs of the ARB_create_context extension.
+ *
+ * The attributes supported are described in the following extensions:
+ *
*
* Use of this class is optional. If an OpenGL context is created without passing an instance of this class
* (or ARB_create_context is not supported), the old context creation code will be used. Support for debug and forward
* compatible mobes is not guaranteed by the OpenGL implementation. Developers may encounter debug contexts being the same
* as non-debug contexts or forward compatible contexts having support for deprecated functionality.
*
- * If the forwardCompatible
- * attribute is used, LWJGL will not load the deprecated functionality (as defined in the OpenGL 3.0 specification). This
- * means that developers can start working on cleaning up their applications without an OpenGL 3.0 complaint driver.
+ * If the {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB} flag is used, LWJGL will not load the deprecated functionality (as defined in the OpenGL 3.0
+ * specification), even if the driver exposes the corresponding entry points.
+ *
+ * This extension is not supported on MacOS X. However, in order to enable the GL 3.2 context on MacOS X 10.7 or newer, an instance of this class must be passed
+ * to LWJGL. The only valid configuration is ContextAttribs(3, 2, CONTEXT_CORE_PROFILE_BIT_ARB)
, anything else will be ignored.
*
* @author spasi
*/
public final class ContextAttribs {
- // Same values for GLX & WGL
- private static final int CONTEXT_ES2_PROFILE_BIT_EXT = 0x00000004;
-
- private static final int CONTEXT_ROBUST_ACCESS_BIT_ARB = 0x00000004;
- private static final int CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB = 0x8256;
- private static final int
- NO_RESET_NOTIFICATION_ARB = 0x8261,
- LOSE_CONTEXT_ON_RESET_ARB = 0x8252;
+ // ATTRIBUTES
+
+ public static final int CONTEXT_MAJOR_VERSION_ARB = 0x2091;
+ public static final int CONTEXT_MINOR_VERSION_ARB = 0x2092;
+
+ public static final int CONTEXT_PROFILE_MASK_ARB = 0x9126,
+ CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001,
+ CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002,
+ CONTEXT_ES2_PROFILE_BIT_EXT = 0x00000004;
+
+ public static final int CONTEXT_FLAGS_ARB = 0x2094,
+ CONTEXT_DEBUG_BIT_ARB = 0x0001,
+ CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002,
+ CONTEXT_ROBUST_ACCESS_BIT_ARB = 0x00000004,
+ CONTEXT_RESET_ISOLATION_BIT_ARB = 0x00000008;
+
+ public static final int CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB = 0x8256,
+ NO_RESET_NOTIFICATION_ARB = 0x8261,
+ LOSE_CONTEXT_ON_RESET_ARB = 0x8252;
+
+ public static final int CONTEXT_RELEASE_BEHABIOR_ARB = 0x2097,
+ CONTEXT_RELEASE_BEHAVIOR_NONE_ARB = 0x0000,
+ CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB = 0x2098;
+
+ public static final int CONTEXT_LAYER_PLANE_ARB = 0x2093; // WGL-only
+
+ // STATE
private int majorVersion;
private int minorVersion;
+ private int profileMask;
+ private int contextFlags;
+
+ private int contextResetNotificationStrategy = NO_RESET_NOTIFICATION_ARB;
+ private int contextReleaseBehavior = CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB;
+
private int layerPlane;
- private boolean debug;
- private boolean forwardCompatible;
- private boolean robustAccess;
-
- private boolean profileCore;
- private boolean profileCompatibility;
- private boolean profileES;
-
- private boolean loseContextOnReset;
-
+ // CONSTRUCTORS
+
+ /** Creates the default ContextAttribs instance. No special attributes will be used when creating the OpenGL context. */
public ContextAttribs() {
this(1, 0);
}
- public ContextAttribs(final int majorVersion, final int minorVersion) {
+ /** Creates a ContextAttribs instance for the given OpenGL version. */
+ public ContextAttribs(int majorVersion, int minorVersion) {
+ this(majorVersion, minorVersion, 0, 0);
+ }
+
+ /**
+ * Creates a new ContextAttribs instance with the given attributes.
+ *
+ * @param majorVersion the major OpenGL version
+ * @param minorVersion the minor OpenGL version
+ * @param profileMask the context profile mask. One of: {@link #CONTEXT_CORE_PROFILE_BIT_ARB}, {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB}, {@link #CONTEXT_ES2_PROFILE_BIT_EXT}
+ */
+ public ContextAttribs(int majorVersion, int minorVersion, int profileMask) {
+ this(majorVersion, minorVersion, 0, profileMask);
+ }
+
+ /**
+ * Creates a new ContextAttribs instance with the given attributes.
+ *
+ * @param majorVersion the major OpenGL version
+ * @param minorVersion the minor OpenGL version
+ * @param profileMask the context profile mask. One of: {@link #CONTEXT_CORE_PROFILE_BIT_ARB}, {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB}, {@link #CONTEXT_ES2_PROFILE_BIT_EXT}
+ * @param contextFlags the context flags, a bitfield value. One or more of: {@link #CONTEXT_DEBUG_BIT_ARB}, {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB}, {@link #CONTEXT_ROBUST_ACCESS_BIT_ARB}, {@link #CONTEXT_RESET_ISOLATION_BIT_ARB}
+ */
+ public ContextAttribs(int majorVersion, int minorVersion, int profileMask, int contextFlags) {
if ( majorVersion < 0 || 4 < majorVersion ||
minorVersion < 0 ||
- (majorVersion == 4 && 0 < minorVersion) ||
+ (majorVersion == 4 && 5 < minorVersion) ||
(majorVersion == 3 && 3 < minorVersion) ||
(majorVersion == 2 && 1 < minorVersion) ||
(majorVersion == 1 && 5 < minorVersion) )
throw new IllegalArgumentException("Invalid OpenGL version specified: " + majorVersion + '.' + minorVersion);
+ if ( LWJGLUtil.CHECKS ) {
+ if ( 1 < Integer.bitCount(profileMask) || CONTEXT_ES2_PROFILE_BIT_EXT < profileMask )
+ throw new IllegalArgumentException("Invalid profile mask specified: " + Integer.toBinaryString(profileMask));
+
+ if ( 0xF < contextFlags )
+ throw new IllegalArgumentException("Invalid context flags specified: " + Integer.toBinaryString(profileMask));
+ }
+
this.majorVersion = majorVersion;
this.minorVersion = minorVersion;
- }
-
- private ContextAttribs(final ContextAttribs attribs) {
- this.majorVersion = attribs.majorVersion;
- this.minorVersion = attribs.minorVersion;
-
- this.layerPlane = attribs.layerPlane;
-
- this.debug = attribs.debug;
- this.forwardCompatible = attribs.forwardCompatible;
- this.robustAccess = attribs.robustAccess;
-
- this.profileCore = attribs.profileCore;
- this.profileCompatibility = attribs.profileCompatibility;
- this.profileES = attribs.profileES;
-
- this.loseContextOnReset = attribs.loseContextOnReset;
- }
-
+
+ this.profileMask = profileMask;
+ this.contextFlags = contextFlags;
+ }
+
+ // Copy constructor
+ private ContextAttribs(ContextAttribs other) {
+ this.majorVersion = other.majorVersion;
+ this.minorVersion = other.minorVersion;
+
+ this.profileMask = other.profileMask;
+ this.contextFlags = other.contextFlags;
+
+ this.contextResetNotificationStrategy = other.contextResetNotificationStrategy;
+ this.contextReleaseBehavior = other.contextReleaseBehavior;
+
+ this.layerPlane = other.layerPlane;
+ }
+
+ // GETTERS
+
+ /** Returns the {@link #CONTEXT_MAJOR_VERSION_ARB} value. */
public int getMajorVersion() {
return majorVersion;
}
+ /** Returns the {@link #CONTEXT_MINOR_VERSION_ARB} value. */
public int getMinorVersion() {
return minorVersion;
}
+ /** Returns the {@link #CONTEXT_PROFILE_MASK_ARB} value. */
+ public int getProfileMask() {
+ return profileMask;
+ }
+
+ private boolean hasMask(int mask) {
+ return profileMask == mask;
+ }
+
+ /** Returns true if the {@link #CONTEXT_CORE_PROFILE_BIT_ARB} has been set. */
+ public boolean isProfileCore() {
+ return hasMask(CONTEXT_CORE_PROFILE_BIT_ARB);
+ }
+
+ /** Returns true if the {@link #CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB} has been set. */
+ public boolean isProfileCompatibility() {
+ return hasMask(CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
+ }
+
+ /** Returns true if the {@link #CONTEXT_ES2_PROFILE_BIT_EXT} has been set. */
+ public boolean isProfileES() {
+ return hasMask(CONTEXT_ES2_PROFILE_BIT_EXT);
+ }
+
+ /** Returns the {@link #CONTEXT_FLAGS_ARB} value. */
+ public int getContextFlags() {
+ return contextFlags;
+ }
+
+ private boolean hasFlag(int flag) {
+ return (contextFlags & flag) != 0;
+ }
+
+ /** Returns true if the {@link #CONTEXT_DEBUG_BIT_ARB} has been set. */
+ public boolean isDebug() {
+ return hasFlag(CONTEXT_DEBUG_BIT_ARB);
+ }
+
+ /** Returns true if the {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB} has been set. */
+ public boolean isForwardCompatible() {
+ return hasFlag(CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
+ }
+
+ /** Returns true if the {@link #CONTEXT_ROBUST_ACCESS_BIT_ARB} has been set. */
+ public boolean isRobustAccess() { return hasFlag(CONTEXT_ROBUST_ACCESS_BIT_ARB); }
+
+ /** Returns true if the {@link #CONTEXT_RESET_ISOLATION_BIT_ARB} has been set. */
+ public boolean isContextResetIsolation() {
+ return hasFlag(CONTEXT_RESET_ISOLATION_BIT_ARB);
+ }
+
+ /** Returns the {@link #CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB} value. */
+ public int getContextResetNotificationStrategy() {
+ return contextResetNotificationStrategy;
+ }
+
+ /**
+ * Returns true if the {@link #CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB} has been set to {@link #LOSE_CONTEXT_ON_RESET_ARB}.
+ *
+ * @deprecated use {@link #getContextResetNotificationStrategy} instead
+ */
+ public boolean isLoseContextOnReset() { return contextResetNotificationStrategy == LOSE_CONTEXT_ON_RESET_ARB; }
+
+ /** Returns the {@link #CONTEXT_RELEASE_BEHABIOR_ARB} value. */
+ public int getContextReleaseBehavior() {
+ return contextReleaseBehavior;
+ }
+
+ /** Returns the {@link #CONTEXT_LAYER_PLANE_ARB} value. */
public int getLayerPlane() {
return layerPlane;
}
- public boolean isDebug() {
- return debug;
- }
-
- public boolean isForwardCompatible() {
- return forwardCompatible;
- }
-
- public boolean isProfileCore() {
- return profileCore;
- }
-
- public boolean isProfileCompatibility() {
- return profileCompatibility;
- }
-
- public boolean isProfileES() {
- return profileES;
- }
-
- public ContextAttribs withLayer(final int layerPlane) {
+ // CHAIN CONFIGURATION PATTERN
+
+ private ContextAttribs toggleMask(int mask, boolean value) {
+ if ( value == hasMask(mask) )
+ return this;
+
+ ContextAttribs attribs = new ContextAttribs(this);
+ attribs.profileMask = value ? mask : 0;
+ return attribs;
+ }
+
+ /**
+ * Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_CORE_PROFILE_BIT_ARB} bit in {@link #CONTEXT_PROFILE_MASK_ARB} set to the given value.
+ * If {@code profileCore} is true, all other bits in the mask are cleared.
+ */
+ public ContextAttribs withProfileCore(boolean profileCore) {
+ if ( majorVersion < 3 || (majorVersion == 3 && minorVersion < 2) )
+ throw new IllegalArgumentException("Profiles are only supported on OpenGL version 3.2 or higher.");
+
+ return toggleMask(CONTEXT_CORE_PROFILE_BIT_ARB, profileCore);
+ }
+
+ /**
+ * Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB} bit in {@link #CONTEXT_PROFILE_MASK_ARB} set to the given value.
+ * If {@code profileCompatibility} is true, all other bits in the mask are cleared.
+ */
+ public ContextAttribs withProfileCompatibility(boolean profileCompatibility) {
+ if ( majorVersion < 3 || (majorVersion == 3 && minorVersion < 2) )
+ throw new IllegalArgumentException("Profiles are only supported on OpenGL version 3.2 or higher.");
+
+ return toggleMask(CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, profileCompatibility);
+ }
+
+ /**
+ * Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_ES2_PROFILE_BIT_EXT} bit in {@link #CONTEXT_PROFILE_MASK_ARB} set to the given value.
+ * If {@code profileES} is true, all other bits in the mask are cleared.
+ */
+ public ContextAttribs withProfileES(boolean profileES) {
+ if ( !(majorVersion == 2 && minorVersion == 0) )
+ throw new IllegalArgumentException("The OpenGL ES profile is only supported on OpenGL version 2.0.");
+
+ return toggleMask(CONTEXT_ES2_PROFILE_BIT_EXT, profileES);
+ }
+
+ private ContextAttribs toggleFlag(int flag, boolean value) {
+ if ( value == hasFlag(flag) )
+ return this;
+
+ ContextAttribs attribs = new ContextAttribs(this);
+ attribs.contextFlags ^= flag; // toggle bit
+ return attribs;
+ }
+
+ /** Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_DEBUG_BIT_ARB} bit in {@link #CONTEXT_FLAGS_ARB} set to the given value. */
+ public ContextAttribs withDebug(boolean debug) { return toggleFlag(CONTEXT_DEBUG_BIT_ARB, debug); }
+
+ /** Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB} bit in {@link #CONTEXT_FLAGS_ARB} set to the given value. */
+ public ContextAttribs withForwardCompatible(boolean forwardCompatible) { return toggleFlag(CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, forwardCompatible); }
+
+ /** Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_ROBUST_ACCESS_BIT_ARB} bit in {@link #CONTEXT_FLAGS_ARB} set to the given value. */
+ public ContextAttribs withRobustAccess(boolean robustAccess) { return toggleFlag(CONTEXT_ROBUST_ACCESS_BIT_ARB, robustAccess); }
+
+ /** Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_RESET_ISOLATION_BIT_ARB} bit in {@link #CONTEXT_FLAGS_ARB} set to the given value. */
+ public ContextAttribs withContextResetIsolation(boolean contextResetIsolation) { return toggleFlag(CONTEXT_RESET_ISOLATION_BIT_ARB, contextResetIsolation); }
+
+ /**
+ * Returns a ContextAttribs instance with {@link #CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB} set to the given strategy. The default context reset notification
+ * strategy is {@link #NO_RESET_NOTIFICATION_ARB}.
+ *
+ * @param strategy the context reset notification strategy. One of: {@link #NO_RESET_NOTIFICATION_ARB}, {@link #LOSE_CONTEXT_ON_RESET_ARB}
+ *
+ * @return the new ContextAttribs
+ */
+ public ContextAttribs withResetNotificationStrategy(int strategy) {
+ if ( strategy == contextResetNotificationStrategy )
+ return this;
+
+ if ( LWJGLUtil.CHECKS && !(strategy == NO_RESET_NOTIFICATION_ARB || strategy == LOSE_CONTEXT_ON_RESET_ARB) )
+ throw new IllegalArgumentException("Invalid context reset notification strategy specified: 0x" + LWJGLUtil.toHexString(strategy));
+
+ ContextAttribs attribs = new ContextAttribs(this);
+ attribs.contextResetNotificationStrategy = strategy;
+ return attribs;
+ }
+
+ /**
+ * Returns a ContextAttribs instance with {@link #CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB} set to {@link #LOSE_CONTEXT_ON_RESET_ARB} if the parameter is
+ * true or to {@link #NO_RESET_NOTIFICATION_ARB} if the parameter is false.
+ *
+ * @param loseContextOnReset the context reset notification strategy
+ *
+ * @return the new ContextAttribs
+ *
+ * @deprecated use {@link #withResetNotificationStrategy} instead
+ */
+ public ContextAttribs withLoseContextOnReset(boolean loseContextOnReset) {
+ return withResetNotificationStrategy(loseContextOnReset ? LOSE_CONTEXT_ON_RESET_ARB : NO_RESET_NOTIFICATION_ARB);
+ }
+
+ /**
+ * Returns a ContextAttribs instance with {@link #CONTEXT_RELEASE_BEHABIOR_ARB} set to the given behavior. The default context release behavior is
+ * {@link #CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB}.
+ *
+ * @param behavior the context release behavior. One of: {@link #CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB}, {@link #CONTEXT_RELEASE_BEHAVIOR_NONE_ARB}
+ *
+ * @return the new ContextAttribs
+ */
+ public ContextAttribs withContextReleaseBehavior(int behavior) {
+ if ( behavior == contextReleaseBehavior )
+ return this;
+
+ if ( LWJGLUtil.CHECKS && !(behavior == CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB || behavior == CONTEXT_RELEASE_BEHAVIOR_NONE_ARB) )
+ throw new IllegalArgumentException("Invalid context release behavior specified: 0x" + LWJGLUtil.toHexString(behavior));
+
+ ContextAttribs attribs = new ContextAttribs(this);
+ attribs.contextReleaseBehavior = behavior;
+ return attribs;
+ }
+
+ /** Returns a new {@code ContextAttribs} instance with {@link #CONTEXT_LAYER_PLANE_ARB} set to the given value. */
+ public ContextAttribs withLayer(int layerPlane) {
+ if ( LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_WINDOWS )
+ throw new IllegalArgumentException("The CONTEXT_LAYER_PLANE_ARB attribute is supported only on the Windows platform.");
+
+ if ( layerPlane == this.layerPlane )
+ return this;
+
if ( layerPlane < 0 )
throw new IllegalArgumentException("Invalid layer plane specified: " + layerPlane);
- if ( layerPlane == this.layerPlane )
- return this;
-
- final ContextAttribs attribs = new ContextAttribs(this);
+ ContextAttribs attribs = new ContextAttribs(this);
attribs.layerPlane = layerPlane;
return attribs;
}
- public ContextAttribs withDebug(final boolean debug) {
- if ( debug == this.debug )
- return this;
-
- final ContextAttribs attribs = new ContextAttribs(this);
- attribs.debug = debug;
- return attribs;
- }
-
- public ContextAttribs withForwardCompatible(final boolean forwardCompatible) {
- if ( forwardCompatible == this.forwardCompatible )
- return this;
-
- final ContextAttribs attribs = new ContextAttribs(this);
- attribs.forwardCompatible = forwardCompatible;
- return attribs;
- }
-
- public ContextAttribs withProfileCore(final boolean profileCore) {
- if ( majorVersion < 3 || (majorVersion == 3 && minorVersion < 2) )
- throw new IllegalArgumentException("Profiles are only supported on OpenGL version 3.2 or higher.");
-
- if ( profileCore == this.profileCore )
- return this;
-
- final ContextAttribs attribs = new ContextAttribs(this);
- attribs.profileCore = profileCore;
- if ( profileCore )
- attribs.profileCompatibility = false;
-
- return attribs;
- }
-
- public ContextAttribs withProfileCompatibility(final boolean profileCompatibility) {
- if ( majorVersion < 3 || (majorVersion == 3 && minorVersion < 2) )
- throw new IllegalArgumentException("Profiles are only supported on OpenGL version 3.2 or higher.");
-
- if ( profileCompatibility == this.profileCompatibility )
- return this;
-
- final ContextAttribs attribs = new ContextAttribs(this);
- attribs.profileCompatibility = profileCompatibility;
- if ( profileCompatibility )
- attribs.profileCore = false;
-
- return attribs;
- }
-
- public ContextAttribs withProfileES(final boolean profileES) {
- if ( !(majorVersion == 2 && minorVersion == 0) )
- throw new IllegalArgumentException("The OpenGL ES profiles is only supported for OpenGL version 2.0.");
-
- if ( profileES == this.profileES )
- return this;
-
- final ContextAttribs attribs = new ContextAttribs(this);
- attribs.profileES = profileES;
-
- return attribs;
- }
-
- /**
- * Returns a ContextAttribs instance with CONTEXT_RESET_NOTIFICATION_STRATEGY set
- * to LOSE_CONTEXT_ON_RESET if the parameter is true or to NO_RESET_NOTIFICATION
- * if the parameter is false.
- *
- * @param loseContextOnReset
- *
- * @return the new ContextAttribs
- */
- public ContextAttribs withLoseContextOnReset(final boolean loseContextOnReset) {
- if ( loseContextOnReset == this.loseContextOnReset )
- return this;
-
- final ContextAttribs attribs = new ContextAttribs(this);
- attribs.loseContextOnReset = loseContextOnReset;
- return attribs;
- }
-
- private static ContextAttribsImplementation getImplementation() {
- switch ( LWJGLUtil.getPlatform() ) {
- case LWJGLUtil.PLATFORM_LINUX:
- return new LinuxContextAttribs();
- case LWJGLUtil.PLATFORM_WINDOWS:
- return new WindowsContextAttribs();
- case LWJGLUtil.PLATFORM_MACOSX:
- return new MacOSXContextAttribs();
- default:
- throw new IllegalStateException("Unsupported platform");
+ IntBuffer getAttribList() {
+ if ( LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_MACOSX )
+ return null;
+
+ LinkedHashMap map = new LinkedHashMap(8);
+
+ if ( !(majorVersion == 1 && minorVersion == 0) ) {
+ map.put(CONTEXT_MAJOR_VERSION_ARB, majorVersion);
+ map.put(CONTEXT_MINOR_VERSION_ARB, minorVersion);
}
- }
-
- IntBuffer getAttribList() {
- ContextAttribsImplementation implementation = getImplementation();
-
- int attribCount = 0;
-
- if ( !(majorVersion == 1 && minorVersion == 0) )
- attribCount += 2;
- if ( 0 < layerPlane )
- attribCount++;
-
- int flags = 0;
- if ( debug )
- flags |= implementation.getDebugBit();
- if ( forwardCompatible )
- flags |= implementation.getForwardCompatibleBit();
- if ( robustAccess )
- flags |= CONTEXT_ROBUST_ACCESS_BIT_ARB;
- if ( 0 < flags )
- attribCount++;
-
- int profileMask = 0;
- if ( profileCore )
- profileMask |= implementation.getProfileCoreBit();
- else if ( profileCompatibility )
- profileMask |= implementation.getProfileCompatibilityBit();
- else if ( profileES )
- profileMask |= CONTEXT_ES2_PROFILE_BIT_EXT;
- if ( 0 < profileMask )
- attribCount++;
-
- if ( attribCount == 0 )
+
+ if ( contextFlags != 0 )
+ map.put(CONTEXT_FLAGS_ARB, contextFlags);
+
+ if ( profileMask != 0 )
+ map.put(CONTEXT_PROFILE_MASK_ARB, profileMask);
+
+ if ( contextResetNotificationStrategy != NO_RESET_NOTIFICATION_ARB )
+ map.put(CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, contextResetNotificationStrategy);
+
+ if ( contextReleaseBehavior != CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB )
+ map.put(CONTEXT_RELEASE_BEHABIOR_ARB, contextReleaseBehavior);
+
+ if ( layerPlane != 0 )
+ map.put(CONTEXT_LAYER_PLANE_ARB, layerPlane);
+
+ if ( map.isEmpty() )
return null;
- final IntBuffer attribs = BufferUtils.createIntBuffer((attribCount * 2) + 1);
-
- if ( !(majorVersion == 1 && minorVersion == 0) ) {
- attribs.put(implementation.getMajorVersionAttrib()).put(majorVersion);
- attribs.put(implementation.getMinorVersionAttrib()).put(minorVersion);
+ IntBuffer attribs = BufferUtils.createIntBuffer((map.size() * 2) + 1);
+ for ( Entry attrib : map.entrySet() ) {
+ attribs
+ .put(attrib.getKey())
+ .put(attrib.getValue());
}
- if ( 0 < layerPlane )
- attribs.put(implementation.getLayerPlaneAttrib()).put(layerPlane);
- if ( 0 < flags )
- attribs.put(implementation.getFlagsAttrib()).put(flags);
- if ( 0 < profileMask )
- attribs.put(implementation.getProfileMaskAttrib()).put(profileMask);
- if ( loseContextOnReset )
- attribs.put(CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB).put(LOSE_CONTEXT_ON_RESET_ARB);
-
attribs.put(0);
attribs.rewind();
return attribs;
@@ -308,19 +438,37 @@
sb.append("ContextAttribs:");
sb.append(" Version=").append(majorVersion).append('.').append(minorVersion);
- sb.append(" - Layer=").append(layerPlane);
- sb.append(" - Debug=").append(debug);
- sb.append(" - ForwardCompatible=").append(forwardCompatible);
- sb.append(" - RobustAccess=").append(robustAccess);
- if ( robustAccess )
- sb.append(" (").append(loseContextOnReset ? "LOSE_CONTEXT_ON_RESET" : "NO_RESET_NOTIFICATION");
- sb.append(" - Profile=");
- if ( profileCore )
- sb.append("Core");
- else if ( profileCompatibility )
- sb.append("Compatibility");
- else
- sb.append("None");
+
+ if ( profileMask != 0 ) {
+ sb.append(", Profile=");
+ if ( hasMask(CONTEXT_CORE_PROFILE_BIT_ARB) )
+ sb.append("CORE");
+ else if ( hasMask(CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) )
+ sb.append("COMPATIBLITY");
+ else if ( hasMask(CONTEXT_ES2_PROFILE_BIT_EXT) )
+ sb.append("ES2");
+ else
+ sb.append("*unknown*");
+ }
+
+ if ( contextFlags != 0 ) {
+ if ( hasFlag(CONTEXT_DEBUG_BIT_ARB) )
+ sb.append(", DEBUG");
+ if ( hasFlag(CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) )
+ sb.append(", FORWARD_COMPATIBLE");
+ if ( hasFlag(CONTEXT_ROBUST_ACCESS_BIT_ARB) )
+ sb.append(", ROBUST_ACCESS");
+ if ( hasFlag(CONTEXT_RESET_ISOLATION_BIT_ARB) )
+ sb.append(", RESET_ISOLATION");
+ }
+
+ if ( contextResetNotificationStrategy != NO_RESET_NOTIFICATION_ARB )
+ sb.append(", LOSE_CONTEXT_ON_RESET");
+ if ( contextReleaseBehavior != CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB )
+ sb.append(", RELEASE_BEHAVIOR_NONE");
+
+ if ( layerPlane != 0 )
+ sb.append(", Layer=").append(layerPlane);
return sb.toString();
}
diff --git a/src/java/org/lwjgl/opengl/ContextAttribsImplementation.java b/src/java/org/lwjgl/opengl/ContextAttribsImplementation.java
deleted file mode 100644
index 44c320d..0000000
--- a/src/java/org/lwjgl/opengl/ContextAttribsImplementation.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2002-2008 LWJGL Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.lwjgl.opengl;
-
-/** @author spasi */
-interface ContextAttribsImplementation {
-
- int getMajorVersionAttrib();
-
- int getMinorVersionAttrib();
-
- int getLayerPlaneAttrib();
-
- int getFlagsAttrib();
-
- int getDebugBit();
-
- int getForwardCompatibleBit();
-
- int getProfileMaskAttrib();
-
- int getProfileCoreBit();
-
- int getProfileCompatibilityBit();
-
-}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/ContextGL.java b/src/java/org/lwjgl/opengl/ContextGL.java
new file mode 100644
index 0000000..b573853
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/ContextGL.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2002-2008 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.PointerBuffer;
+import org.lwjgl.Sys;
+import org.lwjgl.opencl.KHRGLSharing;
+import org.lwjgl.opencl.APPLEGLSharing;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import static org.lwjgl.opengl.GL11.*;
+
+/**
+ *
+ * Context encapsulates an OpenGL context.
+ *
+ *
+ * This class is thread-safe.
+ *
+ * @author elias_naur
+ * @version $Revision$
+ * $Id$
+ */
+final class ContextGL implements Context {
+
+ /** The platform specific implementation of context methods */
+ private static final ContextImplementation implementation;
+
+ /** The current Context */
+ private static final ThreadLocal current_context_local = new ThreadLocal();
+
+ /** Handle to the native GL rendering context */
+ private final ByteBuffer handle;
+ private final PeerInfo peer_info;
+
+ private final ContextAttribs contextAttribs;
+ private final boolean forwardCompatible;
+
+ /** Whether the context has been destroyed */
+ private boolean destroyed;
+
+ private boolean destroy_requested;
+
+ /** The thread that has this context current, or null. */
+ private Thread thread;
+
+ static {
+ Sys.initialize();
+ implementation = createImplementation();
+ }
+
+ private static ContextImplementation createImplementation() {
+ switch ( LWJGLUtil.getPlatform() ) {
+ case LWJGLUtil.PLATFORM_LINUX:
+ return new LinuxContextImplementation();
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ return new WindowsContextImplementation();
+ case LWJGLUtil.PLATFORM_MACOSX:
+ return new MacOSXContextImplementation();
+ default:
+ throw new IllegalStateException("Unsupported platform");
+ }
+ }
+
+ PeerInfo getPeerInfo() {
+ return peer_info;
+ }
+
+ ContextAttribs getContextAttribs() {
+ return contextAttribs;
+ }
+
+ static ContextGL getCurrentContext() {
+ return current_context_local.get();
+ }
+
+ /** Create a context with the specified peer info and shared context */
+ ContextGL(PeerInfo peer_info, ContextAttribs attribs, ContextGL shared_context) throws LWJGLException {
+ ContextGL context_lock = shared_context != null ? shared_context : this;
+ // If shared_context is not null, synchronize on it to make sure it is not deleted
+ // while this context is created. Otherwise, simply synchronize on ourself to avoid NPE
+ synchronized ( context_lock ) {
+ if ( shared_context != null && shared_context.destroyed )
+ throw new IllegalArgumentException("Shared context is destroyed");
+ GLContext.loadOpenGLLibrary();
+ try {
+ this.peer_info = peer_info;
+ this.contextAttribs = attribs;
+
+ IntBuffer attribList;
+ if ( attribs != null ) {
+ attribList = attribs.getAttribList();
+ forwardCompatible = attribs.isForwardCompatible();
+ } else {
+ attribList = null;
+ forwardCompatible = false;
+ }
+
+ this.handle = implementation.create(peer_info, attribList, shared_context != null ? shared_context.handle : null);
+ } catch (LWJGLException e) {
+ GLContext.unloadOpenGLLibrary();
+ throw e;
+ }
+ }
+ }
+
+ /** Release the current context (if any). After this call, no context is current. */
+ public void releaseCurrent() throws LWJGLException {
+ ContextGL current_context = getCurrentContext();
+ if ( current_context != null ) {
+ implementation.releaseCurrentContext();
+ GLContext.useContext(null);
+ current_context_local.set(null);
+ synchronized ( current_context ) {
+ current_context.thread = null;
+ current_context.checkDestroy();
+ }
+ }
+ }
+
+ /**
+ * Release the context from its drawable. This is necessary on some platforms,
+ * like Mac OS X, where binding the context to a drawable and binding the context
+ * for rendering are two distinct actions and where calling releaseDrawable
+ * on every releaseCurrentContext results in artifacts.
+ */
+ public synchronized void releaseDrawable() throws LWJGLException {
+ if ( destroyed )
+ throw new IllegalStateException("Context is destroyed");
+ implementation.releaseDrawable(getHandle());
+ }
+
+ /** Update the context. Should be called whenever it's drawable is moved or resized */
+ public synchronized void update() {
+ if ( destroyed )
+ throw new IllegalStateException("Context is destroyed");
+ implementation.update(getHandle());
+ }
+
+ /** Swap the buffers on the current context. Only valid for double-buffered contexts */
+ public static void swapBuffers() throws LWJGLException {
+ implementation.swapBuffers();
+ }
+
+ private boolean canAccess() {
+ return thread == null || Thread.currentThread() == thread;
+ }
+
+ private void checkAccess() {
+ if ( !canAccess() )
+ throw new IllegalStateException("From thread " + Thread.currentThread() + ": " + thread + " already has the context current");
+ }
+
+ /** Make the context current */
+ public synchronized void makeCurrent() throws LWJGLException {
+ checkAccess();
+ if ( destroyed )
+ throw new IllegalStateException("Context is destroyed");
+ thread = Thread.currentThread();
+ current_context_local.set(this);
+ implementation.makeCurrent(peer_info, handle);
+ GLContext.useContext(this, forwardCompatible);
+ }
+
+ ByteBuffer getHandle() {
+ return handle;
+ }
+
+ /** Query whether the context is current */
+ public synchronized boolean isCurrent() throws LWJGLException {
+ if ( destroyed )
+ throw new IllegalStateException("Context is destroyed");
+ return implementation.isCurrent(handle);
+ }
+
+ private void checkDestroy() {
+ if ( !destroyed && destroy_requested ) {
+ try {
+ releaseDrawable();
+ implementation.destroy(peer_info, handle);
+ CallbackUtil.unregisterCallbacks(this);
+ destroyed = true;
+ thread = null;
+ GLContext.unloadOpenGLLibrary();
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while destroying context: " + e);
+ }
+ }
+ }
+
+ /**
+ * Set the buffer swap interval. This call is a best-attempt at changing
+ * the monitor swap interval, which is the minimum periodicity of color buffer swaps,
+ * measured in video frame periods, and is not guaranteed to be successful.
+ *
+ * A video frame period is the time required to display a full frame of video data.
+ */
+ public static void setSwapInterval(int value) {
+ implementation.setSwapInterval(value);
+ }
+
+ /**
+ * Destroy the context. This method behaves the same as destroy() with the extra
+ * requirement that the context must be either current to the current thread or not
+ * current at all.
+ */
+ public synchronized void forceDestroy() throws LWJGLException {
+ checkAccess();
+ destroy();
+ }
+
+ /**
+ * Request destruction of the Context. If the context is current, no context will be current after this call.
+ * The context is destroyed when no thread has it current.
+ */
+ public synchronized void destroy() throws LWJGLException {
+ if ( destroyed )
+ return;
+ destroy_requested = true;
+ boolean was_current = isCurrent();
+ int error = GL_NO_ERROR;
+ if ( was_current ) {
+ try {
+ // May fail on GLContext.getCapabilities()
+ error = glGetError();
+ } catch (Exception e) {
+ // ignore
+ }
+ releaseCurrent();
+ }
+ checkDestroy();
+ if ( was_current && error != GL_NO_ERROR )
+ throw new OpenGLException(error);
+ }
+
+ public synchronized void setCLSharingProperties(final PointerBuffer properties) throws LWJGLException {
+ final ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ try {
+ switch ( LWJGLUtil.getPlatform() ) {
+ case LWJGLUtil.PLATFORM_WINDOWS:
+ final WindowsContextImplementation implWindows = (WindowsContextImplementation)implementation;
+ properties.put(KHRGLSharing.CL_GL_CONTEXT_KHR).put(implWindows.getHGLRC(handle));
+ properties.put(KHRGLSharing.CL_WGL_HDC_KHR).put(implWindows.getHDC(peer_handle));
+ break;
+ case LWJGLUtil.PLATFORM_LINUX:
+ final LinuxContextImplementation implLinux = (LinuxContextImplementation)implementation;
+ properties.put(KHRGLSharing.CL_GL_CONTEXT_KHR).put(implLinux.getGLXContext(handle));
+ properties.put(KHRGLSharing.CL_GLX_DISPLAY_KHR).put(implLinux.getDisplay(peer_handle));
+ break;
+ case LWJGLUtil.PLATFORM_MACOSX:
+ if (LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 6)) { // only supported on OS X 10.6+
+ // http://oscarbg.blogspot.com/2009/10/about-opencl-opengl-interop.html
+ final MacOSXContextImplementation implMacOSX = (MacOSXContextImplementation)implementation;
+ final long CGLShareGroup = implMacOSX.getCGLShareGroup(handle);
+ properties.put(APPLEGLSharing.CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE).put(CGLShareGroup);
+ break;
+ }
+ default:
+ throw new UnsupportedOperationException("CL/GL context sharing is not supported on this platform.");
+ }
+ } finally {
+ peer_info.unlock();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/ContextGLES.java b/src/java/org/lwjgl/opengl/ContextGLES.java
new file mode 100644
index 0000000..2c4fd08
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/ContextGLES.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2002-2008 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+import org.lwjgl.opengles.EGLContext;
+import org.lwjgl.opengles.GLContext;
+import org.lwjgl.opengles.GLES20;
+import org.lwjgl.opengles.PowerManagementEventException;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/**
+ *
+ * Context encapsulates an OpenGL ES context.
+ *
+ *
+ * This class is thread-safe.
+ *
+ * @author elias_naur
+ * @version $Revision: 3332 $
+ * $Id: Context.java 3332 2010-04-20 18:21:05Z spasi $
+ */
+final class ContextGLES implements org.lwjgl.opengl.Context {
+
+ /** The current Context */
+ private static final ThreadLocal current_context_local = new ThreadLocal();
+
+ /** Handle to the native GL rendering context */
+ private final DrawableGLES drawable;
+ private final EGLContext eglContext;
+
+ private final org.lwjgl.opengles.ContextAttribs contextAttribs;
+
+ /** Whether the context has been destroyed */
+ private boolean destroyed;
+
+ private boolean destroy_requested;
+
+ /** The thread that has this context current, or null. */
+ private Thread thread;
+
+ static {
+ Sys.initialize();
+ }
+
+ public EGLContext getEGLContext() {
+ return eglContext;
+ }
+
+ org.lwjgl.opengles.ContextAttribs getContextAttribs() {
+ return contextAttribs;
+ }
+
+ static ContextGLES getCurrentContext() {
+ return current_context_local.get();
+ }
+
+ /** Create a context with the specified peer info and shared context */
+ ContextGLES(DrawableGLES drawable, org.lwjgl.opengles.ContextAttribs attribs, ContextGLES shared_context) throws LWJGLException {
+ if ( drawable == null )
+ throw new IllegalArgumentException();
+
+ ContextGLES context_lock = shared_context != null ? shared_context : this;
+ // If shared_context is not null, synchronize on it to make sure it is not deleted
+ // while this context is created. Otherwise, simply synchronize on ourself to avoid NPE
+ synchronized ( context_lock ) {
+ if ( shared_context != null && shared_context.destroyed )
+ throw new IllegalArgumentException("Shared context is destroyed");
+
+ this.drawable = drawable;
+ this.contextAttribs = attribs;
+ this.eglContext = drawable.getEGLDisplay().createContext(drawable.getEGLConfig(),
+ shared_context == null ? null : shared_context.eglContext,
+ attribs == null ? new org.lwjgl.opengles.ContextAttribs(2).getAttribList() : attribs.getAttribList());
+ }
+ }
+
+ /** Release the current context (if any). After this call, no context is current. */
+ public void releaseCurrent() throws LWJGLException, PowerManagementEventException {
+ eglReleaseCurrent(drawable.getEGLDisplay());
+ org.lwjgl.opengles.GLContext.useContext(null);
+ current_context_local.set(null);
+
+ synchronized ( this ) {
+ thread = null;
+ checkDestroy();
+ }
+ }
+
+ /** Swap the buffers on the current context. Only valid for double-buffered contexts */
+ public static void swapBuffers() throws LWJGLException, PowerManagementEventException {
+ ContextGLES current_context = getCurrentContext();
+ if ( current_context != null )
+ current_context.drawable.getEGLSurface().swapBuffers();
+ }
+
+ private boolean canAccess() {
+ return thread == null || Thread.currentThread() == thread;
+ }
+
+ private void checkAccess() {
+ if ( !canAccess() )
+ throw new IllegalStateException("From thread " + Thread.currentThread() + ": " + thread + " already has the context current");
+ }
+
+ /** Make the context current */
+ public synchronized void makeCurrent() throws LWJGLException, PowerManagementEventException {
+ checkAccess();
+ if ( destroyed )
+ throw new IllegalStateException("Context is destroyed");
+ thread = Thread.currentThread();
+ current_context_local.set(this);
+ eglContext.makeCurrent(drawable.getEGLSurface());
+ org.lwjgl.opengles.GLContext.useContext(this);
+ }
+
+ /** Query whether the context is current */
+ public synchronized boolean isCurrent() throws LWJGLException {
+ if ( destroyed )
+ throw new IllegalStateException("Context is destroyed");
+ return eglIsCurrentContext(eglContext);
+ }
+
+ private void checkDestroy() {
+ if ( !destroyed && destroy_requested ) {
+ try {
+ eglContext.destroy();
+ destroyed = true;
+ thread = null;
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while destroying context: " + e);
+ }
+ }
+ }
+
+ /**
+ * Set the buffer swap interval. This call is a best-attempt at changing
+ * the monitor swap interval, which is the minimum periodicity of color buffer swaps,
+ * measured in video frame periods, and is not guaranteed to be successful.
+ *
+ * A video frame period is the time required to display a full frame of video data.
+ */
+ public static void setSwapInterval(int value) {
+ ContextGLES current_context = getCurrentContext();
+ if ( current_context != null ) {
+ try {
+ current_context.drawable.getEGLDisplay().setSwapInterval(value);
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to set swap interval. Reason: " + e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Destroy the context. This method behaves the same as destroy() with the extra
+ * requirement that the context must be either current to the current thread or not
+ * current at all.
+ */
+ public synchronized void forceDestroy() throws LWJGLException {
+ checkAccess();
+ destroy();
+ }
+
+ /**
+ * Request destruction of the Context. If the context is current, no context will be current after this call.
+ * The context is destroyed when no thread has it current.
+ */
+ public synchronized void destroy() throws LWJGLException {
+ if ( destroyed )
+ return;
+ destroy_requested = true;
+ boolean was_current = isCurrent();
+ int error = GLES20.GL_NO_ERROR;
+ if ( was_current ) {
+ if ( org.lwjgl.opengles.GLContext.getCapabilities() != null && GLContext.getCapabilities().OpenGLES20 )
+ error = GLES20.glGetError();
+
+ try {
+ releaseCurrent();
+ } catch (PowerManagementEventException e) {
+ // Ignore
+ }
+ }
+ checkDestroy();
+ if ( was_current && error != GLES20.GL_NO_ERROR )
+ throw new OpenGLException(error);
+ }
+
+ public void releaseDrawable() throws LWJGLException {
+ }
+
+}
diff --git a/src/java/org/lwjgl/opengl/ContextImplementation.java b/src/java/org/lwjgl/opengl/ContextImplementation.java
index c0234e0..62a828d 100644
--- a/src/java/org/lwjgl/opengl/ContextImplementation.java
+++ b/src/java/org/lwjgl/opengl/ContextImplementation.java
@@ -42,8 +42,8 @@
*
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: ContextImplementation.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
interface ContextImplementation {
/**
diff --git a/src/java/org/lwjgl/opengl/Display.java b/src/java/org/lwjgl/opengl/Display.java
index 8ec43a8..066f4f1 100644
--- a/src/java/org/lwjgl/opengl/Display.java
+++ b/src/java/org/lwjgl/opengl/Display.java
@@ -62,8 +62,6 @@
import java.util.Arrays;
import java.util.HashSet;
-import static org.lwjgl.opengl.GL11.*;
-
public final class Display {
private static final Thread shutdown_hook = new Thread() {
@@ -84,9 +82,6 @@
/** The current display mode, if created */
private static DisplayMode current_mode;
- /** Timer for sync() */
- private static long timeThen;
-
/** X coordinate of the window */
private static int x = -1;
@@ -99,6 +94,12 @@
*/
private static int y = -1;
+ /** the width of the Display window */
+ private static int width = 0;
+
+ /** the height of the Display window */
+ private static int height = 0;
+
/** Title of the window (never null) */
private static String title = "Game";
@@ -109,11 +110,15 @@
private static int swap_interval;
/** The Drawable instance that tracks the current Display context */
- private static final AbstractDrawable drawable;
+ private static DrawableLWJGL drawable;
private static boolean window_created;
private static boolean parent_resized;
+
+ private static boolean window_resized;
+
+ private static boolean window_resizable;
/** Initial Background Color of Display */
private static float r, g, b;
@@ -134,22 +139,6 @@
LWJGLUtil.log("Initial mode: " + initial_mode);
} catch (LWJGLException e) {
throw new RuntimeException(e);
- }
- drawable = new AbstractDrawable() {
- public void destroy() {
- synchronized ( GlobalLock.lock ) {
- if ( !isCreated() )
- return;
-
- releaseDrawable();
- super.destroy();
- destroyWindow();
- x = y = -1;
- cached_icons = null;
- reset();
- removeShutdownHook();
- }
- }
};
}
@@ -256,7 +245,7 @@
try {
if ( was_fullscreen && !isFullscreen() )
display_impl.resetDisplayMode();
- else if ( isFullscreen() )
+ else if ( isFullscreen() )
switchDisplayMode();
createWindow();
makeCurrentAndSetSwapInterval();
@@ -314,8 +303,11 @@
tmp_parent.addComponentListener(component_listener);
}
DisplayMode mode = getEffectiveMode();
- display_impl.createWindow(mode, tmp_parent, getWindowX(), getWindowY());
+ display_impl.createWindow(drawable, mode, tmp_parent, getWindowX(), getWindowY());
window_created = true;
+
+ width = Display.getDisplayMode().getWidth();
+ height = Display.getDisplayMode().getHeight();
setTitle(title);
initControls();
@@ -330,9 +322,9 @@
private static void releaseDrawable() {
try {
- Context context = drawable.context;
+ Context context = drawable.getContext();
if ( context != null && context.isCurrent() ) {
- Context.releaseCurrentContext();
+ context.releaseCurrent();
context.releaseDrawable();
}
} catch (LWJGLException e) {
@@ -409,40 +401,14 @@
}
}
- private static long timeLate;
-
- /**
- * Best sync method that works reliably.
- *
- * @param fps The desired frame rate, in frames per second
+ /**
+ * An accurate sync method that will attempt to run at a constant frame rate.
+ * It should be called once every frame.
+ *
+ * @param fps - the desired frame rate, in frames per second
*/
public static void sync(int fps) {
- long timeNow;
- long gapTo;
- long savedTimeLate;
- synchronized ( GlobalLock.lock ) {
- gapTo = Sys.getTimerResolution() / fps + timeThen;
- timeNow = Sys.getTime();
- savedTimeLate = timeLate;
- }
-
- try {
- while ( gapTo > timeNow + savedTimeLate ) {
- Thread.sleep(1);
- timeNow = Sys.getTime();
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
-
- synchronized ( GlobalLock.lock ) {
- if ( gapTo < timeNow )
- timeLate = timeNow - gapTo;
- else
- timeLate = 0;
-
- timeThen = timeNow;
- }
+ Sync.sync(fps);
}
/** @return the title of the window */
@@ -648,8 +614,8 @@
throw new IllegalStateException("Display not created");
if ( LWJGLUtil.DEBUG )
- Util.checkGLError();
- Context.swapBuffers();
+ drawable.checkGLError();
+ drawable.swapBuffers();
}
}
@@ -683,9 +649,17 @@
}
}
+ window_resized = !isFullscreen() && parent == null && display_impl.wasResized();
+
+ if ( window_resized ) {
+ width = display_impl.getWidth();
+ height = display_impl.getHeight();
+ }
+
if ( parent_resized ) {
reshape();
parent_resized = false;
+ window_resized = true;
}
if ( processMessages )
@@ -762,9 +736,7 @@
* @throws LWJGLException
*/
public static void create() throws LWJGLException {
- synchronized ( GlobalLock.lock ) {
- create(new PixelFormat());
- }
+ create(new PixelFormat());
}
/**
@@ -782,7 +754,7 @@
*/
public static void create(PixelFormat pixel_format) throws LWJGLException {
synchronized ( GlobalLock.lock ) {
- create(pixel_format, null, null);
+ create(pixel_format, null, (ContextAttribs)null);
}
}
@@ -802,7 +774,7 @@
*/
public static void create(PixelFormat pixel_format, Drawable shared_drawable) throws LWJGLException {
synchronized ( GlobalLock.lock ) {
- create(pixel_format, shared_drawable, null);
+ create(pixel_format, shared_drawable, (ContextAttribs)null);
}
}
@@ -851,12 +823,31 @@
registerShutdownHook();
if ( isFullscreen() )
switchDisplayMode();
+
+ final DrawableGL drawable = new DrawableGL() {
+ public void destroy() {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ return;
+
+ releaseDrawable();
+ super.destroy();
+ destroyWindow();
+ x = y = -1;
+ cached_icons = null;
+ reset();
+ removeShutdownHook();
+ }
+ }
+ };
+ Display.drawable = drawable;
+
try {
- drawable.peer_info = display_impl.createPeerInfo(pixel_format);
+ drawable.setPixelFormat(pixel_format, attribs);
try {
createWindow();
try {
- drawable.context = new Context(drawable.peer_info, attribs, shared_drawable != null ? ((AbstractDrawable)shared_drawable).getContext() : null);
+ drawable.context = new ContextGL(drawable.peer_info, attribs, shared_drawable != null ? ((DrawableGL)shared_drawable).getContext() : null);
try {
makeCurrentAndSetSwapInterval();
initContext();
@@ -880,6 +871,143 @@
}
/**
+ * Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed
+ * context are not supported on the platform, the display mode will be switched to the mode returned by
+ * getDisplayMode(), and a fullscreen context will be created. If isFullscreen() is false, a windowed context
+ * will be created with the dimensions given in the mode returned by getDisplayMode(). If a context can't be
+ * created with the given parameters, a LWJGLException will be thrown.
+ *
+ * The window created will be set up in orthographic 2D projection, with 1:1 pixel ratio with GL coordinates.
+ *
+ * @param pixel_format Describes the minimum specifications the context must fulfill. Must be an instance of org.lwjgl.opengles.PixelFormat.
+ *
+ * @throws LWJGLException
+ */
+
+ public static void create(PixelFormatLWJGL pixel_format) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ create(pixel_format, null, null);
+ }
+ }
+
+ /**
+ * Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed
+ * context are not supported on the platform, the display mode will be switched to the mode returned by
+ * getDisplayMode(), and a fullscreen context will be created. If isFullscreen() is false, a windowed context
+ * will be created with the dimensions given in the mode returned by getDisplayMode(). If a context can't be
+ * created with the given parameters, a LWJGLException will be thrown.
+ *
+ * The window created will be set up in orthographic 2D projection, with 1:1 pixel ratio with GL coordinates.
+ *
+ * @param pixel_format Describes the minimum specifications the context must fulfill. Must be an instance of org.lwjgl.opengles.PixelFormat.
+ * @param shared_drawable The Drawable to share context with. (optional, may be null)
+ *
+ * @throws LWJGLException
+ */
+ public static void create(PixelFormatLWJGL pixel_format, Drawable shared_drawable) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ create(pixel_format, shared_drawable, null);
+ }
+ }
+
+ /**
+ * Create the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed
+ * context are not supported on the platform, the display mode will be switched to the mode returned by
+ * getDisplayMode(), and a fullscreen context will be created. If isFullscreen() is false, a windowed context
+ * will be created with the dimensions given in the mode returned by getDisplayMode(). If a context can't be
+ * created with the given parameters, a LWJGLException will be thrown.
+ *
+ * The window created will be set up in orthographic 2D projection, with 1:1 pixel ratio with GL coordinates.
+ *
+ * @param pixel_format Describes the minimum specifications the context must fulfill. Must be an instance of org.lwjgl.opengles.PixelFormat.
+ * @param attribs The ContextAttribs to use when creating the context. (optional, may be null)
+ *
+ * @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 the OpenGL ES context with the given minimum parameters. If isFullscreen() is true or if windowed
+ * context are not supported on the platform, the display mode will be switched to the mode returned by
+ * getDisplayMode(), and a fullscreen context will be created. If isFullscreen() is false, a windowed context
+ * will be created with the dimensions given in the mode returned by getDisplayMode(). If a context can't be
+ * created with the given parameters, a LWJGLException will be thrown.
+ *
+ * The window created will be set up in orthographic 2D projection, with 1:1 pixel ratio with GL coordinates.
+ *
+ * @param pixel_format Describes the minimum specifications the context must fulfill. Must be an instance of org.lwjgl.opengles.PixelFormat.
+ * @param shared_drawable The Drawable to share context with. (optional, may be null)
+ * @param attribs The ContextAttribs to use when creating the context. (optional, may be null)
+ *
+ * @throws LWJGLException
+ */
+ public static void create(PixelFormatLWJGL pixel_format, Drawable shared_drawable, org.lwjgl.opengles.ContextAttribs attribs) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if ( isCreated() )
+ throw new IllegalStateException("Only one LWJGL context may be instantiated at any one time.");
+ if ( pixel_format == null )
+ throw new NullPointerException("pixel_format cannot be null");
+ removeShutdownHook();
+ registerShutdownHook();
+ if ( isFullscreen() )
+ switchDisplayMode();
+
+ final DrawableGLES drawable = new DrawableGLES() {
+
+ public void setPixelFormat(final PixelFormatLWJGL pf, final ContextAttribs attribs) throws LWJGLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void destroy() {
+ synchronized ( GlobalLock.lock ) {
+ if ( !isCreated() )
+ return;
+
+ releaseDrawable();
+ super.destroy();
+ destroyWindow();
+ x = y = -1;
+ cached_icons = null;
+ reset();
+ removeShutdownHook();
+ }
+ }
+ };
+ Display.drawable = drawable;
+
+ try {
+ drawable.setPixelFormat(pixel_format);
+ try {
+ createWindow();
+ try {
+ drawable.createContext(attribs, shared_drawable);
+ try {
+ makeCurrentAndSetSwapInterval();
+ initContext();
+ } catch (LWJGLException e) {
+ drawable.destroy();
+ throw e;
+ }
+ } catch (LWJGLException e) {
+ destroyWindow();
+ throw e;
+ }
+ } catch (LWJGLException e) {
+ drawable.destroy();
+ throw e;
+ }
+ } catch (LWJGLException e) {
+ display_impl.resetDisplayMode();
+ throw e;
+ }
+ }
+ }
+
+ /**
* Set the initial color of the Display. This method is called before the Display is created and will set the
* background color to the one specified in this method.
*
@@ -896,7 +1024,7 @@
private static void makeCurrentAndSetSwapInterval() throws LWJGLException {
makeCurrent();
try {
- Util.checkGLError();
+ drawable.checkGLError();
} catch (OpenGLException e) {
LWJGLUtil.log("OpenGL error during context creation: " + e.getMessage());
}
@@ -904,10 +1032,7 @@
}
private static void initContext() {
- // set background clear color
- glClearColor(r, g, b, 0.0f);
- // Clear window to avoid the desktop "showing through"
- glClear(GL_COLOR_BUFFER_BIT);
+ drawable.initContext(r, g, b);
update();
}
@@ -920,6 +1045,15 @@
return AccessController.doPrivileged(new PrivilegedAction() {
public Boolean run() {
return Boolean.getBoolean(property_name);
+ }
+ });
+ }
+
+ /** Gets a string property as a privileged action. */
+ static String getPrivilegedString(final String property_name) {
+ return AccessController.doPrivileged(new PrivilegedAction() {
+ public String run() {
+ return System.getProperty(property_name);
}
});
}
@@ -957,7 +1091,9 @@
* regardless of whether the Display was the current rendering context.
*/
public static void destroy() {
- drawable.destroy();
+ if(isCreated()) {
+ drawable.destroy();
+ }
}
/*
@@ -990,7 +1126,8 @@
synchronized ( GlobalLock.lock ) {
swap_interval = value;
if ( isCreated() )
- Context.setSwapInterval(swap_interval);
+ drawable.setSwapInterval(swap_interval);
+
}
}
@@ -1065,7 +1202,7 @@
* Linux (and similar platforms) expect one 32x32 icon.
* Mac OS X should be supplied one 128x128 icon
*
- * The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions nescesarry for the specific platform.
+ * The implementation will use the supplied ByteBuffers with image data in RGBA (size must be a power of two) and perform any conversions nescesarry for the specific platform.
*
* NOTE: The display will make a deep copy of the supplied byte buffer array, for the purpose
* of recreating the icons when you go back and forth fullscreen mode. You therefore only need to
@@ -1097,4 +1234,142 @@
}
}
}
+
+ /**
+ * Enable or disable the Display window to be resized.
+ *
+ * @param resizable set to true to make the Display window resizable;
+ * false to disable resizing on the Display window.
+ */
+ public static void setResizable(boolean resizable) {
+ window_resizable = resizable;
+ if ( isCreated() ) {
+ display_impl.setResizable(resizable);
+ }
+ }
+
+ /**
+ * @return true if the Display window is resizable.
+ */
+ public static boolean isResizable() {
+ return window_resizable;
+ }
+
+ /**
+ * @return true if the Display window has been resized.
+ * This value will be updated after a call to Display.update().
+ *
+ * This will return false if running in fullscreen or with Display.setParent(Canvas parent)
+ */
+ public static boolean wasResized() {
+ return window_resized;
+ }
+
+ /**
+ * @return this method will return the x position (top-left) of the Display window.
+ *
+ * If running in fullscreen mode it will return 0.
+ * If Display.setParent(Canvas parent) is being used, the x position of
+ * the parent will be returned.
+ */
+ public static int getX() {
+
+ if (Display.isFullscreen()) {
+ return 0;
+ }
+
+ if (parent != null) {
+ return parent.getX();
+ }
+
+ return display_impl.getX();
+ }
+
+ /**
+ * @return this method will return the y position (top-left) of the Display window.
+ *
+ * If running in fullscreen mode it will return 0.
+ * If Display.setParent(Canvas parent) is being used, the y position of
+ * the parent will be returned.
+ */
+ public static int getY() {
+
+ if (Display.isFullscreen()) {
+ return 0;
+ }
+
+ if (parent != null) {
+ return parent.getY();
+ }
+
+ return display_impl.getY();
+ }
+
+ /**
+ * @return this method will return the width of the Display window.
+ *
+ * If running in fullscreen mode it will return the width of the current set DisplayMode.
+ * If Display.setParent(Canvas parent) is being used, the width of the parent
+ * will be returned.
+ *
+ * This value will be updated after a call to Display.update().
+ */
+ public static int getWidth() {
+
+ if (Display.isFullscreen()) {
+ return Display.getDisplayMode().getWidth();
+ }
+
+ if (parent != null) {
+ return parent.getWidth();
+ }
+
+ return width;
+ }
+
+ /**
+ * @return this method will return the height of the Display window.
+ *
+ * If running in fullscreen mode it will return the height of the current set DisplayMode.
+ * If Display.setParent(Canvas parent) is being used, the height of the parent
+ * will be returned.
+ *
+ * This value will be updated after a call to Display.update().
+ */
+ public static int getHeight() {
+
+ if (Display.isFullscreen()) {
+ return Display.getDisplayMode().getHeight();
+ }
+
+ if (parent != null) {
+ return parent.getHeight();
+ }
+
+ return height;
+ }
+
+ /**
+ * @return this method will return the pixel scale factor of the Display window.
+ *
+ * This method should be used when running in high DPI mode. In such modes Operating
+ * Systems will scale the Display window to avoid the window shrinking due to high
+ * resolutions. The OpenGL frame buffer will however use the higher resolution and
+ * not be scaled to match the Display window size.
+ *
+ * OpenGL methods that require pixel dependent values e.g. glViewport, glTexImage2D,
+ * glReadPixels, glScissor, glLineWidth, glRenderbufferStorage, etc can convert the
+ * scaled Display and Mouse coordinates to the correct high resolution value by
+ * multiplying them by the pixel scale factor.
+ *
+ * e.g. Display.getWidth() * Display.getPixelScaleFactor() will return the high DPI
+ * width of the OpenGL frame buffer. Whereas Display.getWidth() will be the same as
+ * the OpenGL frame buffer in non high DPI mode.
+ *
+ * Where high DPI mode is not available this method will just return 1.0f therefore
+ * not have any effect on values that are multiplied by it.
+ */
+ public static float getPixelScaleFactor() {
+ return display_impl.getPixelScaleFactor();
+ }
}
diff --git a/src/java/org/lwjgl/opengl/DisplayImplementation.java b/src/java/org/lwjgl/opengl/DisplayImplementation.java
index fb5505e..7f76555 100644
--- a/src/java/org/lwjgl/opengl/DisplayImplementation.java
+++ b/src/java/org/lwjgl/opengl/DisplayImplementation.java
@@ -47,7 +47,7 @@
interface DisplayImplementation extends InputImplementation {
- void createWindow(DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException;
+ void createWindow(DrawableLWJGL drawable, DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException;
void destroyWindow();
@@ -108,7 +108,7 @@
* Create the native PeerInfo.
* @throws LWJGLException
*/
- PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException;
+ PeerInfo createPeerInfo(PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException;
// void destroyPeerInfo();
@@ -136,7 +136,7 @@
/**
* Method to create a Pbuffer
*/
- PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format,
+ PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, ContextAttribs attribs,
IntBuffer pixelFormatCaps,
IntBuffer pBufferAttribs) throws LWJGLException;
@@ -159,4 +159,42 @@
* @return number of icons used.
*/
int setIcon(ByteBuffer[] icons);
+
+ /**
+ * Enable or disable the Display window to be resized.
+ *
+ * @param resizable set to true to make the Display window resizable;
+ * false to disable resizing on the Display window.
+ */
+ void setResizable(boolean resizable);
+
+ /**
+ * @return true if the Display window has been resized since this method was last called.
+ */
+ boolean wasResized();
+
+ /**
+ * @return this method will return the width of the Display window.
+ */
+ int getWidth();
+
+ /**
+ * @return this method will return the height of the Display window.
+ */
+ int getHeight();
+
+ /**
+ * @return this method will return the top-left x position of the Display window.
+ */
+ int getX();
+
+ /**
+ * @return this method will return the top-left y position of the Display window.
+ */
+ int getY();
+
+ /**
+ * @return this method will return the pixel scale factor of the Display window useful for high resolution modes.
+ */
+ float getPixelScaleFactor();
}
diff --git a/src/java/org/lwjgl/opengl/DisplayMode.java b/src/java/org/lwjgl/opengl/DisplayMode.java
index a6e6fb7..23bd84a 100644
--- a/src/java/org/lwjgl/opengl/DisplayMode.java
+++ b/src/java/org/lwjgl/opengl/DisplayMode.java
@@ -38,8 +38,8 @@
* getAvailableDisplayModes() method.
*
* @author cix_foo
- * @version $Revision: 3418 $
- * $Id: DisplayMode.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
public final class DisplayMode {
@@ -75,7 +75,7 @@
this.fullscreen = fullscreen;
}
- /** True iff this instance can be used for fullscreen modes */
+ /** True if this instance can be used for fullscreen modes */
public boolean isFullscreenCapable() {
return fullscreen;
}
diff --git a/src/java/org/lwjgl/opengl/DrawableGL.java b/src/java/org/lwjgl/opengl/DrawableGL.java
new file mode 100644
index 0000000..b1b767c
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/DrawableGL.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.PointerBuffer;
+
+import static org.lwjgl.opengl.GL11.*;
+
+/** @author Spasi */
+abstract class DrawableGL implements DrawableLWJGL {
+
+ /** The PixelFormat used to create the drawable. */
+ protected PixelFormat pixel_format;
+
+ /** Handle to the native GL rendering context */
+ protected PeerInfo peer_info;
+
+ /** The OpenGL Context. */
+ protected ContextGL context;
+
+ protected DrawableGL() {
+ }
+
+ public void setPixelFormat(final PixelFormatLWJGL pf) throws LWJGLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setPixelFormat(final PixelFormatLWJGL pf, final ContextAttribs attribs) throws LWJGLException {
+ this.pixel_format = (PixelFormat)pf;
+ this.peer_info = Display.getImplementation().createPeerInfo(pixel_format, attribs);
+ }
+
+ public PixelFormatLWJGL getPixelFormat() {
+ return pixel_format;
+ }
+
+ public ContextGL getContext() {
+ synchronized ( GlobalLock.lock ) {
+ return context;
+ }
+ }
+
+ public ContextGL createSharedContext() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ return new ContextGL(peer_info, context.getContextAttribs(), context);
+ }
+ }
+
+ public void checkGLError() {
+ Util.checkGLError();
+ }
+
+ public void setSwapInterval(final int swap_interval) {
+ ContextGL.setSwapInterval(swap_interval);
+ }
+
+ public void swapBuffers() throws LWJGLException {
+ ContextGL.swapBuffers();
+ }
+
+ public void initContext(final float r, final float g, final float b) {
+ // set background clear color
+ glClearColor(r, g, b, 0.0f);
+ // Clear window to avoid the desktop "showing through"
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ public boolean isCurrent() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ return context.isCurrent();
+ }
+ }
+
+ public void makeCurrent() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ context.makeCurrent();
+ }
+ }
+
+ public void releaseContext() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ if ( context.isCurrent() )
+ context.releaseCurrent();
+ }
+ }
+
+ public void destroy() {
+ synchronized ( GlobalLock.lock ) {
+ if ( context == null )
+ return;
+
+ try {
+ releaseContext();
+
+ context.forceDestroy();
+ context = null;
+
+ if ( peer_info != null ) {
+ peer_info.destroy();
+ peer_info = null;
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while destroying Drawable: " + e);
+ }
+ }
+ }
+
+ public void setCLSharingProperties(final PointerBuffer properties) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ context.setCLSharingProperties(properties);
+ }
+ }
+
+ protected final void checkDestroyed() {
+ if ( context == null )
+ throw new IllegalStateException("The Drawable has no context available.");
+ }
+
+}
diff --git a/src/java/org/lwjgl/opengl/DrawableGLES.java b/src/java/org/lwjgl/opengl/DrawableGLES.java
new file mode 100644
index 0000000..1b29e7a
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/DrawableGLES.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.PointerBuffer;
+import org.lwjgl.opengles.ContextAttribs;
+import org.lwjgl.opengles.*;
+import org.lwjgl.opengles.Util;
+
+import static org.lwjgl.opengles.EGL.*;
+import static org.lwjgl.opengles.GLES20.*;
+
+/**
+ * @author Spasi
+ * @since 14/5/2011
+ */
+abstract class DrawableGLES implements DrawableLWJGL {
+
+ /** The PixelFormat used to create the EGLDisplay. */
+ protected org.lwjgl.opengles.PixelFormat pixel_format;
+
+ protected EGLDisplay eglDisplay;
+ protected EGLConfig eglConfig;
+ protected EGLSurface eglSurface;
+
+ /** The OpenGL Context. */
+ protected ContextGLES context;
+
+ /** The Drawable that shares objects with this Drawable. */
+ protected Drawable shared_drawable;
+
+ protected DrawableGLES() {
+ }
+
+ public void setPixelFormat(final PixelFormatLWJGL pf) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ this.pixel_format = (org.lwjgl.opengles.PixelFormat)pf;
+ }
+ }
+
+ public PixelFormatLWJGL getPixelFormat() {
+ synchronized ( GlobalLock.lock ) {
+ return pixel_format;
+ }
+ }
+
+ public void initialize(final long window, final long display_id, final int eglSurfaceType, final org.lwjgl.opengles.PixelFormat pf) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ if ( eglSurface != null ) {
+ eglSurface.destroy();
+ eglSurface = null;
+ }
+
+ if ( eglDisplay != null ) {
+ eglDisplay.terminate();
+ eglDisplay = null;
+ }
+
+ final EGLDisplay eglDisplay = eglGetDisplay((int)display_id);
+
+ int[] attribs = {
+ EGL_LEVEL, 0,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NATIVE_RENDERABLE, EGL_FALSE,
+ };
+
+ final EGLConfig[] configs = eglDisplay.chooseConfig(pf.getAttribBuffer(eglDisplay, eglSurfaceType, attribs), null, BufferUtils.createIntBuffer(1));
+ if ( configs.length == 0 )
+ throw new LWJGLException("No EGLConfigs found for the specified PixelFormat.");
+
+ final EGLConfig eglConfig = pf.getBestMatch(configs);
+ final EGLSurface eglSurface = eglDisplay.createWindowSurface(eglConfig, window, null);
+ pf.setSurfaceAttribs(eglSurface);
+
+ this.eglDisplay = eglDisplay;
+ this.eglConfig = eglConfig;
+ this.eglSurface = eglSurface;
+
+ // This can happen when switching in and out of full-screen mode.
+ if ( context != null )
+ context.getEGLContext().setDisplay(eglDisplay);
+ }
+ }
+
+ public void createContext(final ContextAttribs attribs, final Drawable shared_drawable) throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ this.context = new ContextGLES(this, attribs, shared_drawable != null ? ((DrawableGLES)shared_drawable).getContext() : null);
+ this.shared_drawable = shared_drawable;
+ }
+ }
+
+ Drawable getSharedDrawable() {
+ synchronized ( GlobalLock.lock ) {
+ return shared_drawable;
+ }
+ }
+
+ public EGLDisplay getEGLDisplay() {
+ synchronized ( GlobalLock.lock ) {
+ return eglDisplay;
+ }
+ }
+
+ public EGLConfig getEGLConfig() {
+ synchronized ( GlobalLock.lock ) {
+ return eglConfig;
+ }
+ }
+
+ public EGLSurface getEGLSurface() {
+ synchronized ( GlobalLock.lock ) {
+ return eglSurface;
+ }
+ }
+
+ public ContextGLES getContext() {
+ synchronized ( GlobalLock.lock ) {
+ return context;
+ }
+ }
+
+ public org.lwjgl.opengl.Context createSharedContext() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ return new ContextGLES(this, context.getContextAttribs(), context);
+ }
+ }
+
+ public void checkGLError() {
+ Util.checkGLError();
+ }
+
+ public void setSwapInterval(final int swap_interval) {
+ ContextGLES.setSwapInterval(swap_interval);
+ }
+
+ public void swapBuffers() throws LWJGLException {
+ ContextGLES.swapBuffers();
+ }
+
+ public void initContext(final float r, final float g, final float b) {
+ // set background clear color
+ glClearColor(r, g, b, 0.0f);
+ // Clear window to avoid the desktop "showing through"
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ public boolean isCurrent() throws LWJGLException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ return context.isCurrent();
+ }
+ }
+
+ public void makeCurrent() throws LWJGLException, PowerManagementEventException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ context.makeCurrent();
+ }
+ }
+
+ public void releaseContext() throws LWJGLException, PowerManagementEventException {
+ synchronized ( GlobalLock.lock ) {
+ checkDestroyed();
+ if ( context.isCurrent() )
+ context.releaseCurrent();
+ }
+ }
+
+ public void destroy() {
+ synchronized ( GlobalLock.lock ) {
+ try {
+ if ( context != null ) {
+ try {
+ releaseContext();
+ } catch (PowerManagementEventException e) {
+ // Ignore
+ }
+
+ context.forceDestroy();
+ context = null;
+ }
+
+ if ( eglSurface != null ) {
+ eglSurface.destroy();
+ eglSurface = null;
+ }
+
+ if ( eglDisplay != null ) {
+ eglDisplay.terminate();
+ eglDisplay = null;
+ }
+
+ pixel_format = null;
+ shared_drawable = null;
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Exception occurred while destroying Drawable: " + e);
+ }
+ }
+ }
+
+ protected void checkDestroyed() {
+ if ( context == null )
+ throw new IllegalStateException("The Drawable has no context available.");
+ }
+
+ public void setCLSharingProperties(final PointerBuffer properties) throws LWJGLException {
+ throw new UnsupportedOperationException();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/DrawableLWJGL.java b/src/java/org/lwjgl/opengl/DrawableLWJGL.java
index b79c806..e4d989d 100644
--- a/src/java/org/lwjgl/opengl/DrawableLWJGL.java
+++ b/src/java/org/lwjgl/opengl/DrawableLWJGL.java
@@ -1,11 +1,50 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
package org.lwjgl.opengl;
import org.lwjgl.LWJGLException;
/**
+ * [INTERNAL USE ONLY]
+ *
* @author Spasi
*/
interface DrawableLWJGL extends Drawable {
+
+ void setPixelFormat(PixelFormatLWJGL pf) throws LWJGLException;
+
+ void setPixelFormat(PixelFormatLWJGL pf, ContextAttribs attribs) throws LWJGLException;
+
+ PixelFormatLWJGL getPixelFormat();
/**
* [INTERNAL USE ONLY] Returns the Drawable's Context.
@@ -21,4 +60,12 @@
*/
Context createSharedContext() throws LWJGLException;
-}
+ void checkGLError();
+
+ void setSwapInterval(int swap_interval);
+
+ void swapBuffers() throws LWJGLException;
+
+ void initContext(final float r, final float g, final float b);
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/GLChecks.java b/src/java/org/lwjgl/opengl/GLChecks.java
index d0aeff3..f9596a6 100644
--- a/src/java/org/lwjgl/opengl/GLChecks.java
+++ b/src/java/org/lwjgl/opengl/GLChecks.java
@@ -31,10 +31,11 @@
*/
package org.lwjgl.opengl;
-import java.nio.Buffer;
-
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLUtil;
+
+import java.nio.Buffer;
+import java.nio.FloatBuffer;
import static org.lwjgl.opengl.ARBBufferObject.*;
import static org.lwjgl.opengl.ATIVertexArrayObject.*;
@@ -43,6 +44,7 @@
import static org.lwjgl.opengl.EXTDirectStateAccess.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
+import static org.lwjgl.opengl.NVPathRendering.*;
/**
* A class to check buffer boundaries in GL methods. Many GL
@@ -54,8 +56,8 @@
* Thrown by the debug build library of the LWJGL if any OpenGL operation causes an error.
*
* @author cix_foo
- * @version $Revision: 3459 $
- * $Id: GLChecks.java 3459 2010-11-29 17:21:05Z spasi $
+ * @version $Revision$
+ * $Id$
*/
class GLChecks {
@@ -63,43 +65,27 @@
private GLChecks() {
}
- static int getBufferObjectSize(ContextCapabilities caps, int buffer_enum) {
- return glGetBufferParameter(buffer_enum, GL_BUFFER_SIZE);
- }
-
- static int getBufferObjectSizeARB(ContextCapabilities caps, int buffer_enum) {
- return glGetBufferParameterARB(buffer_enum, GL_BUFFER_SIZE_ARB);
- }
-
- static int getBufferObjectSizeATI(ContextCapabilities caps, int buffer) {
- return glGetObjectBufferATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI);
- }
-
- static int getNamedBufferObjectSize(ContextCapabilities caps, int buffer) {
- return glGetNamedBufferParameterEXT(buffer, GL_BUFFER_SIZE);
- }
-
/** Helper method to ensure that array buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
static void ensureArrayVBOdisabled(ContextCapabilities caps) {
- if( LWJGLUtil.CHECKS && StateTracker.getReferences(caps).arrayBuffer != 0 )
+ if ( LWJGLUtil.CHECKS && StateTracker.getReferences(caps).arrayBuffer != 0 )
throw new OpenGLException("Cannot use Buffers when Array Buffer Object is enabled");
}
/** Helper method to ensure that array buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
static void ensureArrayVBOenabled(ContextCapabilities caps) {
- if( LWJGLUtil.CHECKS && StateTracker.getReferences(caps).arrayBuffer == 0 )
+ if ( LWJGLUtil.CHECKS && StateTracker.getReferences(caps).arrayBuffer == 0 )
throw new OpenGLException("Cannot use offsets when Array Buffer Object is disabled");
}
/** Helper method to ensure that element array buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
static void ensureElementVBOdisabled(ContextCapabilities caps) {
- if( LWJGLUtil.CHECKS && StateTracker.getElementArrayBufferBound(caps) != 0 )
+ if ( LWJGLUtil.CHECKS && StateTracker.getElementArrayBufferBound(caps) != 0 )
throw new OpenGLException("Cannot use Buffers when Element Array Buffer Object is enabled");
}
/** Helper method to ensure that element array buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
static void ensureElementVBOenabled(ContextCapabilities caps) {
- if( LWJGLUtil.CHECKS && StateTracker.getElementArrayBufferBound(caps) == 0 )
+ if ( LWJGLUtil.CHECKS && StateTracker.getElementArrayBufferBound(caps) == 0 )
throw new OpenGLException("Cannot use offsets when Element Array Buffer Object is disabled");
}
@@ -209,10 +195,10 @@
case GL_FLOAT:
bpe = 4;
break;
- default :
+ default:
// TODO: Add more types (like the GL12 types GL_UNSIGNED_INT_8_8_8_8
return 0;
- // throw new IllegalArgumentException("Unknown type " + type);
+ // throw new IllegalArgumentException("Unknown type " + type);
}
int epp;
switch ( format ) {
@@ -233,7 +219,7 @@
case GL_BGRA_EXT:
epp = 4;
break;
- default :
+ default:
// TODO: Add more formats. Assuming 4 is too wasteful on buffer sizes where e.g. 1 is enough (like GL_DEPTH_COMPONENT)
return 0;
/* // Assume 4 elements per pixel
@@ -242,4 +228,116 @@
return bpe * epp;
}
-}
+
+ // NV_path_rendering checks
+
+ static int calculateBytesPerCharCode(int type) {
+ switch ( type ) {
+ case GL_UNSIGNED_BYTE:
+ case GL_UTF8_NV:
+ return 1;
+ case GL_UNSIGNED_SHORT:
+ case GL_2_BYTES:
+ case GL_UTF16_NV:
+ return 2;
+ case GL_3_BYTES:
+ return 3;
+ case GL_4_BYTES:
+ return 4;
+ default:
+ throw new IllegalArgumentException("Unsupported charcode type: " + type);
+ }
+ }
+
+ static int calculateBytesPerPathName(int pathNameType) {
+ switch ( pathNameType ) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_UTF8_NV:
+ return 1;
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_2_BYTES:
+ case GL_UTF16_NV:
+ return 2;
+ case GL_3_BYTES:
+ return 3;
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ case GL_4_BYTES:
+ return 4;
+ default:
+ throw new IllegalArgumentException("Unsupported path name type: " + pathNameType);
+ }
+ }
+
+ static int calculateTransformPathValues(int transformType) {
+ switch ( transformType ) {
+ case GL_NONE:
+ return 0;
+ case GL_TRANSLATE_X_NV:
+ case GL_TRANSLATE_Y_NV:
+ return 1;
+ case GL_TRANSLATE_2D_NV:
+ return 2;
+ case GL_TRANSLATE_3D_NV:
+ return 3;
+ case GL_AFFINE_2D_NV:
+ case GL_TRANSPOSE_AFFINE_2D_NV:
+ return 6;
+ case GL_AFFINE_3D_NV:
+ case GL_TRANSPOSE_AFFINE_3D_NV:
+ return 12;
+ default:
+ throw new IllegalArgumentException("Unsupported transform type: " + transformType);
+ }
+ }
+
+ static int calculatePathColorGenCoeffsCount(int genMode, int colorFormat) {
+ final int coeffsPerComponent = calculatePathGenCoeffsPerComponent(genMode);
+
+ switch ( colorFormat ) {
+ case GL_RGB:
+ return 3 * coeffsPerComponent;
+ case GL_RGBA:
+ return 4 * coeffsPerComponent;
+ default:
+ return coeffsPerComponent;
+ }
+ }
+
+ static int calculatePathTextGenCoeffsPerComponent(FloatBuffer coeffs, int genMode) {
+ if ( genMode == GL_NONE )
+ return 0;
+
+ return coeffs.remaining() / calculatePathGenCoeffsPerComponent(genMode);
+ }
+
+ private static int calculatePathGenCoeffsPerComponent(int genMode) {
+ switch ( genMode ) {
+ case GL_NONE:
+ return 0;
+ case GL_OBJECT_LINEAR:
+ case GL_PATH_OBJECT_BOUNDING_BOX_NV:
+ return 3;
+ case GL_EYE_LINEAR:
+ return 4;
+ default:
+ throw new IllegalArgumentException("Unsupported gen mode: " + genMode);
+ }
+ }
+
+ static int calculateMetricsSize(int metricQueryMask, int stride) {
+ if ( LWJGLUtil.DEBUG && (stride < 0 || (stride % 4) != 0) )
+ throw new IllegalArgumentException("Invalid stride value: " + stride);
+
+ final int metrics = Integer.bitCount(metricQueryMask);
+
+ if ( LWJGLUtil.DEBUG && (stride >> 2) < metrics )
+ throw new IllegalArgumentException("The queried metrics do not fit in the specified stride: " + stride);
+
+ return stride == 0 ? metrics : (stride >> 2);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/GLContext.java b/src/java/org/lwjgl/opengl/GLContext.java
index 897a869..69f665b 100644
--- a/src/java/org/lwjgl/opengl/GLContext.java
+++ b/src/java/org/lwjgl/opengl/GLContext.java
@@ -33,9 +33,11 @@
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
+import org.lwjgl.MemoryUtil;
import org.lwjgl.Sys;
import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
@@ -56,8 +58,8 @@
* That way, multiple threads can have multiple contexts current and render to them concurrently.
*
* @author elias_naur
- * @version $Revision: 3418 $
- * $Id: GLContext.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
public final class GLContext {
@@ -117,6 +119,14 @@
* @return The current capabilities instance.
*/
public static ContextCapabilities getCapabilities() {
+ ContextCapabilities caps = getCapabilitiesImpl();
+ if ( caps == null )
+ throw new RuntimeException("No OpenGL context found in the current thread.");
+
+ return caps;
+ }
+
+ private static ContextCapabilities getCapabilitiesImpl() {
CapabilitiesCacheEntry recent_cache_entry = fast_path_cache;
// Check owner of cache entry
if ( recent_cache_entry.owner == Thread.currentThread() ) {
@@ -126,6 +136,17 @@
return recent_cache_entry.capabilities;
} else // Some other thread has written to the cache since, and we fall back to the slower path
return getThreadLocalCapabilities();
+ }
+
+ /**
+ * Returns the capabilities instance associated with the specified context object.
+ *
+ * @param context the context object
+ *
+ * @return the capabilities instance
+ */
+ static ContextCapabilities getCapabilities(Object context) {
+ return capability_cache.get(context);
}
private static ContextCapabilities getThreadLocalCapabilities() {
@@ -187,8 +208,12 @@
return 0;
}
- /** Helper method to get a pointer to a named function in the OpenGL library */
- static native long getFunctionAddress(String name);
+ /** Helper method to get a pointer to a named function in the OpenGL library. */
+ static long getFunctionAddress(String name) {
+ ByteBuffer buffer = MemoryUtil.encodeASCII(name);
+ return ngetFunctionAddress(MemoryUtil.getAddress(buffer));
+ }
+ private static native long ngetFunctionAddress(long name);
/**
* Determine which extensions are available and returns the context profile mask. Helper method to ContextCapabilities.
@@ -218,10 +243,10 @@
}
final int[][] GL_VERSIONS = {
- { 1, 2, 3, 4, 5 }, // OpenGL 1
- { 0, 1 }, // OpenGL 2
- { 0, 1, 2, 3 }, // OpenGL 3
- { 0, 1 }, // OpenGL 4
+ { 1, 2, 3, 4, 5 }, // OpenGL 1
+ { 0, 1 }, // OpenGL 2
+ { 0, 1, 2, 3 }, // OpenGL 3
+ { 0, 1, 2, 3, 4, 5 }, // OpenGL 4
};
for ( int major = 1; major <= GL_VERSIONS.length; major++ ) {
diff --git a/src/java/org/lwjgl/opengl/GLUConstants.java b/src/java/org/lwjgl/opengl/GLUConstants.java
index 356e6a5..ac93f9e 100644
--- a/src/java/org/lwjgl/opengl/GLUConstants.java
+++ b/src/java/org/lwjgl/opengl/GLUConstants.java
@@ -38,8 +38,8 @@
* GLU constants.
*
* @author cix_foo
- * @version $Revision: 3418 $
- * $Id: GLUConstants.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
public interface GLUConstants {
diff --git a/src/java/org/lwjgl/opengl/InputImplementation.java b/src/java/org/lwjgl/opengl/InputImplementation.java
index 3f7de2c..1d5cdfb 100644
--- a/src/java/org/lwjgl/opengl/InputImplementation.java
+++ b/src/java/org/lwjgl/opengl/InputImplementation.java
@@ -69,7 +69,7 @@
void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons);
/**
- * Method to read the keyboard buffer
+ * Method to read the mouse buffer
*/
void readMouse(ByteBuffer buffer);
diff --git a/src/java/org/lwjgl/opengl/KHRDebugCallback.java b/src/java/org/lwjgl/opengl/KHRDebugCallback.java
new file mode 100644
index 0000000..fd3a03e
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/KHRDebugCallback.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2002-2008 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+import org.lwjgl.PointerWrapperAbstract;
+
+/**
+ * Instances of this class are needed to use the callback functionality of the KHR_debug extension.
+ * Users of this class may provide implementations of the {@code Handler} interface to receive notifications.
+ * The same {@code Handler} instance may be used by different contexts but it is not recommended.
+ * Handler notifications are synchronized.
+ *
+ * @author Spasi
+ */
+public final class KHRDebugCallback extends PointerWrapperAbstract {
+
+ /** Severity levels. */
+ private static final int
+ GL_DEBUG_SEVERITY_HIGH = 0x9146,
+ GL_DEBUG_SEVERITY_MEDIUM = 0x9147,
+ GL_DEBUG_SEVERITY_LOW = 0x9148,
+ GL_DEBUG_SEVERITY_NOTIFICATION = 0x826B;
+
+ /** Sources. */
+ private static final int
+ GL_DEBUG_SOURCE_API = 0x8246,
+ GL_DEBUG_SOURCE_WINDOW_SYSTEM = 0x8247,
+ GL_DEBUG_SOURCE_SHADER_COMPILER = 0x8248,
+ GL_DEBUG_SOURCE_THIRD_PARTY = 0x8249,
+ GL_DEBUG_SOURCE_APPLICATION = 0x824A,
+ GL_DEBUG_SOURCE_OTHER = 0x824B;
+
+ /** Types. */
+ private static final int
+ GL_DEBUG_TYPE_ERROR = 0x824C,
+ GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR = 0x824D,
+ GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR = 0x824E,
+ GL_DEBUG_TYPE_PORTABILITY = 0x824F,
+ GL_DEBUG_TYPE_PERFORMANCE = 0x8250,
+ GL_DEBUG_TYPE_OTHER = 0x8251,
+ GL_DEBUG_TYPE_MARKER = 0x8268;
+
+ private static final long CALLBACK_POINTER;
+
+ static {
+ long pointer = 0;
+ try {
+ // Call reflectively so that we can compile this class for the Generator.
+ pointer = (Long)Class.forName("org.lwjgl.opengl.CallbackUtil").getDeclaredMethod("getDebugCallbackKHR").invoke(null);
+ } catch (Exception e) {
+ // ignore
+ }
+ CALLBACK_POINTER = pointer;
+ }
+
+ private final Handler handler;
+
+ /**
+ * Creates an KHRebugCallback with a default callback handler.
+ * The default handler will simply print the message on System.err.
+ */
+ public KHRDebugCallback() {
+ this(new Handler() {
+ public void handleMessage(final int source, final int type, final int id, final int severity, final String message) {
+ System.err.println("[LWJGL] KHR_debug message");
+ System.err.println("\tID: " + id);
+
+ String description;
+ switch ( source ) {
+ case GL_DEBUG_SOURCE_API:
+ description = "API";
+ break;
+ case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ description = "WINDOW SYSTEM";
+ break;
+ case GL_DEBUG_SOURCE_SHADER_COMPILER:
+ description = "SHADER COMPILER";
+ break;
+ case GL_DEBUG_SOURCE_THIRD_PARTY:
+ description = "THIRD PARTY";
+ break;
+ case GL_DEBUG_SOURCE_APPLICATION:
+ description = "APPLICATION";
+ break;
+ case GL_DEBUG_SOURCE_OTHER:
+ description = "OTHER";
+ break;
+ default:
+ description = printUnknownToken(source);
+ }
+ System.err.println("\tSource: " + description);
+
+ switch ( type ) {
+ case GL_DEBUG_TYPE_ERROR:
+ description = "ERROR";
+ break;
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ description = "DEPRECATED BEHAVIOR";
+ break;
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ description = "UNDEFINED BEHAVIOR";
+ break;
+ case GL_DEBUG_TYPE_PORTABILITY:
+ description = "PORTABILITY";
+ break;
+ case GL_DEBUG_TYPE_PERFORMANCE:
+ description = "PERFORMANCE";
+ break;
+ case GL_DEBUG_TYPE_OTHER:
+ description = "OTHER";
+ break;
+ case GL_DEBUG_TYPE_MARKER:
+ description = "MARKER";
+ break;
+ default:
+ description = printUnknownToken(type);
+ }
+ System.err.println("\tType: " + description);
+
+ switch ( severity ) {
+ case GL_DEBUG_SEVERITY_HIGH:
+ description = "HIGH";
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ description = "MEDIUM";
+ break;
+ case GL_DEBUG_SEVERITY_LOW:
+ description = "LOW";
+ break;
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ description = "NOTIFICATION";
+ break;
+ default:
+ description = printUnknownToken(severity);
+ }
+ System.err.println("\tSeverity: " + description);
+
+ System.err.println("\tMessage: " + message);
+ }
+
+ private String printUnknownToken(final int token) {
+ return "Unknown (0x" + Integer.toHexString(token).toUpperCase() + ")";
+ }
+ });
+ }
+
+ /**
+ * Creates an ARBDebugOutputCallback with the specified callback handler.
+ * The handler's {@code handleMessage} method will be called whenever
+ * debug output is generated by the GL.
+ *
+ * @param handler the callback handler
+ */
+ public KHRDebugCallback(final Handler handler) {
+ super(CALLBACK_POINTER);
+
+ this.handler = handler;
+ }
+
+ Handler getHandler() {
+ return handler;
+ }
+
+ /** Implementations of this interface can be used to receive ARB_debug_output notifications. */
+ public interface Handler {
+
+ /**
+ * This method will be called when an ARB_debug_output message is generated.
+ *
+ * @param source the message source
+ * @param type the message type
+ * @param id the message ID
+ * @param severity the message severity
+ * @param message the string representation of the message.
+ */
+ void handleMessage(int source, int type, int id, int severity, String message);
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java
index f49d0eb..b7267c1 100644
--- a/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java
@@ -40,8 +40,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: LinuxAWTGLCanvasPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class LinuxAWTGLCanvasPeerInfo extends LinuxPeerInfo {
private final Canvas component;
diff --git a/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java b/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java
index 4b068bc..e84d400 100644
--- a/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java
+++ b/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java
@@ -44,8 +44,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3418 $
- * $Id: LinuxCanvasImplementation.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class LinuxCanvasImplementation implements AWTCanvasImplementation {
static int getScreenFromDevice(final GraphicsDevice device) throws LWJGLException {
@@ -76,7 +76,7 @@
}
}
- public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
+ public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException {
return new LinuxAWTGLCanvasPeerInfo(component);
}
diff --git a/src/java/org/lwjgl/opengl/LinuxContextAttribs.java b/src/java/org/lwjgl/opengl/LinuxContextAttribs.java
deleted file mode 100644
index d8fa015..0000000
--- a/src/java/org/lwjgl/opengl/LinuxContextAttribs.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2002-2008 LWJGL Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.lwjgl.opengl;
-
-/**
- * An implementation of ContextAttribs using GLX_create_context.
- *
- * ---- WIP - GLX_create_context has not been defined yet ----
- *
- * @author spasi
- */
-final class LinuxContextAttribs implements ContextAttribsImplementation {
-
- private static final int GLX_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
- private static final int GLX_CONTEXT_MINOR_VERSION_ARB = 0x2092;
- private static final int GLX_CONTEXT_LAYER_PLANE_ARB = 0x2093;
- private static final int GLX_CONTEXT_FLAGS_ARB = 0x2094;
- private static final int GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126;
-
- private static final int GLX_CONTEXT_DEBUG_BIT_ARB = 0x0001;
- private static final int GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002;
-
- private static final int GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
- private static final int GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
-
- LinuxContextAttribs() {
- }
-
- public int getMajorVersionAttrib() {
- return GLX_CONTEXT_MAJOR_VERSION_ARB;
- }
-
- public int getMinorVersionAttrib() {
- return GLX_CONTEXT_MINOR_VERSION_ARB;
- }
-
- public int getLayerPlaneAttrib() {
- return GLX_CONTEXT_LAYER_PLANE_ARB;
- }
-
- public int getFlagsAttrib() {
- return GLX_CONTEXT_FLAGS_ARB;
- }
-
- public int getDebugBit() {
- return GLX_CONTEXT_DEBUG_BIT_ARB;
- }
-
- public int getForwardCompatibleBit() {
- return GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
- }
-
- public int getProfileMaskAttrib() {
- return GLX_CONTEXT_PROFILE_MASK_ARB;
- }
-
- public int getProfileCoreBit() {
- return GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
- }
-
- public int getProfileCompatibilityBit() {
- return GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
- }
-
-}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/LinuxContextImplementation.java b/src/java/org/lwjgl/opengl/LinuxContextImplementation.java
index 4ad98be..0b244fc 100644
--- a/src/java/org/lwjgl/opengl/LinuxContextImplementation.java
+++ b/src/java/org/lwjgl/opengl/LinuxContextImplementation.java
@@ -38,8 +38,8 @@
/**
* @author elias_naur
- * @version $Revision: 3412 $
- * $Id: LinuxContextImplementation.java 3412 2010-09-26 23:43:24Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class LinuxContextImplementation implements ContextImplementation {
@@ -67,7 +67,7 @@
}
public void swapBuffers() throws LWJGLException {
- Context current_context = Context.getCurrentContext();
+ ContextGL current_context = ContextGL.getCurrentContext();
if ( current_context == null )
throw new IllegalStateException("No context is current");
synchronized ( current_context ) {
@@ -89,7 +89,7 @@
private static native void nSwapBuffers(ByteBuffer peer_info_handle) throws LWJGLException;
public void releaseCurrentContext() throws LWJGLException {
- Context current_context = Context.getCurrentContext();
+ ContextGL current_context = ContextGL.getCurrentContext();
if ( current_context == null )
throw new IllegalStateException("No context is current");
synchronized ( current_context ) {
@@ -142,17 +142,30 @@
private static native boolean nIsCurrent(ByteBuffer context_handle) throws LWJGLException;
public void setSwapInterval(int value) {
- Context current_context = Context.getCurrentContext();
+ ContextGL current_context = ContextGL.getCurrentContext();
+ PeerInfo peer_info = current_context.getPeerInfo();
+
if ( current_context == null )
throw new IllegalStateException("No context is current");
synchronized ( current_context ) {
LinuxDisplay.lockAWT();
- nSetSwapInterval(current_context.getHandle(), value);
- LinuxDisplay.unlockAWT();
+ try {
+ ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ try {
+ nSetSwapInterval(peer_handle, current_context.getHandle(), value);
+ } finally {
+ peer_info.unlock();
+ }
+ } catch (LWJGLException e) {
+ // API CHANGE - this methods should throw LWJGLException
+ e.printStackTrace();
+ } finally {
+ LinuxDisplay.unlockAWT();
+ }
}
}
- private static native void nSetSwapInterval(ByteBuffer context_handle, int value);
+ private static native void nSetSwapInterval(ByteBuffer peer_handle, ByteBuffer context_handle, int value);
public void destroy(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException {
LinuxDisplay.lockAWT();
diff --git a/src/java/org/lwjgl/opengl/LinuxDisplay.java b/src/java/org/lwjgl/opengl/LinuxDisplay.java
index 2795538..3ce738a 100644
--- a/src/java/org/lwjgl/opengl/LinuxDisplay.java
+++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java
@@ -39,17 +39,24 @@
*/
import java.awt.Canvas;
+import java.awt.event.FocusListener;
+import java.awt.event.FocusEvent;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
+import java.lang.reflect.InvocationTargetException;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
+import org.lwjgl.MemoryUtil;
import org.lwjgl.opengl.XRandR.Screen;
+import org.lwjgl.opengles.EGL;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -79,6 +86,8 @@
private static final int SetModeInsert = 0;
private static final int SaveSetRoot = 1;
private static final int SaveSetUnmap = 1;
+
+ private static final int X_SetInputFocus = 42;
/** Window mode enum */
private static final int FULLSCREEN_LEGACY = 1;
@@ -120,7 +129,6 @@
private DisplayMode saved_mode;
private DisplayMode current_mode;
- private Screen[] savedXrandrConfig;
private boolean keyboard_grabbed;
private boolean pointer_grabbed;
@@ -132,14 +140,42 @@
private boolean close_requested;
private long current_cursor;
private long blank_cursor;
+ private boolean mouseInside = true;
+ private boolean resizable;
+ private boolean resized;
+
+ private int window_x;
+ private int window_y;
+ private int window_width;
+ private int window_height;
+
private Canvas parent;
private long parent_window;
- private boolean xembedded;
- private boolean parent_focus;
- private boolean mouseInside = true;
-
+ private static boolean xembedded;
+ private long parent_proxy_focus_window;
+ private boolean parent_focused;
+ private boolean parent_focus_changed;
+ private long last_window_focus = 0;
+
private LinuxKeyboard keyboard;
private LinuxMouse mouse;
+
+ private String wm_class;
+
+ private final FocusListener focus_listener = new FocusListener() {
+ public void focusGained(FocusEvent e) {
+ synchronized (GlobalLock.lock) {
+ parent_focused = true;
+ parent_focus_changed = true;
+ }
+ }
+ public void focusLost(FocusEvent e) {
+ synchronized (GlobalLock.lock) {
+ parent_focused = false;
+ parent_focus_changed = true;
+ }
+ }
+ };
private static ByteBuffer getCurrentGammaRamp() throws LWJGLException {
lockAWT();
@@ -259,7 +295,12 @@
*/
static void incDisplay() throws LWJGLException {
if (display_connection_usage_count == 0) {
- GLContext.loadOpenGLLibrary();
+ try {
+ // TODO: Can we know if we're on desktop or ES?
+ GLContext.loadOpenGLLibrary();
+ org.lwjgl.opengles.GLContext.loadOpenGLLibrary();
+ } catch (Throwable t) {
+ }
saved_error_handler = setErrorHandler();
display = openDisplay();
// synchronize(display, true);
@@ -272,6 +313,8 @@
private static native void synchronize(long display, boolean synchronize);
private static int globalErrorHandler(long display, long event_ptr, long error_display, long serial, long error_code, long request_code, long minor_code) throws LWJGLException {
+ if (xembedded && request_code == X_SetInputFocus) return 0; // ignore X error in xembeded mode to fix a browser issue when dragging or switching tabs
+
if (display == getDisplay()) {
String error_msg = getErrorText(display, error_code);
throw new LWJGLException("X Error - disp: 0x" + Long.toHexString(error_display) + " serial: " + serial + " error: " + error_msg + " request_code: " + request_code + " minor_code: " + minor_code);
@@ -408,26 +451,54 @@
ungrabKeyboard();
}
- public void createWindow(DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
+ public void createWindow(final DrawableLWJGL drawable, DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
lockAWT();
try {
incDisplay();
try {
+ if ( drawable instanceof DrawableGLES )
+ peer_info = new LinuxDisplayPeerInfo();
+
ByteBuffer handle = peer_info.lockAndGetHandle();
try {
current_window_mode = getWindowMode(Display.isFullscreen());
+
// Try to enable Lecagy FullScreen Support in Compiz, else
// we may have trouble with stuff overlapping our fullscreen window.
if ( current_window_mode != WINDOWED )
Compiz.setLegacyFullscreenSupport(true);
+
// Setting _MOTIF_WM_HINTS in fullscreen mode is problematic for certain window
// managers. We do not set MWM_HINTS_DECORATIONS in fullscreen mode anymore,
// unless org.lwjgl.opengl.Window.undecorated_fs has been specified.
// See native/linux/org_lwjgl_opengl_Display.c, createWindow function.
boolean undecorated = Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated") || (current_window_mode != WINDOWED && Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated_fs"));
+
this.parent = parent;
parent_window = parent != null ? getHandle(parent) : getRootWindow(getDisplay(), getDefaultScreen());
- current_window = nCreateWindow(getDisplay(), getDefaultScreen(), handle, mode, current_window_mode, x, y, undecorated, parent_window);
+ resizable = Display.isResizable();
+ resized = false;
+ window_x = x;
+ window_y = y;
+ window_width = mode.getWidth();
+ window_height = mode.getHeight();
+
+ // overwrite arguments x and y - superclass always uses 0,0 for fullscreen windows
+ // use the coordinates of XRandRs primary screen instead
+ // this is required to let the fullscreen window appear on the primary screen
+ if (mode.isFullscreenCapable() && current_displaymode_extension == XRANDR) {
+ Screen primaryScreen = XRandR.DisplayModetoScreen(Display.getDisplayMode());
+ x = primaryScreen.xPos;
+ y = primaryScreen.yPos;
+ }
+
+ current_window = nCreateWindow(getDisplay(), getDefaultScreen(), handle, mode, current_window_mode, x, y, undecorated, parent_window, resizable);
+
+ // Set the WM_CLASS hint which is needed by some WM's e.g. Gnome Shell
+ wm_class = Display.getPrivilegedString("LWJGL_WM_CLASS");
+ if (wm_class == null) wm_class = Display.getTitle();
+ setClassHint(Display.getTitle(), wm_class);
+
mapRaised(getDisplay(), current_window);
xembedded = parent != null && isAncestorXEmbedded(parent_window);
blank_cursor = createBlankCursor();
@@ -440,6 +511,15 @@
grab = false;
minimized = false;
dirty = true;
+
+ if ( drawable instanceof DrawableGLES )
+ ((DrawableGLES)drawable).initialize(current_window, getDisplay(), EGL.EGL_WINDOW_BIT, (org.lwjgl.opengles.PixelFormat)drawable.getPixelFormat());
+
+ if (parent != null) {
+ parent.addFocusListener(focus_listener);
+ parent_focused = parent.isFocusOwner();
+ parent_focus_changed = true;
+ }
} finally {
peer_info.unlock();
}
@@ -451,12 +531,20 @@
unlockAWT();
}
}
- private static native long nCreateWindow(long display, int screen, ByteBuffer peer_info_handle, DisplayMode mode, int window_mode, int x, int y, boolean undecorated, long parent_handle) throws LWJGLException;
+ private static native long nCreateWindow(long display, int screen, ByteBuffer peer_info_handle, DisplayMode mode, int window_mode, int x, int y, boolean undecorated, long parent_handle, boolean resizable) throws LWJGLException;
private static native long getRootWindow(long display, int screen);
private static native boolean hasProperty(long display, long window, long property);
private static native long getParentWindow(long display, long window) throws LWJGLException;
+ private static native int getChildCount(long display, long window) throws LWJGLException;
private static native void mapRaised(long display, long window);
private static native void reparentWindow(long display, long window, long parent, int x, int y);
+ private static native long nGetInputFocus(long display) throws LWJGLException;
+ private static native void nSetInputFocus(long display, long window, long time);
+ private static native void nSetWindowSize(long display, long window, int width, int height, boolean resizable);
+ private static native int nGetX(long display, long window);
+ private static native int nGetY(long display, long window);
+ private static native int nGetWidth(long display, long window);
+ private static native int nGetHeight(long display, long window);
private static boolean isAncestorXEmbedded(long window) throws LWJGLException {
long xembed_atom = internAtom("_XEMBED_INFO", true);
@@ -473,7 +561,7 @@
private static long getHandle(Canvas parent) throws LWJGLException {
AWTCanvasImplementation awt_impl = AWTGLCanvas.createImplementation();
- LinuxPeerInfo parent_peer_info = (LinuxPeerInfo)awt_impl.createPeerInfo(parent, null);
+ LinuxPeerInfo parent_peer_info = (LinuxPeerInfo)awt_impl.createPeerInfo(parent, null, null);
ByteBuffer parent_peer_info_handle = parent_peer_info.lockAndGetHandle();
try {
return parent_peer_info.getDrawable();
@@ -490,6 +578,9 @@
public void destroyWindow() {
lockAWT();
try {
+ if (parent != null) {
+ parent.removeFocusListener(focus_listener);
+ }
try {
setNativeCursor(null);
} catch (LWJGLException e) {
@@ -520,12 +611,17 @@
}
private void switchDisplayModeOnTmpDisplay(DisplayMode mode) throws LWJGLException {
- incDisplay();
- try {
- nSwitchDisplayMode(getDisplay(), getDefaultScreen(), current_displaymode_extension, mode);
- } finally {
- decDisplay();
- }
+ if (current_displaymode_extension == XRANDR) {
+ // let Xrandr set the display mode
+ XRandR.setConfiguration(false, XRandR.DisplayModetoScreen(mode));
+ } else {
+ incDisplay();
+ try {
+ nSwitchDisplayMode(getDisplay(), getDefaultScreen(), current_displaymode_extension, mode);
+ } finally {
+ decDisplay();
+ }
+ }
}
private static native void nSwitchDisplayMode(long display, int screen, int extension, DisplayMode mode) throws LWJGLException;
@@ -542,11 +638,11 @@
public void resetDisplayMode() {
lockAWT();
try {
- if( current_displaymode_extension == XRANDR && savedXrandrConfig.length > 0 )
+ if( current_displaymode_extension == XRANDR )
{
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
- XRandR.setConfiguration( savedXrandrConfig );
+ XRandR.restoreConfiguration();
return null;
}
});
@@ -644,12 +740,12 @@
throw new LWJGLException("No modes available");
switch (current_displaymode_extension) {
case XRANDR:
- savedXrandrConfig = AccessController.doPrivileged(new PrivilegedAction() {
- public Screen[] run() {
- return XRandR.getConfiguration();
+ saved_mode = AccessController.doPrivileged(new PrivilegedAction() {
+ public DisplayMode run() {
+ XRandR.saveConfiguration();
+ return XRandR.ScreentoDisplayMode(XRandR.getConfiguration());
}
});
- saved_mode = getCurrentXRandrMode();
break;
case XF86VIDMODE:
saved_mode = modes[0];
@@ -686,12 +782,27 @@
public void setTitle(String title) {
lockAWT();
try {
- nSetTitle(getDisplay(), getWindow(), title);
- } finally {
- unlockAWT();
- }
- }
- private static native void nSetTitle(long display, long window, String title);
+ final ByteBuffer titleText = MemoryUtil.encodeUTF8(title);
+ nSetTitle(getDisplay(), getWindow(), MemoryUtil.getAddress(titleText), titleText.remaining() - 1);
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native void nSetTitle(long display, long window, long title, int len);
+
+ /** the WM_CLASS hint is needed by some WM's e.g. gnome shell */
+ private void setClassHint(String wm_name, String wm_class) {
+ lockAWT();
+ try {
+ final ByteBuffer nameText = MemoryUtil.encodeUTF8(wm_name);
+ final ByteBuffer classText = MemoryUtil.encodeUTF8(wm_class);
+
+ nSetClassHint(getDisplay(), getWindow(), MemoryUtil.getAddress(nameText), MemoryUtil.getAddress(classText));
+ } finally {
+ unlockAWT();
+ }
+ }
+ private static native void nSetClassHint(long display, long window, long wm_name, long wm_class);
public boolean isCloseRequested() {
boolean result = close_requested;
@@ -713,12 +824,10 @@
return result;
}
- public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException {
+ public PeerInfo createPeerInfo(PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException {
peer_info = new LinuxDisplayPeerInfo(pixel_format);
return peer_info;
}
-
- static native void setInputFocus(long display, long window, long time);
private void relayEventToParent(LinuxEvent event_buffer, int event_mask) {
tmp_event_buffer.copyFrom(event_buffer);
@@ -737,10 +846,10 @@
relayEventToParent(event_buffer, KeyPressMask);
break;
case LinuxEvent.ButtonPress:
- relayEventToParent(event_buffer, KeyPressMask);
+ if (xembedded || !focused) relayEventToParent(event_buffer, KeyPressMask);
break;
case LinuxEvent.ButtonRelease:
- relayEventToParent(event_buffer, KeyPressMask);
+ if (xembedded || !focused) relayEventToParent(event_buffer, KeyPressMask);
break;
default:
break;
@@ -778,6 +887,23 @@
case LinuxEvent.Expose:
dirty = true;
break;
+ case LinuxEvent.ConfigureNotify:
+ int x = nGetX(getDisplay(), getWindow());
+ int y = nGetY(getDisplay(), getWindow());
+
+ int width = nGetWidth(getDisplay(), getWindow());
+ int height = nGetHeight(getDisplay(), getWindow());
+
+ window_x = x;
+ window_y = y;
+
+ if (window_width != width || window_height != height) {
+ resized = true;
+ window_width = width;
+ window_height = height;
+ }
+
+ break;
case LinuxEvent.EnterNotify:
mouseInside = true;
break;
@@ -813,13 +939,29 @@
public DisplayMode[] getAvailableDisplayModes() throws LWJGLException {
lockAWT();
try {
- incDisplay();
- try {
- DisplayMode[] modes = nGetAvailableDisplayModes(getDisplay(), getDefaultScreen(), current_displaymode_extension);
- return modes;
- } finally {
- decDisplay();
- }
+ incDisplay();
+ if (current_displaymode_extension == XRANDR) {
+ // nGetAvailableDisplayModes cannot be trusted. Use it only for bitsPerPixel
+ DisplayMode[] nDisplayModes = nGetAvailableDisplayModes(getDisplay(), getDefaultScreen(), current_displaymode_extension);
+ int bpp = 24;
+ if (nDisplayModes.length > 0) {
+ bpp = nDisplayModes[0].getBitsPerPixel();
+ }
+ // get the resolutions and frequencys from XRandR
+ Screen[] resolutions = XRandR.getResolutions(XRandR.getScreenNames()[0]);
+ DisplayMode[] modes = new DisplayMode[resolutions.length];
+ for (int i = 0; i < modes.length; i++) {
+ modes[i] = new DisplayMode(resolutions[i].width, resolutions[i].height, bpp, resolutions[i].freq);
+ }
+ return modes;
+ } else {
+ try {
+ DisplayMode[] modes = nGetAvailableDisplayModes(getDisplay(), getDefaultScreen(), current_displaymode_extension);
+ return modes;
+ } finally {
+ decDisplay();
+ }
+ }
} finally {
unlockAWT();
}
@@ -879,61 +1021,119 @@
private void checkInput() {
if (parent == null) return;
- if (parent_focus != parent.hasFocus()) {
- parent_focus = parent.hasFocus();
-
- if (parent_focus) {
- setInputFocusUnsafe(current_window);
- }
- else if (xembedded) {
- setInputFocusUnsafe(1);
- }
- }
- //else if (parent_focus && !focused && !xembedded) {
- // setInputFocusUnsafe(current_window);
- //}
- }
-
- private void setFocused(boolean got_focus, int focus_detail) {
- if (focused == got_focus || focus_detail == NotifyDetailNone || focus_detail == NotifyPointer || focus_detail == NotifyPointerRoot)
- return;
- focused = got_focus;
-
- if (focused) {
- acquireInput();
- if (parent != null && !xembedded) parent.setFocusable(false);
+ if (xembedded) {
+ long current_focus_window = 0;
+
+ if (last_window_focus != current_focus_window || parent_focused != focused) {
+ if (isParentWindowActive(current_focus_window)) {
+ if (parent_focused) {
+ nSetInputFocus(getDisplay(), current_window, CurrentTime);
+ last_window_focus = current_window;
+ focused = true;
+ }
+ else {
+ // return focus to the parent proxy focus window
+ nSetInputFocus(getDisplay(), parent_proxy_focus_window, CurrentTime);
+ last_window_focus = parent_proxy_focus_window;
+ focused = false;
+ }
+ }
+ else {
+ last_window_focus = current_focus_window;
+ focused = false;
+ }
+ }
}
else {
- releaseInput();
- if (parent != null && !xembedded) parent.setFocusable(true);
- }
- }
- static native long nGetInputFocus(long display);
-
- private static void setInputFocusUnsafe(long window) {
- try {
- setInputFocus(getDisplay(), window, CurrentTime);
- sync(getDisplay(), false);
+ if (parent_focus_changed && parent_focused) {
+ setInputFocusUnsafe(getWindow());
+ parent_focus_changed = false;
+ }
+ }
+ }
+
+ private void setInputFocusUnsafe(long window) {
+ try {
+ nSetInputFocus(getDisplay(), window, CurrentTime);
+ nSync(getDisplay(), false);
} catch (LWJGLException e) {
// Since we don't have any event timings for XSetInputFocus, a race condition might give a BadMatch, which we'll catch and ignore
LWJGLUtil.log("Got exception while trying to focus: " + e);
}
}
- private static native void sync(long display, boolean throw_away_events) throws LWJGLException;
+
+ private static native void nSync(long display, boolean throw_away_events) throws LWJGLException;
+
+ /**
+ * This method will check if the parent window is active when running
+ * in xembed mode. Every xembed embedder window has a focus proxy
+ * window that recieves all the input. This method will test whether
+ * the provided window handle is the focus proxy, if so it will get its
+ * parent window and then test whether this is an ancestor to our
+ * current_window. If so then parent window is active.
+ *
+ * @param window - the window handle to test
+ */
+ private boolean isParentWindowActive(long window) {
+ try {
+ // parent window already active as window is current_window
+ if (window == current_window) return true;
+
+ // xembed focus proxy will have no children
+ if (getChildCount(getDisplay(), window) != 0) return false;
+
+ // get parent, will be xembed embedder window and ancestor of current_window
+ long parent_window = getParentWindow(getDisplay(), window);
+
+ // parent must not be None
+ if (parent_window == None) return false;
+
+ // scroll current_window's ancestors to find parent_window
+ long w = current_window;
+
+ while (w != None) {
+ w = getParentWindow(getDisplay(), w);
+ if (w == parent_window) {
+ parent_proxy_focus_window = window; // save focus proxy window
+ return true;
+ }
+ }
+ } catch (LWJGLException e) {
+ LWJGLUtil.log("Failed to detect if parent window is active: " + e.getMessage());
+ return true; // on failure assume still active
+ }
+
+ return false; // failed to find an active parent window
+ }
+
+ private void setFocused(boolean got_focus, int focus_detail) {
+ if (focused == got_focus || focus_detail == NotifyDetailNone || focus_detail == NotifyPointer || focus_detail == NotifyPointerRoot || xembedded)
+ return;
+ focused = got_focus;
+
+ if (focused) {
+ acquireInput();
+ }
+ else {
+ releaseInput();
+ }
+ }
private void releaseInput() {
if (isLegacyFullscreen() || input_released)
return;
+ if ( keyboard != null )
+ keyboard.releaseAll();
input_released = true;
updateInputGrab();
if (current_window_mode == FULLSCREEN_NETWM) {
nIconifyWindow(getDisplay(), getWindow(), getDefaultScreen());
try {
- if( current_displaymode_extension == XRANDR && savedXrandrConfig.length > 0 )
+ if( current_displaymode_extension == XRANDR )
{
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
- XRandR.setConfiguration( savedXrandrConfig );
+ XRandR.restoreConfiguration();
return null;
}
});
@@ -1143,7 +1343,7 @@
return false;
}
- public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format,
+ public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, ContextAttribs attribs,
IntBuffer pixelFormatCaps,
IntBuffer pBufferAttribs) throws LWJGLException {
return new LinuxPbufferPeerInfo(width, height, pixel_format);
@@ -1160,50 +1360,58 @@
public void releaseTexImageFromPbuffer(PeerInfo handle, int buffer) {
throw new UnsupportedOperationException();
}
-
- private static ByteBuffer convertIcon(ByteBuffer icon, int width, int height) {
- ByteBuffer icon_rgb = BufferUtils.createByteBuffer(icon.capacity());
- int x;
- int y;
- byte r,g,b;
-
- int depth = 4;
-
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- r = icon.get((x*4)+(y*width*4));
- g = icon.get((x*4)+(y*width*4)+1);
- b = icon.get((x*4)+(y*width*4)+2);
-
- icon_rgb.put((x*depth)+(y*width*depth), b); // blue
- icon_rgb.put((x*depth)+(y*width*depth)+1, g); // green
- icon_rgb.put((x*depth)+(y*width*depth)+2, r);
- }
- }
- return icon_rgb;
- }
-
- private static ByteBuffer convertIconMask(ByteBuffer icon, int width, int height) {
- ByteBuffer icon_mask = BufferUtils.createByteBuffer((icon.capacity()/4)/8);
- int x;
- int y;
- byte a;
-
- int depth = 4;
-
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- a = icon.get((x*4)+(y*width*4)+3);
-
- int mask_index = x + y*width;
- int mask_byte_index = mask_index/8;
- int mask_bit_index = mask_index%8;
- byte bit = (((int)a) & 0xff) >= 127 ? (byte)1 : (byte)0;
- byte new_byte = (byte)((icon_mask.get(mask_byte_index) | (bit< 0 ) {
+ bufferSize += 2 * 4; // add 32 bit width & height, 4 bytes each
+ bufferSize += dimension * dimension * 4;
+ }
+ }
+
+ if (bufferSize == 0) return null;
+
+ ByteBuffer icon_argb = BufferUtils.createByteBuffer(bufferSize);//icon.capacity()+(2*4));
+ icon_argb.order(ByteOrder.BIG_ENDIAN);
+
+ for ( ByteBuffer icon : icons ) {
+ int size = icon.limit() / 4;
+ int dimension = (int)Math.sqrt(size);
+
+ icon_argb.putInt(dimension); // width
+ icon_argb.putInt(dimension); // height
+
+ for (int y = 0; y < dimension; y++) {
+ for (int x = 0; x < dimension; x++) {
+
+ byte r = icon.get((x*4)+(y*dimension*4));
+ byte g = icon.get((x*4)+(y*dimension*4)+1);
+ byte b = icon.get((x*4)+(y*dimension*4)+2);
+ byte a = icon.get((x*4)+(y*dimension*4)+3);
+
+ icon_argb.put(a);
+ icon_argb.put(r);
+ icon_argb.put(g);
+ icon_argb.put(b);
+ }
+ }
+ }
+
+ return icon_argb;
}
/**
@@ -1223,17 +1431,11 @@
try {
incDisplay();
try {
- for ( ByteBuffer icon : icons ) {
- int size = icon.limit() / 4;
- int dimension = (int)Math.sqrt(size);
- if ( dimension > 0 ) {
- ByteBuffer icon_rgb = convertIcon(icon, dimension, dimension);
- ByteBuffer icon_mask = convertIconMask(icon, dimension, dimension);
- nSetWindowIcon(getDisplay(), getWindow(), icon_rgb, icon_rgb.capacity(), icon_mask, icon_mask.capacity(), dimension, dimension);
- return 1;
- }
- }
- return 0;
+ // get icons as cardinal ARGB format
+ ByteBuffer icons_data = convertIcons(icons);
+ if (icons_data == null) return 0;
+ nSetWindowIcon(getDisplay(), getWindow(), icons_data, icons_data.capacity());//, icon_mask, icon_mask.capacity(), dimension, dimension);
+ return icons.length;
} finally {
decDisplay();
}
@@ -1245,20 +1447,50 @@
}
}
- private static native void nSetWindowIcon(long display, long window, ByteBuffer icon_rgb, int icon_rgb_size, ByteBuffer icon_mask, int icon_mask_size, int width, int height);
-
+ private static native void nSetWindowIcon(long display, long window, ByteBuffer icons_data, int icons_size);
+
+ public int getX() {
+ return window_x;
+ }
+
+ public int getY() {
+ return window_y;
+ }
+
public int getWidth() {
- return Display.getDisplayMode().getWidth();
+ return window_width;
}
public int getHeight() {
- return Display.getDisplayMode().getHeight();
+ return window_height;
}
public boolean isInsideWindow() {
return mouseInside;
}
+ public void setResizable(boolean resizable) {
+ if (this.resizable == resizable) {
+ return;
+ }
+
+ this.resizable = resizable;
+ nSetWindowSize(getDisplay(), getWindow(), window_width, window_height, resizable);
+ }
+
+ public boolean wasResized() {
+ if (resized) {
+ resized = false;
+ return true;
+ }
+
+ return false;
+ }
+
+ public float getPixelScaleFactor() {
+ return 1f;
+ }
+
/**
* Helper class for managing Compiz's workarounds. We need this to enable Legacy
* Fullscreen Support in Compiz, else we'll have trouble with fullscreen windows
@@ -1446,4 +1678,4 @@
}
}
-}
\ No newline at end of file
+}
diff --git a/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java
index debfa8d..76af84a 100644
--- a/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java
@@ -38,11 +38,20 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: LinuxDisplayPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class LinuxDisplayPeerInfo extends LinuxPeerInfo {
+
+ final boolean egl;
+
+ LinuxDisplayPeerInfo() throws LWJGLException {
+ egl = true;
+ org.lwjgl.opengles.GLContext.loadOpenGLLibrary();
+ }
+
LinuxDisplayPeerInfo(PixelFormat pixel_format) throws LWJGLException {
+ egl = false;
LinuxDisplay.lockAWT();
try {
GLContext.loadOpenGLLibrary();
@@ -80,9 +89,14 @@
public void destroy() {
super.destroy();
- LinuxDisplay.lockAWT();
- LinuxDisplay.decDisplay();
- GLContext.unloadOpenGLLibrary();
- LinuxDisplay.unlockAWT();
+
+ if ( egl )
+ org.lwjgl.opengles.GLContext.unloadOpenGLLibrary();
+ else {
+ LinuxDisplay.lockAWT();
+ LinuxDisplay.decDisplay();
+ GLContext.unloadOpenGLLibrary();
+ LinuxDisplay.unlockAWT();
+ }
}
}
diff --git a/src/java/org/lwjgl/opengl/LinuxEvent.java b/src/java/org/lwjgl/opengl/LinuxEvent.java
index fb8e982..e8fbe90 100644
--- a/src/java/org/lwjgl/opengl/LinuxEvent.java
+++ b/src/java/org/lwjgl/opengl/LinuxEvent.java
@@ -53,6 +53,7 @@
public static final int UnmapNotify = 18;
public static final int MapNotify = 19;
public static final int Expose = 12;
+ public static final int ConfigureNotify = 22;
public static final int ClientMessage = 33;
private final ByteBuffer event_buffer;
diff --git a/src/java/org/lwjgl/opengl/LinuxKeyboard.java b/src/java/org/lwjgl/opengl/LinuxKeyboard.java
index 9966503..7fbb411 100644
--- a/src/java/org/lwjgl/opengl/LinuxKeyboard.java
+++ b/src/java/org/lwjgl/opengl/LinuxKeyboard.java
@@ -296,7 +296,7 @@
return keycode;
}
- private byte getKeyState(int event_type) {
+ private static byte getKeyState(int event_type) {
switch (event_type) {
case LinuxEvent.KeyPress:
return 1;
@@ -307,10 +307,22 @@
}
}
+ /** This is called when the window loses focus: we release all currently pressed keys. */
+ void releaseAll() {
+ for ( int i = 0; i < key_down_buffer.length; i++ ) {
+ if ( key_down_buffer[i] != 0 ) {
+ key_down_buffer[i] = 0;
+ putKeyboardEvent(i, (byte)0, 0, 0L, false);
+ }
+ }
+ }
+
private void handleKeyEvent(long event_ptr, long millis, int event_type, int event_keycode, int event_state) {
int keycode = getKeycode(event_ptr, event_state);
byte key_state = getKeyState(event_type);
boolean repeat = key_state == key_down_buffer[keycode];
+ if ( repeat && event_type == LinuxEvent.KeyRelease ) // This can happen for modifier keys after losing and regaining focus.
+ return;
key_down_buffer[keycode] = key_state;
long nanos = millis*1000000;
if (event_type == LinuxEvent.KeyPress) {
diff --git a/src/java/org/lwjgl/opengl/LinuxMouse.java b/src/java/org/lwjgl/opengl/LinuxMouse.java
index 7383ec1..88bea2a 100644
--- a/src/java/org/lwjgl/opengl/LinuxMouse.java
+++ b/src/java/org/lwjgl/opengl/LinuxMouse.java
@@ -43,17 +43,23 @@
import org.lwjgl.input.Mouse;
final class LinuxMouse {
- private static final int NUM_BUTTONS = 3;
private static final int POINTER_WARP_BORDER = 10;
// scale the mouse wheel according to DirectInput
private static final int WHEEL_SCALE = 120;
+ private int button_count;
+
/* X11 constants */
private static final int Button1 = 1;
private static final int Button2 = 2;
private static final int Button3 = 3;
private static final int Button4 = 4;
private static final int Button5 = 5;
+
+ private static final int Button6 = 6; // wheel tilt left *rare*
+ private static final int Button7 = 7; // wheel tilt right *rare*
+ private static final int Button8 = 8; // back button
+ private static final int Button9 = 9; // forward button
private static final int ButtonPress = 4;
private static final int ButtonRelease = 5;
@@ -70,7 +76,7 @@
private int accum_dx;
private int accum_dy;
private int accum_dz;
- private byte[] buttons = new byte[NUM_BUTTONS];
+ private byte[] buttons;
private EventQueue event_queue;
private long last_event_nanos;
@@ -79,6 +85,8 @@
this.window = window;
this.input_window = input_window;
this.warp_atom = LinuxDisplay.nInternAtom(display, "_LWJGL", false);
+ button_count = nGetButtonCount(display);
+ buttons = new byte[button_count];
reset(false, false);
}
@@ -189,6 +197,8 @@
}
private static native int nGetWindowHeight(long display, long window);
private static native int nGetWindowWidth(long display, long window);
+
+ private static native int nGetButtonCount(long display);
private static native long nQueryPointer(long display, long window, IntBuffer result);
@@ -213,7 +223,23 @@
case Button3:
button_num = (byte)1;
break;
+ case Button6:
+ button_num = (byte)5;
+ break;
+ case Button7:
+ button_num = (byte)6;
+ break;
+ case Button8:
+ button_num = (byte)3; // back button
+ break;
+ case Button9:
+ button_num = (byte)4; // forward button
+ break;
default:
+ if (button > Button9 && button <= button_count) {
+ button_num = (byte)(button-1);
+ break;
+ }
return;
}
buttons[button_num] = state;
diff --git a/src/java/org/lwjgl/opengl/LinuxPbufferPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxPbufferPeerInfo.java
index 65f40d1..3828c01 100644
--- a/src/java/org/lwjgl/opengl/LinuxPbufferPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/LinuxPbufferPeerInfo.java
@@ -38,8 +38,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: LinuxPbufferPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class LinuxPbufferPeerInfo extends LinuxPeerInfo {
LinuxPbufferPeerInfo(int width, int height, PixelFormat pixel_format) throws LWJGLException {
diff --git a/src/java/org/lwjgl/opengl/LinuxPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxPeerInfo.java
index 84930a7..ea1aece 100644
--- a/src/java/org/lwjgl/opengl/LinuxPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/LinuxPeerInfo.java
@@ -36,8 +36,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: LinuxPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
abstract class LinuxPeerInfo extends PeerInfo {
LinuxPeerInfo() {
diff --git a/src/java/org/lwjgl/opengl/MacOSXAWTGLCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXAWTGLCanvasPeerInfo.java
index 50a8f00..69e9d3d 100644
--- a/src/java/org/lwjgl/opengl/MacOSXAWTGLCanvasPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/MacOSXAWTGLCanvasPeerInfo.java
@@ -38,14 +38,14 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: MacOSXAWTGLCanvasPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class MacOSXAWTGLCanvasPeerInfo extends MacOSXCanvasPeerInfo {
private final Canvas component;
- MacOSXAWTGLCanvasPeerInfo(Canvas component, PixelFormat pixel_format, boolean support_pbuffer) throws LWJGLException {
- super(pixel_format, support_pbuffer);
+ MacOSXAWTGLCanvasPeerInfo(Canvas component, PixelFormat pixel_format, ContextAttribs attribs, boolean support_pbuffer) throws LWJGLException {
+ super(pixel_format, attribs, support_pbuffer);
this.component = component;
}
diff --git a/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java b/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java
index 258fcca..6bd7b23 100644
--- a/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java
+++ b/src/java/org/lwjgl/opengl/MacOSXCanvasImplementation.java
@@ -40,15 +40,15 @@
/**
*
* @author elias_naur
- * @version $Revision: 3002 $
- * $Id: MacOSXCanvasImplementation.java 3002 2008-04-10 20:25:54Z elias_naur $
+ * @version $Revision$
+ * $Id$
*/
final class MacOSXCanvasImplementation implements AWTCanvasImplementation {
- public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
+ public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException {
try {
- return new MacOSXAWTGLCanvasPeerInfo(component, pixel_format, true);
+ return new MacOSXAWTGLCanvasPeerInfo(component, pixel_format, attribs, true);
} catch (LWJGLException e) {
- return new MacOSXAWTGLCanvasPeerInfo(component, pixel_format, false);
+ return new MacOSXAWTGLCanvasPeerInfo(component, pixel_format, attribs, false);
}
}
diff --git a/src/java/org/lwjgl/opengl/MacOSXCanvasListener.java b/src/java/org/lwjgl/opengl/MacOSXCanvasListener.java
index c0111bf..405aa97 100644
--- a/src/java/org/lwjgl/opengl/MacOSXCanvasListener.java
+++ b/src/java/org/lwjgl/opengl/MacOSXCanvasListener.java
@@ -47,6 +47,7 @@
private int width;
private int height;
private boolean context_update;
+ private boolean resized;
MacOSXCanvasListener(Canvas canvas) {
this.canvas = canvas;
@@ -102,6 +103,7 @@
public void componentResized(ComponentEvent e) {
setUpdate();
+ resized = true;
}
public void componentMoved(ComponentEvent e) {
@@ -111,4 +113,13 @@
public void hierarchyChanged(HierarchyEvent e) {
setUpdate();
}
+
+ public boolean wasResized() {
+ if (resized) {
+ resized = false;
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java
index be8dd57..33d051c 100644
--- a/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java
@@ -32,29 +32,151 @@
package org.lwjgl.opengl;
import java.awt.Canvas;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.Insets;
+import java.awt.Container;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Window;
import java.nio.ByteBuffer;
+import javax.swing.SwingUtilities;
+
import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: MacOSXCanvasPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @author kappaOne
+ * @version $Revision$
+ * $Id$
*/
abstract class MacOSXCanvasPeerInfo extends MacOSXPeerInfo {
private final AWTSurfaceLock awt_surface = new AWTSurfaceLock();
-
- protected MacOSXCanvasPeerInfo(PixelFormat pixel_format, boolean support_pbuffer) throws LWJGLException {
- super(pixel_format, true, true, support_pbuffer, true);
+ public ByteBuffer window_handle;
+
+ protected MacOSXCanvasPeerInfo(PixelFormat pixel_format, ContextAttribs attribs, boolean support_pbuffer) throws LWJGLException {
+ super(pixel_format, attribs, true, true, support_pbuffer, true);
}
protected void initHandle(Canvas component) throws LWJGLException {
- nInitHandle(awt_surface.lockAndGetHandle(component), getHandle());
+ boolean forceCALayer = true;
+ boolean autoResizable = true; // set the CALayer to autoResize
+
+ String javaVersion = System.getProperty("java.version");
+
+ if (javaVersion.startsWith("1.5") || javaVersion.startsWith("1.6")) {
+ // On Java 7 and newer CALayer mode is the only way to use OpenGL with AWT
+ // therefore force it on all JVM's except for the older Java 5 and Java 6
+ // where the older cocoaViewRef NSView method maybe be available.
+ forceCALayer = false;
+ }
+ else if (javaVersion.startsWith("1.7")) {
+ autoResizable = false;
+ }
+
+ Insets insets = getInsets(component);
+
+ int top = insets != null ? insets.top : 0;
+ int left = insets != null ? insets.left : 0;
+
+ window_handle = nInitHandle(awt_surface.lockAndGetHandle(component), getHandle(), window_handle, forceCALayer, autoResizable, component.getX()-left, component.getY()-top);
+
+ if (javaVersion.startsWith("1.7")) {
+ // fix for CALayer position not covering Canvas due to a Java 7 bug
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7172187
+ addComponentListener(component);
+
+ reSetLayerBounds(component, getHandle());
+ }
}
- private static native void nInitHandle(ByteBuffer surface_buffer, ByteBuffer peer_info_handle) throws LWJGLException;
+
+ private void addComponentListener(final Canvas component) {
+
+ ComponentListener[] components = component.getComponentListeners();
+
+ // avoid adding duplicate listners by checking if one has already been added
+ for (int i = 0; i < components.length; i++) {
+ ComponentListener c = components[i];
+ if (c.toString() == "CanvasPeerInfoListener") {
+ return; // already contains the listner below return without adding
+ }
+ }
+
+ ComponentListener comp = new ComponentListener() {
+ public void componentHidden(ComponentEvent e) {
+
+ }
+ public void componentMoved(ComponentEvent e) {
+
+ //nSetLayerPosition(getHandle(), component.getX() - left, component.getY() - top);
+ reSetLayerBounds(component, getHandle());
+ }
+
+ public void componentResized(ComponentEvent e) {
+
+ //nSetLayerPosition(getHandle(), component.getX() - left, component.getY() - top);
+ reSetLayerBounds(component, getHandle());
+ }
+
+ public void componentShown(ComponentEvent e) {
+
+ }
+
+ public String toString() {
+ return "CanvasPeerInfoListener";
+ }
+ };
+
+ component.addComponentListener(comp);
+ }
+
+ private static native ByteBuffer nInitHandle(ByteBuffer surface_buffer, ByteBuffer peer_info_handle, ByteBuffer window_handle, boolean forceCALayer, boolean autoResizable, int x, int y) throws LWJGLException;
+
+ private static native void nSetLayerPosition(ByteBuffer peer_info_handle, int x, int y);
+
+ private static native void nSetLayerBounds(ByteBuffer peer_info_handle, int x, int y, int width, int height);
+
+ /**
+ * fix for CALayer position not covering Canvas due to a Java 7 bug
+ * {@link http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7172187}
+ * @param component
+ * @param peer_info_handle
+ */
+ private static void reSetLayerBounds(Canvas component, ByteBuffer peer_info_handle) {
+ // report the root parent (peer).
+ Component peer = SwingUtilities.getRoot(component);
+
+ Point rtLoc = SwingUtilities.convertPoint(component.getParent(), component.getLocation(), peer);
+ int x = (int) rtLoc.getX(), y = (int) rtLoc.getY();
+
+ Insets insets = getInsets(component);
+ x -= insets != null ? insets.left : 0;
+ y -= insets != null ? insets.top : 0;
+
+ // http://hg.openjdk.java.net/jdk8/awt/jdk/rev/65d874d16d59
+ y = (int) peer.getHeight() - y - (int) component.getHeight();
+
+ nSetLayerBounds(peer_info_handle, x, y, component.getWidth(), component.getHeight());
+ }
+
protected void doUnlock() throws LWJGLException {
awt_surface.unlock();
}
+
+ /**
+ * @return rootpane insets (peer insets) values.
+ */
+ private static Insets getInsets(Canvas component) {
+ Container c = SwingUtilities.getRootPane(component);
+
+ if(c != null) {
+ return c.getInsets();
+ } else {
+ return new Insets(0, 0, 0, 0);
+ }
+ }
}
diff --git a/src/java/org/lwjgl/opengl/MacOSXContextAttribs.java b/src/java/org/lwjgl/opengl/MacOSXContextAttribs.java
deleted file mode 100644
index 01a5c5a..0000000
--- a/src/java/org/lwjgl/opengl/MacOSXContextAttribs.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2002-2008 LWJGL Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.lwjgl.opengl;
-
-/**
- * An implementation of ContextAttribs for MacOS X.
- *
- * ---- WIP - No XGL_create_context has been defined for MacOS X yet ----
- *
- * @author spasi
- */
-final class MacOSXContextAttribs implements ContextAttribsImplementation {
-
- private static final int XGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
- private static final int XGL_CONTEXT_MINOR_VERSION_ARB = 0x2092;
- private static final int XGL_CONTEXT_LAYER_PLANE_ARB = 0x2093;
- private static final int XGL_CONTEXT_FLAGS_ARB = 0x2094;
- private static final int XGL_CONTEXT_PROFILE_MASK_ARB = 0x9126;
-
- private static final int XGL_CONTEXT_DEBUG_BIT_ARB = 0x0001;
- private static final int XGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002;
-
- private static final int XGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
- private static final int XGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
-
- MacOSXContextAttribs() {
- }
-
- public int getMajorVersionAttrib() {
- return XGL_CONTEXT_MAJOR_VERSION_ARB;
- }
-
- public int getMinorVersionAttrib() {
- return XGL_CONTEXT_MINOR_VERSION_ARB;
- }
-
- public int getLayerPlaneAttrib() {
- return XGL_CONTEXT_LAYER_PLANE_ARB;
- }
-
- public int getFlagsAttrib() {
- return XGL_CONTEXT_FLAGS_ARB;
- }
-
- public int getDebugBit() {
- return XGL_CONTEXT_DEBUG_BIT_ARB;
- }
-
- public int getForwardCompatibleBit() {
- return XGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
- }
-
- public int getProfileMaskAttrib() {
- return XGL_CONTEXT_PROFILE_MASK_ARB;
- }
-
- public int getProfileCoreBit() {
- return XGL_CONTEXT_CORE_PROFILE_BIT_ARB;
- }
-
- public int getProfileCompatibilityBit() {
- return XGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
- }
-
-}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java b/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java
index 62711c5..c47d8c8 100644
--- a/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java
+++ b/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java
@@ -38,24 +38,24 @@
/**
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: MacOSXContextImplementation.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class MacOSXContextImplementation implements ContextImplementation {
public ByteBuffer create(PeerInfo peer_info, IntBuffer attribs, ByteBuffer shared_context_handle) throws LWJGLException {
ByteBuffer peer_handle = peer_info.lockAndGetHandle();
try {
- return nCreate(peer_handle, attribs, shared_context_handle);
+ return nCreate(peer_handle, shared_context_handle);
} finally {
peer_info.unlock();
}
}
- private static native ByteBuffer nCreate(ByteBuffer peer_handle, IntBuffer attribs, ByteBuffer shared_context_handle) throws LWJGLException;
+ private static native ByteBuffer nCreate(ByteBuffer peer_handle, ByteBuffer shared_context_handle) throws LWJGLException;
public void swapBuffers() throws LWJGLException {
- Context current_context = Context.getCurrentContext();
+ ContextGL current_context = ContextGL.getCurrentContext();
if ( current_context == null )
throw new IllegalStateException("No context is current");
synchronized ( current_context ) {
@@ -63,6 +63,8 @@
}
}
+ native long getCGLShareGroup(ByteBuffer context_handle);
+
private static native void nSwapBuffers(ByteBuffer context_handle) throws LWJGLException;
public void update(ByteBuffer context_handle) {
@@ -83,7 +85,7 @@
private static native void clearDrawable(ByteBuffer handle) throws LWJGLException;
- static void resetView(PeerInfo peer_info, Context context) throws LWJGLException {
+ static void resetView(PeerInfo peer_info, ContextGL context) throws LWJGLException {
ByteBuffer peer_handle = peer_info.lockAndGetHandle();
try {
synchronized ( context ) {
@@ -117,7 +119,7 @@
private static native boolean nIsCurrent(ByteBuffer context_handle) throws LWJGLException;
public void setSwapInterval(int value) {
- Context current_context = Context.getCurrentContext();
+ ContextGL current_context = ContextGL.getCurrentContext();
synchronized ( current_context ) {
nSetSwapInterval(current_context.getHandle(), value);
}
diff --git a/src/java/org/lwjgl/opengl/MacOSXDisplay.java b/src/java/org/lwjgl/opengl/MacOSXDisplay.java
index eaccaee..b46ce81 100644
--- a/src/java/org/lwjgl/opengl/MacOSXDisplay.java
+++ b/src/java/org/lwjgl/opengl/MacOSXDisplay.java
@@ -35,11 +35,13 @@
* This is the Display implementation interface. Display delegates
* to implementors of this interface. There is one DisplayImplementation
* for each supported platform.
- * @author elias_naur
+ *
+ * @author elias_naur
+ * @author mojang
+ * @author kappaOne
*/
import java.awt.Canvas;
-import java.awt.Cursor;
import java.awt.Robot;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
@@ -50,13 +52,13 @@
import java.util.ArrayList;
import java.util.List;
+import org.lwjgl.input.Cursor;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.BufferUtils;
+import org.lwjgl.MemoryUtil;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
-
-import com.apple.eawt.Application;
-import com.apple.eawt.ApplicationAdapter;
-import com.apple.eawt.ApplicationEvent;
import static org.lwjgl.opengl.GL11.*;
@@ -64,82 +66,157 @@
private static final int PBUFFER_HANDLE_SIZE = 24;
private static final int GAMMA_LENGTH = 256;
- private MacOSXCanvasListener canvas_listener;
- private MacOSXFrame frame;
+ //private MacOSXCanvasListener canvas_listener;
private Canvas canvas;
private Robot robot;
private MacOSXMouseEventQueue mouse_queue;
private KeyboardEventQueue keyboard_queue;
- private java.awt.DisplayMode requested_mode;
-
- /* States */
+ private DisplayMode requested_mode;
+
+ /* Members for native window use */
+ private MacOSXNativeMouse mouse;
+ private MacOSXNativeKeyboard keyboard;
+ private ByteBuffer window;
+ private ByteBuffer context;
+
+ private boolean skipViewportValue = false;
+ private static final IntBuffer current_viewport = BufferUtils.createIntBuffer(16);
+
+ private boolean mouseInsideWindow;
+
private boolean close_requested;
+
+ private boolean native_mode = true;
+
+ private boolean updateNativeCursor = false;
+
+ private long currentNativeCursor = 0;
+
+ private boolean enableHighDPI = false;
+
+ private float scaleFactor = 1.0f;
MacOSXDisplay() {
+
+ }
+
+ private native ByteBuffer nCreateWindow(int x, int y, int width, int height, boolean fullscreen, boolean undecorated, boolean resizable, boolean parented, boolean enableFullscreenModeAPI, boolean enableHighDPI, ByteBuffer peer_info_handle, ByteBuffer window_handle) throws LWJGLException;
+
+ private native Object nGetCurrentDisplayMode();
+
+ private native void nGetDisplayModes(Object modesList);
+
+ private native boolean nIsMiniaturized(ByteBuffer window_handle);
+
+ private native boolean nIsFocused(ByteBuffer window_handle);
+
+ private native void nSetResizable(ByteBuffer window_handle, boolean resizable);
+
+ private native void nResizeWindow(ByteBuffer window_handle, int x, int y, int width, int height);
+
+ private native boolean nWasResized(ByteBuffer window_handle);
+
+ private native int nGetX(ByteBuffer window_handle);
+
+ private native int nGetY(ByteBuffer window_handle);
+
+ private native int nGetWidth(ByteBuffer window_handle);
+
+ private native int nGetHeight(ByteBuffer window_handle);
+
+ private native boolean nIsNativeMode(ByteBuffer peer_info_handle);
+
+ private static boolean isUndecorated() {
+ return Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated");
+ }
+
+ public void createWindow(final DrawableLWJGL drawable, DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
+ boolean fullscreen = Display.isFullscreen();
+ boolean resizable = Display.isResizable();
+ boolean parented = (parent != null) && !fullscreen;
+
+ // OS X fullscreen mode API is only available on OS X 10.7+
+ boolean enableFullscreenModeAPI = LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 7) && parent == null &&
+ !Display.getPrivilegedBoolean("org.lwjgl.opengl.Display.disableOSXFullscreenModeAPI");
+
+ // OS X high DPI mode is only available on OS X 10.7+
+ enableHighDPI = LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 7) && parent == null &&
+ (Display.getPrivilegedBoolean("org.lwjgl.opengl.Display.enableHighDPI") || fullscreen);
+
+ if (parented) this.canvas = parent;
+ else this.canvas = null;
+
+ close_requested = false;
+
+ DrawableGL gl_drawable = (DrawableGL)Display.getDrawable();
+ PeerInfo peer_info = gl_drawable.peer_info;
+ ByteBuffer peer_handle = peer_info.lockAndGetHandle();
+ ByteBuffer window_handle = parented ? ((MacOSXCanvasPeerInfo)peer_info).window_handle : window;
+
try {
- AccessController.doPrivileged(new PrivilegedExceptionAction() {
- public Object run() throws Exception {
- Application.getApplication().addApplicationListener(new ApplicationAdapter() {
- public void handleQuit(ApplicationEvent event) {
- doHandleQuit();
- }
- });
- return null;
- }
- });
- } catch (Throwable e) {
- /**
- * In an applet environment, referencing com.apple.eawt.Application can fail with
- * a native exception. So log any exceptions instead of re-throwing.
- */
- LWJGLUtil.log("Failed to register quit handler: " + e.getMessage());
- }
- }
-
- public void createWindow(DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
- boolean fullscreen = Display.isFullscreen();
- hideUI(fullscreen);
- close_requested = false;
- try {
- if (parent == null) {
- frame = new MacOSXFrame(mode, requested_mode, fullscreen, x, y);
- canvas = frame.getCanvas();
- } else {
- frame = null;
- canvas = parent;
- }
- canvas_listener = new MacOSXCanvasListener(canvas);
- robot = AWTUtil.createRobot(canvas);
+
+ window = nCreateWindow(x, y, mode.getWidth(), mode.getHeight(),
+ fullscreen, isUndecorated(), resizable,
+ parented, enableFullscreenModeAPI, enableHighDPI, peer_handle, window_handle);
+
+ if (fullscreen) {
+ // when going to fullscreen viewport is set to screen size by Cocoa, ignore this value
+ skipViewportValue = true;
+ // if starting in fullscreen then set initial viewport to displaymode size
+ current_viewport.put(2, mode.getWidth());
+ current_viewport.put(3, mode.getHeight());
+ }
+
+ native_mode = nIsNativeMode(peer_handle);
+
+ if (!native_mode) {
+ robot = AWTUtil.createRobot(canvas);
+ }
+
} catch (LWJGLException e) {
destroyWindow();
throw e;
- }
- }
-
- private void doHandleQuit() {
+ } finally {
+ peer_info.unlock();
+ }
+ }
+
+ public void doHandleQuit() {
synchronized (this) {
close_requested = true;
}
}
+
+ public void mouseInsideWindow(boolean inside) {
+ synchronized (this) {
+ mouseInsideWindow = inside;
+ }
+ updateNativeCursor = true;
+ }
+
+ public void setScaleFactor(float scale) {
+ synchronized (this) {
+ scaleFactor = scale;
+ }
+ }
+
+ public native void nDestroyCALayer(ByteBuffer peer_info_handle);
+
+ public native void nDestroyWindow(ByteBuffer window_handle);
public void destroyWindow() {
- if (canvas_listener != null) {
- canvas_listener.disableListeners();
- canvas_listener = null;
- }
- if (frame != null) {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- if (MacOSXFrame.getDevice().getFullScreenWindow() == frame)
- MacOSXFrame.getDevice().setFullScreenWindow(null);
- return null;
- }
- });
- if (frame.isDisplayable())
- frame.dispose();
- frame = null;
- }
- hideUI(false);
+
+ if (!native_mode) {
+ DrawableGL gl_drawable = (DrawableGL)Display.getDrawable();
+ PeerInfo peer_info = gl_drawable.peer_info;
+ if (peer_info != null) {
+ ByteBuffer peer_handle = peer_info.getHandle();
+ nDestroyCALayer(peer_handle);
+ }
+ robot = null;
+ }
+
+ nDestroyWindow(window);
}
public int getGammaRampLength() {
@@ -155,81 +232,80 @@
public String getVersion() {
return null;
}
-
- private static boolean equals(java.awt.DisplayMode awt_mode, DisplayMode mode) {
- return awt_mode.getWidth() == mode.getWidth() && awt_mode.getHeight() == mode.getHeight()
- && awt_mode.getBitDepth() == mode.getBitsPerPixel() && awt_mode.getRefreshRate() == mode.getFrequency();
+
+ private static boolean equals(DisplayMode mode1, DisplayMode mode2) {
+ return mode1.getWidth() == mode2.getWidth() && mode1.getHeight() == mode2.getHeight()
+ && mode1.getBitsPerPixel() == mode2.getBitsPerPixel() && mode1.getFrequency() == mode2.getFrequency();
}
public void switchDisplayMode(DisplayMode mode) throws LWJGLException {
- java.awt.DisplayMode[] awt_modes = MacOSXFrame.getDevice().getDisplayModes();
- for ( java.awt.DisplayMode awt_mode : awt_modes ) {
- if (equals(awt_mode, mode)) {
- requested_mode = awt_mode;
+ DisplayMode[] modes = getAvailableDisplayModes();
+
+ for (DisplayMode available_mode : modes) {
+ if (equals(available_mode, mode)) {
+ requested_mode = available_mode;
return;
}
}
+
throw new LWJGLException(mode + " is not supported");
}
public void resetDisplayMode() {
- if (MacOSXFrame.getDevice().getFullScreenWindow() != null)
- MacOSXFrame.getDevice().setFullScreenWindow(null);
- requested_mode = null;
+ requested_mode = null;
restoreGamma();
}
private native void restoreGamma();
- private static DisplayMode createLWJGLDisplayMode(java.awt.DisplayMode awt_mode) {
- int bit_depth;
- int refresh_rate;
- int awt_bit_depth = awt_mode.getBitDepth();
- int awt_refresh_rate = awt_mode.getRefreshRate();
- if (awt_bit_depth != java.awt.DisplayMode.BIT_DEPTH_MULTI)
- bit_depth = awt_bit_depth;
- else
- bit_depth = 32; // Assume the best bit depth
- if (awt_refresh_rate != java.awt.DisplayMode.REFRESH_RATE_UNKNOWN)
- refresh_rate = awt_refresh_rate;
- else
- refresh_rate = 0;
- return new DisplayMode(awt_mode.getWidth(), awt_mode.getHeight(), bit_depth, refresh_rate);
- }
-
+ public Object createDisplayMode(int width, int height, int bitsPerPixel, int refreshRate) {
+ return new DisplayMode(width, height, bitsPerPixel, refreshRate);
+ }
+
public DisplayMode init() throws LWJGLException {
- return createLWJGLDisplayMode(MacOSXFrame.getDevice().getDisplayMode());
+ return (DisplayMode) nGetCurrentDisplayMode();
+ }
+
+ public void addDisplayMode(Object modesList, int width, int height, int bitsPerPixel, int refreshRate) {
+ List modes = (List) modesList;
+ DisplayMode displayMode = new DisplayMode(width, height, bitsPerPixel, refreshRate);
+ modes.add(displayMode);
}
public DisplayMode[] getAvailableDisplayModes() throws LWJGLException {
- java.awt.DisplayMode[] awt_modes = MacOSXFrame.getDevice().getDisplayModes();
List modes = new ArrayList();
- for ( java.awt.DisplayMode awt_mode : awt_modes )
- if ( awt_mode.getBitDepth() >= 16 )
- modes.add(createLWJGLDisplayMode(awt_mode));
+ nGetDisplayModes(modes); // will populate the above list
+ modes.add(Display.getDesktopDisplayMode()); // add desktop resolution as scaled resolutions do not appear
return modes.toArray(new DisplayMode[modes.size()]);
}
+ private native void nSetTitle(ByteBuffer window_handle, ByteBuffer title_buffer);
+
public void setTitle(String title) {
- if (frame != null)
- frame.setTitle(title);
+ ByteBuffer buffer = MemoryUtil.encodeUTF8(title);
+ nSetTitle(window, buffer);
}
public boolean isCloseRequested() {
boolean result;
synchronized (this) {
- result = close_requested || (frame != null && frame.syncIsCloseRequested());
+ result = close_requested;
close_requested = false;
}
return result;
}
public boolean isVisible() {
- return frame == null || frame.syncIsVisible();
+ return true;
}
public boolean isActive() {
- return canvas.isFocusOwner();
+ if (native_mode) {
+ return nIsFocused(window);
+ }
+ else {
+ return Display.getParent().hasFocus();
+ }
}
public Canvas getCanvas() {
@@ -237,82 +313,48 @@
}
public boolean isDirty() {
- return frame != null && frame.getCanvas().syncIsDirty();
- }
-
- public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException {
+ return false;
+ }
+
+ public PeerInfo createPeerInfo(PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException {
try {
- return new MacOSXDisplayPeerInfo(pixel_format, true);
+ return new MacOSXDisplayPeerInfo(pixel_format, attribs, true);
} catch (LWJGLException e) {
- return new MacOSXDisplayPeerInfo(pixel_format, false);
- }
- }
-
- private static final IntBuffer current_viewport = BufferUtils.createIntBuffer(16);
+ return new MacOSXDisplayPeerInfo(pixel_format, attribs, false);
+ }
+ }
+
public void update() {
- boolean should_update = canvas_listener.syncShouldUpdateContext();
- /*
- * Workaround for the "white screen in fullscreen mode" problem
- *
- * Sometimes, switching from windowed mode to fullscreen or simply creating the Display
- * in fullscreen mode will result in the context not being bound to the window correctly.
- * The program runs fine, but the canvas background (white) is shown instead of the context
- * front buffer.
- *
- * I've discovered that re-binding the context with another setView() won't fix the problem, while a
- * clearDrawable() followed by a setView() does work. A straightforward workaround would be
- * to simply run the combination at every update(). This is not sufficient, since the clearDrawable()
- * call makes the the background appear shortly, causing visual artifacts.
- * What we really need is a way to detect that a setView() failed, and then do the magic combo. I've not
- * been able to find such a detection so alternatively I'm triggering the combo if the display is fullscreen
- * (I've not seen the white screen problem in windowed mode) and if the canvas has gotten a paint message or
- * if its update flag was set.
- *
- * My testing seems to indicate that the workaround works, since I've not seen the problem after the fix.
- *
- * - elias
- */
- AbstractDrawable drawable = (AbstractDrawable)Display.getDrawable();
- if (Display.isFullscreen() && (frame != null && frame.getCanvas().syncCanvasPainted() || should_update)) {
+ boolean should_update = true;
+
+ DrawableGL drawable = (DrawableGL)Display.getDrawable();
+ if (should_update) {
+
+ // Save the current viewport size as cocoa will automatically
+ // set the viewport size to the window size on context update
+ if (skipViewportValue) skipViewportValue = false;
+ else glGetInteger(GL_VIEWPORT, current_viewport);
+
+ drawable.context.update();
+
+ // restore the original viewport size that was set before the update
+ glViewport(current_viewport.get(0), current_viewport.get(1), current_viewport.get(2), current_viewport.get(3));
+ }
+
+ if (native_mode && updateNativeCursor) {
+ updateNativeCursor = false;
try {
- MacOSXContextImplementation.resetView(drawable.peer_info, drawable.context);
+ setNativeCursor(currentNativeCursor);
} catch (LWJGLException e) {
- LWJGLUtil.log("Failed to reset context: " + e);
- }
- }
- if (should_update) {
- drawable.context.update();
- /* This is necessary to make sure the context won't "forget" about the view size */
- glGetInteger(GL_VIEWPORT, current_viewport);
- glViewport(current_viewport.get(0), current_viewport.get(1), current_viewport.get(2), current_viewport.get(3));
- }
- if (frame != null && mouse_queue != null) {
- if (frame.syncShouldReleaseCursor())
- MacOSXMouseEventQueue.nGrabMouse(false);
- if (frame.syncShouldWarpCursor())
- mouse_queue.warpCursor();
- }
- }
-
- /**
- * This is an interface to the native Carbon call
- * SetSystemUIMode. It is used to hide the dock in a way
- * that will prevent AWT from shifting the fullscreen window
- *
- * The workaround is not necessary on 10.4, and since 10.4 shows
- * instability problems calling SetSystemUIMode, we'll only call it
- * when the OS version is 10.3 or lower.
- */
- private void hideUI(boolean hide) {
- if (!LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 4))
- nHideUI(hide);
- }
-
- private native void nHideUI(boolean hide);
+ e.printStackTrace();
+ }
+ }
+ }
public void reshape(int x, int y, int width, int height) {
- if (frame != null)
- frame.resize(x, y, width, height);
+ //if (native_mode) {
+ // nResizeWindow(window, x, y, width, height);
+ //}
}
/* Mouse */
@@ -325,119 +367,190 @@
}
public void createMouse() throws LWJGLException {
- this.mouse_queue = new MacOSXMouseEventQueue(canvas);
- mouse_queue.register();
+ if (native_mode) {
+ mouse = new MacOSXNativeMouse(this, window);
+ mouse.register();
+ }
+ else {
+ this.mouse_queue = new MacOSXMouseEventQueue(canvas);
+ mouse_queue.register();
+ }
}
public void destroyMouse() {
- if (mouse_queue != null) {
- MacOSXMouseEventQueue.nGrabMouse(false);
- mouse_queue.unregister();
- }
- this.mouse_queue = null;
+ if (native_mode) {
+ // restore default native cursor
+ try {
+ MacOSXNativeMouse.setCursor(0);
+ } catch (LWJGLException e) {};
+
+ // release any mouse grab
+ grabMouse(false);
+
+ if (mouse != null) {
+ mouse.unregister();
+ }
+ mouse = null;
+ }
+ else {
+ if (mouse_queue != null) {
+ MacOSXMouseEventQueue.nGrabMouse(false);
+ mouse_queue.unregister();
+ }
+ this.mouse_queue = null;
+ }
}
public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons_buffer) {
- mouse_queue.poll(coord_buffer, buttons_buffer);
+ if (native_mode) {
+ mouse.poll(coord_buffer, buttons_buffer);
+ }
+ else {
+ mouse_queue.poll(coord_buffer, buttons_buffer);
+ }
}
public void readMouse(ByteBuffer buffer) {
- mouse_queue.copyEvents(buffer);
+ if (native_mode) {
+ mouse.copyEvents(buffer);
+ }
+ else {
+ mouse_queue.copyEvents(buffer);
+ }
}
public void grabMouse(boolean grab) {
- mouse_queue.setGrabbed(grab);
+ if (native_mode) {
+ mouse.setGrabbed(grab);
+ }
+ else {
+ mouse_queue.setGrabbed(grab);
+ }
}
public int getNativeCursorCapabilities() {
+ if (native_mode) {
+ return Cursor.CURSOR_ONE_BIT_TRANSPARENCY | Cursor.CURSOR_8_BIT_ALPHA | Cursor.CURSOR_ANIMATION;
+ }
+
return AWTUtil.getNativeCursorCapabilities();
}
public void setCursorPosition(int x, int y) {
- AWTUtil.setCursorPosition(canvas, robot, x, y);
+ if (native_mode) {
+ if (mouse != null) {
+ mouse.setCursorPosition(x, y);
+ }
+ }
+ //else {
+ //MacOSXMouseEventQueue.nWarpCursor(x, y);
+ //}
}
public void setNativeCursor(Object handle) throws LWJGLException {
- Cursor awt_cursor = (Cursor)handle;
- if (frame != null)
- frame.setCursor(awt_cursor);
+ if (native_mode) {
+ currentNativeCursor = getCursorHandle(handle);
+ if (Display.isCreated()) {
+ if (mouseInsideWindow) MacOSXNativeMouse.setCursor(currentNativeCursor);
+ else MacOSXNativeMouse.setCursor(0); // restore default cursor if outside Display
+ }
+ }
}
public int getMinCursorSize() {
- return AWTUtil.getMinCursorSize();
+ return 1;
}
public int getMaxCursorSize() {
- return AWTUtil.getMaxCursorSize();
+ // as there is no max cursor size limit on OS X
+ // return the max cursor size as half the screen resolution
+ DisplayMode dm = Display.getDesktopDisplayMode();
+ return Math.min(dm.getWidth(), dm.getHeight()) / 2;
}
/* Keyboard */
public void createKeyboard() throws LWJGLException {
- this.keyboard_queue = new KeyboardEventQueue(canvas);
- keyboard_queue.register();
+ if (native_mode) {
+ this.keyboard = new MacOSXNativeKeyboard(window);
+ keyboard.register();
+ }
+ else {
+ this.keyboard_queue = new KeyboardEventQueue(canvas);
+ keyboard_queue.register();
+ }
}
public void destroyKeyboard() {
- if (keyboard_queue != null)
- keyboard_queue.unregister();
- this.keyboard_queue = null;
+ if (native_mode) {
+ if (keyboard != null) {
+ keyboard.unregister();
+ }
+ keyboard = null;
+ }
+ else {
+ if (keyboard_queue != null) {
+ keyboard_queue.unregister();
+ }
+ this.keyboard_queue = null;
+ }
}
public void pollKeyboard(ByteBuffer keyDownBuffer) {
- keyboard_queue.poll(keyDownBuffer);
+ if (native_mode) {
+ keyboard.poll(keyDownBuffer);
+ }
+ else {
+ keyboard_queue.poll(keyDownBuffer);
+ }
}
public void readKeyboard(ByteBuffer buffer) {
- keyboard_queue.copyEvents(buffer);
- }
-
-/* public int isStateKeySet(int key) {
- int awt_key;
- switch (key) {
- case Keyboard.KEY_CAPITAL:
- awt_key = KeyEvent.VK_CAPS_LOCK;
- break;
- case Keyboard.KEY_NUMLOCK:
- awt_key = KeyEvent.VK_NUM_LOCK;
- break;
- case Keyboard.KEY_SYSRQ:
- awt_key = KeyEvent.VK_SCROLL_LOCK;
- break;
- default:
- return Keyboard.STATE_UNKNOWN;
- }
- try {
- boolean state = Toolkit.getDefaultToolkit().getLockingKeyState(awt_key);
- return state ? Keyboard.STATE_ON : Keyboard.STATE_OFF;
- } catch (Exception e) {
- LWJGLUtil.log("Failed to query key state: " + e);
- return Keyboard.STATE_UNKNOWN;
- }
- }
-*/
+ if (native_mode) {
+ keyboard.copyEvents(buffer);
+ }
+ else {
+ keyboard_queue.copyEvents(buffer);
+ }
+ }
+
/** Native cursor handles */
public Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
- return AWTUtil.createCursor(width, height, xHotspot, yHotspot, numImages, images, delays);
+ if (native_mode) {
+ long cursor = MacOSXNativeMouse.createCursor(width, height, xHotspot, yHotspot, numImages, images, delays);
+ return cursor;
+ }
+ else {
+ return AWTUtil.createCursor(width, height, xHotspot, yHotspot, numImages, images, delays);
+ }
}
public void destroyCursor(Object cursor_handle) {
+ long handle = getCursorHandle(cursor_handle);
+
+ // reset current cursor if same
+ if (currentNativeCursor == handle) {
+ currentNativeCursor = 0;
+ }
+
+ MacOSXNativeMouse.destroyCursor(handle);
+ }
+
+ private static long getCursorHandle(Object cursor_handle) {
+ return cursor_handle != null ? (Long)cursor_handle : 0;
}
public int getPbufferCapabilities() {
- if (LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 3))
- return Pbuffer.PBUFFER_SUPPORTED;
- else
- return 0;
+ return Pbuffer.PBUFFER_SUPPORTED;
}
public boolean isBufferLost(PeerInfo handle) {
return false;
}
- public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format,
+ public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, ContextAttribs attribs,
IntBuffer pixelFormatCaps,
IntBuffer pBufferAttribs) throws LWJGLException {
- return new MacOSXPbufferPeerInfo(width, height, pixel_format);
+ return new MacOSXPbufferPeerInfo(width, height, pixel_format, attribs);
}
public void setPbufferAttrib(PeerInfo handle, int attrib, int value) {
@@ -465,7 +578,7 @@
* @return number of icons used.
*/
public int setIcon(ByteBuffer[] icons) {
-/* int size = 0;
+ /*int size = 0;
int biggest = -1;
for (int i=0;i
- * @version $Revision: 3418 $
- * $Id: MacOSXDisplayPeerInfo.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class MacOSXDisplayPeerInfo extends MacOSXCanvasPeerInfo {
private boolean locked;
- MacOSXDisplayPeerInfo(PixelFormat pixel_format, boolean support_pbuffer) throws LWJGLException {
- super(pixel_format, support_pbuffer);
+ MacOSXDisplayPeerInfo(PixelFormat pixel_format, ContextAttribs attribs, boolean support_pbuffer) throws LWJGLException {
+ super(pixel_format, attribs, support_pbuffer);
}
protected void doLockAndInitHandle() throws LWJGLException {
diff --git a/src/java/org/lwjgl/opengl/MacOSXFrame.java b/src/java/org/lwjgl/opengl/MacOSXFrame.java
deleted file mode 100644
index 502b16c..0000000
--- a/src/java/org/lwjgl/opengl/MacOSXFrame.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (c) 2002-2008 LWJGL Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.lwjgl.opengl;
-
-/**
- * This is the Mac OS X AWT Frame. It contains thread safe
- * methods to manipulateit from non-AWT threads
- * @author elias_naur
- */
-
-import java.awt.BorderLayout;
-import java.awt.Frame;
-import java.awt.GraphicsDevice;
-import java.awt.GraphicsEnvironment;
-import java.awt.Insets;
-import java.awt.Rectangle;
-import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowListener;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-import org.lwjgl.LWJGLException;
-
-final class MacOSXFrame extends Frame implements WindowListener, ComponentListener {
-
- private static final long serialVersionUID = -5823294716668988777L;
-
- private final MacOSXGLCanvas canvas;
- private boolean close_requested;
-
- /* States */
- private Rectangle bounds;
- private boolean active;
- private boolean minimized;
- private boolean should_warp_cursor;
- private boolean should_release_cursor;
-
- MacOSXFrame(DisplayMode mode, final java.awt.DisplayMode requested_mode, boolean fullscreen, int x, int y) throws LWJGLException {
- setResizable(false);
- addWindowListener(this);
- addComponentListener(this);
- canvas = new MacOSXGLCanvas();
- canvas.setFocusTraversalKeysEnabled(false);
- add(canvas, BorderLayout.CENTER);
- boolean undecorated = Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated");
- setUndecorated(fullscreen || undecorated);
- if ( fullscreen ) {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction() {
- public Object run() throws Exception {
- getDevice().setFullScreenWindow(MacOSXFrame.this);
- getDevice().setDisplayMode(requested_mode);
- java.awt.DisplayMode real_mode = getDevice().getDisplayMode();
- /** For some strange reason, the display mode is sometimes silently capped even though the mode is reported as supported */
- if ( requested_mode.getWidth() != real_mode.getWidth() || requested_mode.getHeight() != real_mode.getHeight() ) {
- getDevice().setFullScreenWindow(null);
- if (isDisplayable())
- dispose();
- throw new LWJGLException("AWT capped mode: requested mode = " + requested_mode.getWidth() + "x" + requested_mode.getHeight() +
- " but got " + real_mode.getWidth() + " " + real_mode.getHeight());
- }
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- throw new LWJGLException(e);
- }
- }
- pack();
- resize(x, y, mode.getWidth(), mode.getHeight());
- setVisible(true);
- requestFocus();
- canvas.requestFocus();
- updateBounds();
- }
-
- public void resize(int x, int y, int width, int height) {
- Insets insets = getInsets();
- setBounds(x, y, width + insets.left + insets.right, height + insets.top + insets.bottom);
- }
-
- public Rectangle syncGetBounds() {
- synchronized ( this ) {
- return bounds;
- }
- }
-
- public void componentShown(ComponentEvent e) {
- }
-
- public void componentHidden(ComponentEvent e) {
- }
-
- private void updateBounds() {
- synchronized ( this ) {
- bounds = getBounds();
- }
- }
-
- public void componentResized(ComponentEvent e) {
- updateBounds();
- }
-
- public void componentMoved(ComponentEvent e) {
- updateBounds();
- }
-
- public static GraphicsDevice getDevice() {
- GraphicsEnvironment g_env = GraphicsEnvironment.getLocalGraphicsEnvironment();
- GraphicsDevice device = g_env.getDefaultScreenDevice();
- return device;
- }
-
- public void windowIconified(WindowEvent e) {
- synchronized ( this ) {
- minimized = true;
- }
- }
-
- public void windowDeiconified(WindowEvent e) {
- synchronized ( this ) {
- minimized = false;
- }
- }
-
- public void windowOpened(WindowEvent e) {
- }
-
- public void windowClosed(WindowEvent e) {
- }
-
- public void windowClosing(WindowEvent e) {
- synchronized ( this ) {
- close_requested = true;
- }
- }
-
- public void windowDeactivated(WindowEvent e) {
- synchronized ( this ) {
- active = false;
- should_release_cursor = true;
- should_warp_cursor = false;
- }
- }
-
- public void windowActivated(WindowEvent e) {
- synchronized ( this ) {
- active = true;
- should_warp_cursor = true;
- should_release_cursor = false;
- }
- }
-
- public boolean syncIsCloseRequested() {
- boolean result;
- synchronized ( this ) {
- result = close_requested;
- close_requested = false;
- }
- return result;
- }
-
- public boolean syncIsVisible() {
- synchronized ( this ) {
- return !minimized;
- }
- }
-
- public boolean syncIsActive() {
- synchronized ( this ) {
- return active;
- }
- }
-
- public MacOSXGLCanvas getCanvas() {
- return canvas;
- }
-
- public boolean syncShouldReleaseCursor() {
- boolean result;
- synchronized ( this ) {
- result = should_release_cursor;
- should_release_cursor = false;
- }
- return result;
- }
-
- public boolean syncShouldWarpCursor() {
- boolean result;
- synchronized ( this ) {
- result = should_warp_cursor;
- should_warp_cursor = false;
- }
- return result;
- }
-}
diff --git a/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java b/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java
index b232bec..3104c18 100644
--- a/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java
+++ b/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java
@@ -96,13 +96,13 @@
// If we're going to warp the cursor position, we'll skip the next event to avoid bogus delta values
skip_event = isGrabbed();
}
-/* if (isGrabbed()) {
+ if (isGrabbed()) {
Rectangle bounds = getComponent().getBounds();
Point location_on_screen = getComponent().getLocationOnScreen();
int x = location_on_screen.x + bounds.width/2;
int y = location_on_screen.y + bounds.height/2;
nWarpCursor(x, y);
- }*/
+ }
}
private static native void getMouseDeltas(IntBuffer delta_buffer);
@@ -110,4 +110,4 @@
private static native void nWarpCursor(int x, int y);
static native void nGrabMouse(boolean grab);
-}
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/MacOSXNativeKeyboard.java b/src/java/org/lwjgl/opengl/MacOSXNativeKeyboard.java
new file mode 100644
index 0000000..428541a
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXNativeKeyboard.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2002-2008 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+/**
+ * A native implementation of a LWJGL compatible Keyboard event queue.
+ * @author elias_naur
+ * @author mojang
+ */
+
+import java.awt.event.KeyEvent;
+import java.util.HashMap;
+import java.nio.ByteBuffer;
+
+import org.lwjgl.input.Keyboard;
+
+final class MacOSXNativeKeyboard extends EventQueue {
+ private final byte[] key_states = new byte[Keyboard.KEYBOARD_SIZE];
+
+ /** Event scratch array */
+ private final ByteBuffer event = ByteBuffer.allocate(Keyboard.EVENT_SIZE);
+
+ private ByteBuffer window_handle;
+
+ private boolean has_deferred_event;
+ private long deferred_nanos;
+ private int deferred_key_code;
+ private byte deferred_key_state;
+ private int deferred_character;
+
+ private HashMap nativeToLwjglMap;
+
+ MacOSXNativeKeyboard(ByteBuffer window_handle) {
+ super(Keyboard.EVENT_SIZE);
+ nativeToLwjglMap = new HashMap();
+ initKeyboardMappings();
+ this.window_handle = window_handle;
+ }
+
+ private native void nRegisterKeyListener(ByteBuffer window_handle);
+
+ private native void nUnregisterKeyListener(ByteBuffer window_handle);
+
+ // These are from:
+ private void initKeyboardMappings() {
+ nativeToLwjglMap.put((short)0x1D, Keyboard.KEY_0);
+ nativeToLwjglMap.put((short)0x12, Keyboard.KEY_1);
+ nativeToLwjglMap.put((short)0x13, Keyboard.KEY_2);
+ nativeToLwjglMap.put((short)0x14, Keyboard.KEY_3);
+ nativeToLwjglMap.put((short)0x15, Keyboard.KEY_4);
+ nativeToLwjglMap.put((short)0x17, Keyboard.KEY_5);
+ nativeToLwjglMap.put((short)0x16, Keyboard.KEY_6);
+ nativeToLwjglMap.put((short)0x1A, Keyboard.KEY_7);
+ nativeToLwjglMap.put((short)0x1C, Keyboard.KEY_8);
+ nativeToLwjglMap.put((short)0x19, Keyboard.KEY_9);
+ nativeToLwjglMap.put((short)0x00, Keyboard.KEY_A);
+ nativeToLwjglMap.put((short)0x0B, Keyboard.KEY_B);
+ nativeToLwjglMap.put((short)0x08, Keyboard.KEY_C);
+ nativeToLwjglMap.put((short)0x02, Keyboard.KEY_D);
+ nativeToLwjglMap.put((short)0x0E, Keyboard.KEY_E);
+ nativeToLwjglMap.put((short)0x03, Keyboard.KEY_F);
+ nativeToLwjglMap.put((short)0x05, Keyboard.KEY_G);
+ nativeToLwjglMap.put((short)0x04, Keyboard.KEY_H);
+ nativeToLwjglMap.put((short)0x22, Keyboard.KEY_I);
+ nativeToLwjglMap.put((short)0x26, Keyboard.KEY_J);
+ nativeToLwjglMap.put((short)0x28, Keyboard.KEY_K);
+ nativeToLwjglMap.put((short)0x25, Keyboard.KEY_L);
+ nativeToLwjglMap.put((short)0x2E, Keyboard.KEY_M);
+ nativeToLwjglMap.put((short)0x2D, Keyboard.KEY_N);
+ nativeToLwjglMap.put((short)0x1F, Keyboard.KEY_O);
+ nativeToLwjglMap.put((short)0x23, Keyboard.KEY_P);
+ nativeToLwjglMap.put((short)0x0C, Keyboard.KEY_Q);
+ nativeToLwjglMap.put((short)0x0F, Keyboard.KEY_R);
+ nativeToLwjglMap.put((short)0x01, Keyboard.KEY_S);
+ nativeToLwjglMap.put((short)0x11, Keyboard.KEY_T);
+ nativeToLwjglMap.put((short)0x20, Keyboard.KEY_U);
+ nativeToLwjglMap.put((short)0x09, Keyboard.KEY_V);
+ nativeToLwjglMap.put((short)0x0D, Keyboard.KEY_W);
+ nativeToLwjglMap.put((short)0x07, Keyboard.KEY_X);
+ nativeToLwjglMap.put((short)0x10, Keyboard.KEY_Y);
+ nativeToLwjglMap.put((short)0x06, Keyboard.KEY_Z);
+
+ nativeToLwjglMap.put((short)0x2A, Keyboard.KEY_BACKSLASH);
+ nativeToLwjglMap.put((short)0x2B, Keyboard.KEY_COMMA);
+ nativeToLwjglMap.put((short)0x18, Keyboard.KEY_EQUALS);
+ nativeToLwjglMap.put((short)0x21, Keyboard.KEY_LBRACKET);
+ nativeToLwjglMap.put((short)0x1B, Keyboard.KEY_MINUS);
+ nativeToLwjglMap.put((short)0x27, Keyboard.KEY_APOSTROPHE);
+ nativeToLwjglMap.put((short)0x1E, Keyboard.KEY_RBRACKET);
+ nativeToLwjglMap.put((short)0x29, Keyboard.KEY_SEMICOLON);
+ nativeToLwjglMap.put((short)0x2C, Keyboard.KEY_SLASH);
+ nativeToLwjglMap.put((short)0x2F, Keyboard.KEY_PERIOD);
+ nativeToLwjglMap.put((short)0x32, Keyboard.KEY_GRAVE);
+
+ nativeToLwjglMap.put((short)0x41, Keyboard.KEY_DECIMAL);
+ nativeToLwjglMap.put((short)0x43, Keyboard.KEY_MULTIPLY);
+ nativeToLwjglMap.put((short)0x45, Keyboard.KEY_ADD);
+ nativeToLwjglMap.put((short)0x47, Keyboard.KEY_CLEAR);
+ nativeToLwjglMap.put((short)0x4B, Keyboard.KEY_DIVIDE);
+ nativeToLwjglMap.put((short)0x4C, Keyboard.KEY_NUMPADENTER);
+ nativeToLwjglMap.put((short)0x4E, Keyboard.KEY_SUBTRACT);
+ nativeToLwjglMap.put((short)0x51, Keyboard.KEY_NUMPADEQUALS);
+
+ nativeToLwjglMap.put((short)0x52, Keyboard.KEY_NUMPAD0);
+ nativeToLwjglMap.put((short)0x53, Keyboard.KEY_NUMPAD1);
+ nativeToLwjglMap.put((short)0x54, Keyboard.KEY_NUMPAD2);
+ nativeToLwjglMap.put((short)0x55, Keyboard.KEY_NUMPAD3);
+ nativeToLwjglMap.put((short)0x56, Keyboard.KEY_NUMPAD4);
+ nativeToLwjglMap.put((short)0x57, Keyboard.KEY_NUMPAD5);
+ nativeToLwjglMap.put((short)0x58, Keyboard.KEY_NUMPAD6);
+ nativeToLwjglMap.put((short)0x59, Keyboard.KEY_NUMPAD7);
+ nativeToLwjglMap.put((short)0x5B, Keyboard.KEY_NUMPAD8);
+ nativeToLwjglMap.put((short)0x5C, Keyboard.KEY_NUMPAD9);
+
+
+ nativeToLwjglMap.put((short)0x24, Keyboard.KEY_RETURN);
+ nativeToLwjglMap.put((short)0x30, Keyboard.KEY_TAB);
+ nativeToLwjglMap.put((short)0x31, Keyboard.KEY_SPACE);
+ nativeToLwjglMap.put((short)0x33, Keyboard.KEY_BACK);
+ nativeToLwjglMap.put((short)0x35, Keyboard.KEY_ESCAPE);
+ nativeToLwjglMap.put((short)0x36, Keyboard.KEY_RMETA); // not in Events.h - works on MBP
+ nativeToLwjglMap.put((short)0x37, Keyboard.KEY_LMETA);
+ nativeToLwjglMap.put((short)0x38, Keyboard.KEY_LSHIFT);
+ nativeToLwjglMap.put((short)0x39, Keyboard.KEY_CAPITAL);
+ nativeToLwjglMap.put((short)0x3A, Keyboard.KEY_LMENU);
+ nativeToLwjglMap.put((short)0x3B, Keyboard.KEY_LCONTROL);
+ nativeToLwjglMap.put((short)0x3C, Keyboard.KEY_RSHIFT);
+ nativeToLwjglMap.put((short)0x3D, Keyboard.KEY_RMENU);
+ nativeToLwjglMap.put((short)0x3E, Keyboard.KEY_RCONTROL);
+
+ nativeToLwjglMap.put((short)0x3F, Keyboard.KEY_FUNCTION);
+ nativeToLwjglMap.put((short)0x77, Keyboard.KEY_END);
+
+ nativeToLwjglMap.put((short)0x7A, Keyboard.KEY_F1);
+ nativeToLwjglMap.put((short)0x78, Keyboard.KEY_F2);
+ nativeToLwjglMap.put((short)0x63, Keyboard.KEY_F3);
+ nativeToLwjglMap.put((short)0x76, Keyboard.KEY_F4);
+ nativeToLwjglMap.put((short)0x60, Keyboard.KEY_F5);
+ nativeToLwjglMap.put((short)0x61, Keyboard.KEY_F6);
+ nativeToLwjglMap.put((short)0x62, Keyboard.KEY_F7);
+ nativeToLwjglMap.put((short)0x64, Keyboard.KEY_F8);
+ nativeToLwjglMap.put((short)0x65, Keyboard.KEY_F9);
+ nativeToLwjglMap.put((short)0x6D, Keyboard.KEY_F10);
+ nativeToLwjglMap.put((short)0x67, Keyboard.KEY_F11);
+ nativeToLwjglMap.put((short)0x6F, Keyboard.KEY_F12);
+ nativeToLwjglMap.put((short)0x69, Keyboard.KEY_F13);
+ nativeToLwjglMap.put((short)0x6B, Keyboard.KEY_F14);
+ nativeToLwjglMap.put((short)0x71, Keyboard.KEY_F15);
+ nativeToLwjglMap.put((short)0x6A, Keyboard.KEY_F16);
+ nativeToLwjglMap.put((short)0x40, Keyboard.KEY_F17);
+ nativeToLwjglMap.put((short)0x4F, Keyboard.KEY_F18);
+ nativeToLwjglMap.put((short)0x50, Keyboard.KEY_F19);
+ // nativeToLwjglMap.put((short)0x5A, Keyboard.KEY_F20);
+
+ nativeToLwjglMap.put((short)0x75, Keyboard.KEY_DELETE);
+ nativeToLwjglMap.put((short)0x72, Keyboard.KEY_INSERT); // 'Help' in Events.h
+ nativeToLwjglMap.put((short)0x73, Keyboard.KEY_HOME);
+ // nativeToLwjglMap.put((short)0xA4, Keyboard.KEY_MUTE);
+ nativeToLwjglMap.put((short)0x79, Keyboard.KEY_NEXT);
+ nativeToLwjglMap.put((short)0x74, Keyboard.KEY_PRIOR);
+ // nativeToLwjglMap.put((short)0x49, Keyboard.KEY_VOLUMEDOWN);
+ // nativeToLwjglMap.put((short)0x48, Keyboard.KEY_VOLUMEUP);
+ nativeToLwjglMap.put((short)0x7B, Keyboard.KEY_LEFT);
+ nativeToLwjglMap.put((short)0x7C, Keyboard.KEY_RIGHT);
+ nativeToLwjglMap.put((short)0x7D, Keyboard.KEY_DOWN);
+ nativeToLwjglMap.put((short)0x7E, Keyboard.KEY_UP);
+
+ nativeToLwjglMap.put((short)0x0A, Keyboard.KEY_SECTION);
+
+ nativeToLwjglMap.put((short)0x6E, Keyboard.KEY_APPS); // not in Events.h
+ nativeToLwjglMap.put((short)0x129, Keyboard.KEY_COLON); // not in Events.h -- do we need it?
+ }
+
+ public void register() {
+ nRegisterKeyListener(window_handle);
+ }
+
+ public void unregister() {
+ nUnregisterKeyListener(window_handle);
+ }
+
+ public void putKeyboardEvent(int key_code, byte state, int character, long nanos, boolean repeat) {
+ event.clear();
+ event.putInt(key_code).put(state).putInt(character).putLong(nanos).put(repeat ? (byte)1 : (byte)0);
+ event.flip();
+ putEvent(event);
+ }
+
+ public synchronized void poll(ByteBuffer key_down_buffer) {
+ flushDeferredEvent();
+ int old_position = key_down_buffer.position();
+ key_down_buffer.put(key_states);
+ key_down_buffer.position(old_position);
+ }
+
+ public synchronized void copyEvents(ByteBuffer dest) {
+ flushDeferredEvent();
+ super.copyEvents(dest);
+ }
+
+ private synchronized void handleKey(int key_code, byte state, int character, long nanos) {
+ if (character == KeyEvent.CHAR_UNDEFINED)
+ character = Keyboard.CHAR_NONE;
+ if (state == 1) {
+ boolean repeat = false;
+ if (has_deferred_event) {
+ if ((nanos == deferred_nanos && deferred_key_code == key_code)) {
+ has_deferred_event = false;
+ repeat = true; // Repeat event
+ } else
+ flushDeferredEvent();
+ }
+ putKeyEvent(key_code, state, character, nanos, repeat);
+ } else {
+ flushDeferredEvent();
+ has_deferred_event = true;
+ deferred_nanos = nanos;
+ deferred_key_code = key_code;
+ deferred_key_state = state;
+ deferred_character = character;
+ }
+ }
+
+ private void flushDeferredEvent() {
+ if (has_deferred_event) {
+ putKeyEvent(deferred_key_code, deferred_key_state, deferred_character, deferred_nanos, false);
+ has_deferred_event = false;
+ }
+ }
+
+ public void putKeyEvent(int key_code, byte state, int character, long nanos, boolean repeat) {
+ /* Ignore repeating presses */
+ int mapped_code = getMappedKeyCode((short)key_code);
+ if (mapped_code < 0) {
+ System.out.println("Unrecognized keycode: " + key_code);
+ /* Unrecognized / unmapped code, do nothing */
+ return;
+ }
+ if ( key_states[mapped_code] == state )
+ repeat = true;
+ key_states[mapped_code] = state;
+ int key_int_char = character & 0xffff;
+ putKeyboardEvent(mapped_code, state, key_int_char, nanos, repeat);
+ }
+
+ private int getMappedKeyCode(short key_code) {
+ if (nativeToLwjglMap.containsKey(key_code)) {
+ return nativeToLwjglMap.get(key_code);
+ }
+ return -1;
+ }
+
+ public void keyPressed(int key_code, String chars, long nanos) {
+ // use only first character of chars returned for key press
+ int character = (chars == null || chars.length() == 0) ? 0 : (int)chars.charAt(0);
+ handleKey(key_code, (byte)1, character, nanos);
+ }
+
+ public void keyReleased(int key_code, String chars, long nanos) {
+ // use only first character of chars returned for key release
+ int character = (chars == null || chars.length() == 0) ? 0 : (int)chars.charAt(0);
+ handleKey(key_code, (byte)0, character, nanos);
+ }
+
+ public void keyTyped(KeyEvent e) {
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXNativeMouse.java b/src/java/org/lwjgl/opengl/MacOSXNativeMouse.java
new file mode 100644
index 0000000..8d23bfc
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/MacOSXNativeMouse.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2002-2008 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+/**
+ * A Cocoa implementation of a LWJGL compatible Mouse.
+ * @author mojang
+ * @author kappaOne
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.input.Mouse;
+import org.lwjgl.LWJGLException;
+
+import java.lang.reflect.*;
+import java.lang.Integer;
+import java.lang.Long;
+
+import org.lwjgl.BufferUtils;
+
+final class MacOSXNativeMouse extends EventQueue {
+ private static final int WHEEL_SCALE = 120;
+ private static final int NUM_BUTTONS = 3;
+
+ private ByteBuffer window_handle;
+ private MacOSXDisplay display;
+
+ private boolean grabbed;
+
+ /** The accumulated mouse deltas returned by poll() */
+ private float accum_dx;
+ private float accum_dy;
+ private int accum_dz;
+
+ /** The last mouse position */
+ private float last_x;
+ private float last_y;
+
+ /** Saved control key state for ctrl-click right button emulation */
+ private boolean saved_control_state;
+
+ private final ByteBuffer event = ByteBuffer.allocate(Mouse.EVENT_SIZE);
+ private IntBuffer delta_buffer = BufferUtils.createIntBuffer(2);
+ private int skip_event;
+
+ private final byte[] buttons = new byte[NUM_BUTTONS];
+
+ MacOSXNativeMouse(MacOSXDisplay display, ByteBuffer window_handle) {
+ super(Mouse.EVENT_SIZE);
+ this.display = display;
+ this.window_handle = window_handle;
+ }
+
+ private native void nSetCursorPosition(ByteBuffer window_handle, int x, int y);
+
+ public static native void nGrabMouse(boolean grab);
+
+ private native void nRegisterMouseListener(ByteBuffer window_handle);
+
+ private native void nUnregisterMouseListener(ByteBuffer window_handle);
+
+ private static native long nCreateCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset, IntBuffer delays, int delays_offset) throws LWJGLException;
+
+ private static native void nDestroyCursor(long cursor_handle);
+
+ private static native void nSetCursor(long cursor_handle) throws LWJGLException;
+
+ public synchronized void register() {
+ nRegisterMouseListener(window_handle);
+ }
+
+ public static long createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException {
+ try {
+ return nCreateCursor(width, height, xHotspot, yHotspot, numImages, images, images.position(), delays, delays != null ? delays.position() : -1);
+ } catch (LWJGLException e) {
+ throw e;
+ }
+ }
+
+ public static void destroyCursor(long cursor_handle) {
+ nDestroyCursor(cursor_handle);
+ }
+
+ public static void setCursor(long cursor_handle) throws LWJGLException {
+ try {
+ nSetCursor(cursor_handle);
+ } catch (LWJGLException e) {
+ throw e;
+ }
+ }
+
+ public synchronized void setCursorPosition(int x, int y) {
+ nSetCursorPosition(window_handle, x, y);
+ }
+
+ public synchronized void unregister() {
+ nUnregisterMouseListener(window_handle);
+ }
+
+ public synchronized void setGrabbed(boolean grabbed) {
+ this.grabbed = grabbed;
+ nGrabMouse(grabbed);
+ skip_event = 1;
+ accum_dx = accum_dy = 0;
+ }
+
+ public synchronized boolean isGrabbed() {
+ return grabbed;
+ }
+
+ protected void resetCursorToCenter() {
+ clearEvents();
+ accum_dx = accum_dy = 0;
+ if (display != null) {
+ last_x = display.getWidth() / 2;
+ last_y = display.getHeight() / 2;
+ }
+ }
+
+ private void putMouseEvent(byte button, byte state, int dz, long nanos) {
+ if (grabbed)
+ putMouseEventWithCoords(button, state, 0, 0, dz, nanos);
+ else
+ putMouseEventWithCoords(button, state, (int)last_x, (int)last_y, dz, nanos);
+ }
+
+ protected void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) {
+ event.clear();
+ event.put(button).put(state).putInt(coord1).putInt(coord2).putInt(dz).putLong(nanos);
+ event.flip();
+ putEvent(event);
+ }
+
+ public synchronized void poll(IntBuffer coord_buffer, ByteBuffer buttons_buffer) {
+ if (grabbed) {
+ coord_buffer.put(0, (int)accum_dx);
+ coord_buffer.put(1, (int)accum_dy);
+ } else {
+ coord_buffer.put(0, (int)last_x);
+ coord_buffer.put(1, (int)last_y);
+ }
+ coord_buffer.put(2, accum_dz);
+ accum_dx = accum_dy = accum_dz = 0;
+ int old_position = buttons_buffer.position();
+ buttons_buffer.put(buttons, 0, buttons.length);
+ buttons_buffer.position(old_position);
+ }
+
+ private void setCursorPos(float x, float y, long nanos) {
+ if ( grabbed )
+ return;
+ float dx = x - last_x;
+ float dy = y - last_y;
+ addDelta(dx, dy);
+ last_x = x;
+ last_y = y;
+ putMouseEventWithCoords((byte)-1, (byte)0, (int)x, (int)y, 0, nanos);
+ }
+
+ protected void addDelta(float dx, float dy) {
+ accum_dx += dx;
+ accum_dy += -dy;
+ }
+
+ public synchronized void setButton(int button, int state, long nanos) {
+ buttons[button] = (byte)state;
+ putMouseEvent((byte)button, (byte)state, 0, nanos);
+ }
+
+ public synchronized void mouseMoved(float x, float y, float dx, float dy, float dz, long nanos) {
+ if (skip_event > 0) {
+ skip_event--;
+ if (skip_event == 0) {
+ last_x = x;
+ last_y = y;
+ }
+ return;
+ }
+
+ if ( dz != 0 ) { // if scroll wheel event
+ // if no vertical wheel events, then map the horizontal wheel event to it
+ if (dy == 0) dy = dx;
+
+ int wheel_amount = (int)(dy * WHEEL_SCALE);
+ accum_dz += wheel_amount;
+ putMouseEvent((byte)-1, (byte)0, wheel_amount, nanos);
+ }
+ else if (grabbed) {
+ if ( dx != 0 || dy != 0 ) {
+ putMouseEventWithCoords((byte)-1, (byte)0, (int)dx, (int)-dy, 0, nanos);
+ addDelta(dx, dy);
+ }
+ } else {
+ setCursorPos(x, y, nanos);
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/opengl/MacOSXPbufferPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXPbufferPeerInfo.java
index 3a5b52a..d39a528 100644
--- a/src/java/org/lwjgl/opengl/MacOSXPbufferPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/MacOSXPbufferPeerInfo.java
@@ -38,12 +38,12 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: MacOSXPbufferPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class MacOSXPbufferPeerInfo extends MacOSXPeerInfo {
- MacOSXPbufferPeerInfo(int width, int height, PixelFormat pixel_format) throws LWJGLException {
- super(pixel_format, false, false, true, false);
+ MacOSXPbufferPeerInfo(int width, int height, PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException {
+ super(pixel_format, attribs, false, false, true, false);
nCreate(getHandle(), width, height);
}
private static native void nCreate(ByteBuffer handle, int width, int height) throws LWJGLException;
diff --git a/src/java/org/lwjgl/opengl/MacOSXPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXPeerInfo.java
index a008ad7..9f11ca0 100644
--- a/src/java/org/lwjgl/opengl/MacOSXPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/MacOSXPeerInfo.java
@@ -39,22 +39,25 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: MacOSXPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
abstract class MacOSXPeerInfo extends PeerInfo {
- MacOSXPeerInfo(PixelFormat pixel_format, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException {
+ MacOSXPeerInfo(PixelFormat pixel_format, ContextAttribs attribs, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException {
super(createHandle());
- if (pixel_format.isFloatingPoint() && !LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 4))
- throw new LWJGLException("Floating point pixel format requested, but is not supported");
- choosePixelFormat(pixel_format, use_display_bpp, support_window, support_pbuffer, double_buffered);
+
+ boolean gl32 = attribs != null && (3 < attribs.getMajorVersion() || (attribs.getMajorVersion() == 3 && 2 <= attribs.getMinorVersion())) && attribs.isProfileCore();
+ if ( gl32 && !LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 7) )
+ throw new LWJGLException("OpenGL 3.2+ requested, but it requires MacOS X 10.7 or newer");
+
+ choosePixelFormat(pixel_format, gl32, use_display_bpp, support_window, support_pbuffer, double_buffered);
}
private static native ByteBuffer createHandle();
- private void choosePixelFormat(PixelFormat pixel_format, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException {
- nChoosePixelFormat(getHandle(), pixel_format, use_display_bpp, support_window, support_pbuffer, double_buffered);
+ private void choosePixelFormat(PixelFormat pixel_format, boolean gl32, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException {
+ nChoosePixelFormat(getHandle(), pixel_format, gl32, use_display_bpp, support_window, support_pbuffer, double_buffered);
}
- private static native void nChoosePixelFormat(ByteBuffer peer_info_handle, PixelFormat pixel_format, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException;
+ private static native void nChoosePixelFormat(ByteBuffer peer_info_handle, PixelFormat pixel_format, boolean gl32, boolean use_display_bpp, boolean support_window, boolean support_pbuffer, boolean double_buffered) throws LWJGLException;
public void destroy() {
nDestroy(getHandle());
diff --git a/src/java/org/lwjgl/opengl/MouseEventQueue.java b/src/java/org/lwjgl/opengl/MouseEventQueue.java
index fa537cd..356b471 100644
--- a/src/java/org/lwjgl/opengl/MouseEventQueue.java
+++ b/src/java/org/lwjgl/opengl/MouseEventQueue.java
@@ -81,15 +81,19 @@
public synchronized void register() {
resetCursorToCenter();
- component.addMouseListener(this);
- component.addMouseMotionListener(this);
- component.addMouseWheelListener(this);
+ if (component != null) {
+ component.addMouseListener(this);
+ component.addMouseMotionListener(this);
+ component.addMouseWheelListener(this);
+ }
}
public synchronized void unregister() {
- component.removeMouseListener(this);
- component.removeMouseMotionListener(this);
- component.removeMouseWheelListener(this);
+ if (component != null) {
+ component.removeMouseListener(this);
+ component.removeMouseMotionListener(this);
+ component.removeMouseWheelListener(this);
+ }
}
protected Component getComponent() {
@@ -105,18 +109,23 @@
return grabbed;
}
- private int transformY(int y) {
- return component.getHeight() - 1 - y;
+ protected int transformY(int y) {
+ if (component != null) {
+ return component.getHeight() - 1 - y;
+ }
+ return y;
}
protected void resetCursorToCenter() {
clearEvents();
accum_dx = accum_dy = 0;
- Point cursor_location = AWTUtil.getCursorPosition(component);
- if (cursor_location != null) {
- last_x = cursor_location.x;
- last_y = cursor_location.y;
- }
+ if (component != null) {
+ Point cursor_location = AWTUtil.getCursorPosition(component);
+ if (cursor_location != null) {
+ last_x = cursor_location.x;
+ last_y = cursor_location.y;
+ }
+ }
}
private void putMouseEvent(byte button, byte state, int dz, long nanos) {
diff --git a/src/java/org/lwjgl/opengl/NVPresentVideoUtil.java b/src/java/org/lwjgl/opengl/NVPresentVideoUtil.java
new file mode 100644
index 0000000..a79f281
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/NVPresentVideoUtil.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.lwjgl.opengl;
+
+import org.lwjgl.BufferChecks;
+import org.lwjgl.LWJGLUtil;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+
+/**
+ * This class exposes the platform specific functionality present in the
+ * NV_present_video extension.
+ *
+ * @author Spasi
+ * @since 20/5/2011
+ */
+public final class NVPresentVideoUtil {
+
+ private NVPresentVideoUtil() {}
+
+ private static void checkExtension() {
+ if ( LWJGLUtil.CHECKS && !GLContext.getCapabilities().GL_NV_present_video )
+ throw new IllegalStateException("NV_present_video is not supported");
+ }
+
+ private static ByteBuffer getPeerInfo() {
+ return ContextGL.getCurrentContext().getPeerInfo().getHandle();
+ }
+
+ /**
+ * Enumerate the available video output devices. This method is the cross-platform
+ * equivalent of glXEnumerateVideoDevicesNV and wglEnumerateVideoDevicesNV. Since they are
+ * not really compatible, this method works like the WGL version. That is, you first
+ * call it with a null devices buffer, get the number of devices, then call it again
+ * with an appropriately sized buffer.
+ *
+ * @param devices the buffer to store devices in
+ *
+ * @return the number of available video output devices
+ */
+ public static int glEnumerateVideoDevicesNV(LongBuffer devices) {
+ checkExtension();
+
+ if ( devices != null )
+ BufferChecks.checkBuffer(devices, 1);
+ return nglEnumerateVideoDevicesNV(getPeerInfo(), devices, devices == null ? 0 : devices.position());
+ }
+
+ private static native int nglEnumerateVideoDevicesNV(ByteBuffer peer_info, LongBuffer devices, int devices_position);
+
+ /**
+ * Binds the video output device specified to one of the context's available video output slots.
+ * This method is the cross-platform equivalent of glXBindVideoDeviceNV and wglBindVideoDeviceNV.
+ * To release a video device without binding another device to the same slot, call it with
+ * video_device set to 0 (will use INVALID_HANDLE_VALUE on WGL).
+ *
+ * @param video_slot the video slot
+ * @param video_device the video device
+ * @param attrib_list the attributes to use
+ *
+ * @return true if the binding was successful
+ */
+ public static boolean glBindVideoDeviceNV(int video_slot, long video_device, IntBuffer attrib_list) {
+ checkExtension();
+
+ if ( attrib_list != null )
+ BufferChecks.checkNullTerminated(attrib_list);
+ return nglBindVideoDeviceNV(getPeerInfo(), video_slot, video_device, attrib_list, attrib_list == null ? 0 : attrib_list.position());
+ }
+
+ private static native boolean nglBindVideoDeviceNV(ByteBuffer peer_info, int video_slot, long video_device, IntBuffer attrib_list, int attrib_list_position);
+
+ /**
+ * Queries an attribute associated with the current context. This method is the cross-platform
+ * equivalent of glXQueryContext and wglQueryCurrentContextNV.
+ *
+ * @param attrib the attribute to query
+ * @param value the buffer to store the value in
+ */
+ public static boolean glQueryContextNV(int attrib, IntBuffer value) {
+ checkExtension();
+
+ BufferChecks.checkBuffer(value, 1);
+ ContextGL ctx = ContextGL.getCurrentContext();
+ return nglQueryContextNV(ctx.getPeerInfo().getHandle(), ctx.getHandle(), attrib, value, value.position());
+ }
+
+ private static native boolean nglQueryContextNV(ByteBuffer peer_info, ByteBuffer context_handle, int attrib, IntBuffer value, int value_position);
+
+}
diff --git a/src/java/org/lwjgl/opengl/NVVideoCaptureUtil.java b/src/java/org/lwjgl/opengl/NVVideoCaptureUtil.java
new file mode 100644
index 0000000..f6409e8
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/NVVideoCaptureUtil.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.lwjgl.opengl;
+
+import org.lwjgl.BufferChecks;
+import org.lwjgl.LWJGLUtil;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+
+/**
+ * This class exposes the platform specific functionality present in the
+ * NV_video_capture extension.
+ *
+ * @author Spasi
+ * @since 20/5/2011
+ */
+public final class NVVideoCaptureUtil {
+
+ private NVVideoCaptureUtil() {}
+
+ private static void checkExtension() {
+ if ( LWJGLUtil.CHECKS && !GLContext.getCapabilities().GL_NV_video_capture )
+ throw new IllegalStateException("NV_video_capture is not supported");
+ }
+
+ private static ByteBuffer getPeerInfo() {
+ return ContextGL.getCurrentContext().getPeerInfo().getHandle();
+ }
+
+ /**
+ * After successfully locking a video capture device, use this method to bind it
+ * to the capture slot specified in the current context. This method is the cross-
+ * platform equivalent of glXBindVideoCaptureDeviceNV and wglBindVideoCaptureDeviceNV.
+ *
+ * @param video_slot the video slot
+ * @param device the video capture device
+ *
+ * @return true if the binding was successful
+ */
+ public static boolean glBindVideoCaptureDeviceNV(int video_slot, long device) {
+ checkExtension();
+ return nglBindVideoCaptureDeviceNV(getPeerInfo(), video_slot, device);
+ }
+
+ private static native boolean nglBindVideoCaptureDeviceNV(ByteBuffer peer_info, int video_slot, long device);
+
+ /**
+ * Enumerate the available video capture devices. This method is the cross-platform
+ * equivalent of glXEnumerateVideoCaptureDevicesNV and wglEnumerateVideoCaptureDevicesNV.
+ * Since they are not really compatible, this method works like the WGL version. That is,
+ * you first call it with a null devices buffer, get the number of devices, then call it
+ * again with an appropriately sized buffer.
+ *
+ * @param devices the buffer to store devices in
+ *
+ * @return the number of available video capture devices
+ */
+ public static int glEnumerateVideoCaptureDevicesNV(LongBuffer devices) {
+ checkExtension();
+
+ if ( devices != null )
+ BufferChecks.checkBuffer(devices, 1);
+ return nglEnumerateVideoCaptureDevicesNV(getPeerInfo(), devices, devices == null ? 0 : devices.position());
+ }
+
+ private static native int nglEnumerateVideoCaptureDevicesNV(ByteBuffer peer_info, LongBuffer devices, int devices_position);
+
+ /**
+ * To lock a video capture device to a display connection, use this method.
+ * Before using a video capture device, it must be locked. Once a
+ * video capture device is locked by a process, no other process can
+ * lock a video capture device with the same unique ID until the lock
+ * is released or the process ends.
+ *
+ * @param device the device to lock
+ *
+ * @return true if the lock was successful
+ */
+ public static boolean glLockVideoCaptureDeviceNV(long device) {
+ checkExtension();
+ return nglLockVideoCaptureDeviceNV(getPeerInfo(), device);
+ }
+
+ private static native boolean nglLockVideoCaptureDeviceNV(ByteBuffer peer_info, long device);
+
+ /**
+ * Use this method to query the unique ID of the physical device backing a
+ * video capture device handle.
+ *
+ * @param device the device
+ * @param attribute the attribute to query
+ * @param value the buffer to store the value in
+ *
+ * @return true if the query was successful
+ */
+ public static boolean glQueryVideoCaptureDeviceNV(long device, int attribute, IntBuffer value) {
+ checkExtension();
+
+ BufferChecks.checkBuffer(value, 1);
+ return nglQueryVideoCaptureDeviceNV(getPeerInfo(), device, attribute, value, value.position());
+ }
+
+ private static native boolean nglQueryVideoCaptureDeviceNV(ByteBuffer peer_info, long device, int attribute, IntBuffer value, int value_position);
+
+ /**
+ * Use this method when finished capturing data on a locked video capture device
+ * to unlock it.
+ *
+ * @param device the device
+ *
+ * @return true if the device was unlocked successfully
+ */
+ public static boolean glReleaseVideoCaptureDeviceNV(long device) {
+ checkExtension();
+ return nglReleaseVideoCaptureDeviceNV(getPeerInfo(), device);
+ }
+
+ private static native boolean nglReleaseVideoCaptureDeviceNV(ByteBuffer peer_info, long device);
+
+}
+
diff --git a/src/java/org/lwjgl/opengl/OpenGLException.java b/src/java/org/lwjgl/opengl/OpenGLException.java
index bdc7715..29fec00 100644
--- a/src/java/org/lwjgl/opengl/OpenGLException.java
+++ b/src/java/org/lwjgl/opengl/OpenGLException.java
@@ -36,8 +36,8 @@
* Thrown by the debug build library of the LWJGL if any OpenGL operation causes an error.
*
* @author cix_foo
- * @version $Revision: 2983 $
- * $Id: OpenGLException.java 2983 2008-04-07 18:36:09Z matzon $
+ * @version $Revision$
+ * $Id$
*/
public class OpenGLException extends RuntimeException {
diff --git a/src/java/org/lwjgl/opengl/Pbuffer.java b/src/java/org/lwjgl/opengl/Pbuffer.java
index e11b7c6..2e88017 100644
--- a/src/java/org/lwjgl/opengl/Pbuffer.java
+++ b/src/java/org/lwjgl/opengl/Pbuffer.java
@@ -45,10 +45,10 @@
* This class is thread-safe.
*
* @author elias_naur
- * @version $Revision: 3334 $
- * $Id: Pbuffer.java 3334 2010-04-22 23:21:48Z spasi $
+ * @version $Revision$
+ * $Id$
*/
-public final class Pbuffer extends AbstractDrawable {
+public final class Pbuffer extends DrawableGL {
/**
* Indicates that Pbuffers can be created.
*/
@@ -216,24 +216,24 @@
throw new NullPointerException("Pixel format must be non-null");
this.width = width;
this.height = height;
- this.peer_info = createPbuffer(width, height, pixel_format, renderTexture);
- Context shared_context;
+ this.peer_info = createPbuffer(width, height, pixel_format, attribs, renderTexture);
+ Context shared_context = null;
+ if ( shared_drawable == null )
+ shared_drawable = Display.getDrawable(); // May be null
if (shared_drawable != null)
shared_context = ((DrawableLWJGL)shared_drawable).getContext();
- else
- shared_context = ((DrawableLWJGL)Display.getDrawable()).getContext(); // May be null
- this.context = new Context(peer_info, attribs, shared_context);
- }
-
- private static PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, RenderTexture renderTexture) throws LWJGLException {
+ this.context = new ContextGL(peer_info, attribs, (ContextGL)shared_context);
+ }
+
+ private static PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, ContextAttribs attribs, RenderTexture renderTexture) throws LWJGLException {
if ( renderTexture == null ) {
// Though null is a perfectly valid argument, Matrox Parhelia drivers expect
// a 0 terminated list, or else they crash. Supplying NULL or 0, should
// cause the drivers to use default settings
IntBuffer defaultAttribs = BufferUtils.createIntBuffer(1);
- return Display.getImplementation().createPbuffer(width, height, pixel_format, null, defaultAttribs);
+ return Display.getImplementation().createPbuffer(width, height, pixel_format, attribs, null, defaultAttribs);
} else
- return Display.getImplementation().createPbuffer(width, height, pixel_format,
+ return Display.getImplementation().createPbuffer(width, height, pixel_format, attribs,
renderTexture.pixelFormatCaps,
renderTexture.pBufferAttribs);
}
diff --git a/src/java/org/lwjgl/opengl/PeerInfo.java b/src/java/org/lwjgl/opengl/PeerInfo.java
index 4603e35..95e04fa 100644
--- a/src/java/org/lwjgl/opengl/PeerInfo.java
+++ b/src/java/org/lwjgl/opengl/PeerInfo.java
@@ -39,8 +39,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3418 $
- * $Id: PeerInfo.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
abstract class PeerInfo {
private final ByteBuffer handle;
diff --git a/src/java/org/lwjgl/opengl/PixelFormat.java b/src/java/org/lwjgl/opengl/PixelFormat.java
index 7c11bfb..10559f3 100644
--- a/src/java/org/lwjgl/opengl/PixelFormat.java
+++ b/src/java/org/lwjgl/opengl/PixelFormat.java
@@ -38,17 +38,16 @@
*
* Instants of this class are immutable. An example of the expected way to set
* the PixelFormat property values is the following:
- * PixelFormat pf = new PixelFormat().withDepth(24).withSamples(4).withSRGB(true);
+ * PixelFormat pf = new PixelFormat().withDepthBits(24).withSamples(4).withSRGB(true);
*
* WARNING: Some pixel formats are known to cause troubles on certain buggy drivers.
* Example: Under Windows, specifying samples != 0 will enable the ARB
* pixel format selection path, which could trigger a crash.
*
* @author elias_naur@sourceforge.net
- * @version $Revision: 3355 $
+ * @version $Revision$
*/
-
-public final class PixelFormat {
+public final class PixelFormat implements PixelFormatLWJGL {
/**
* The number of bits per pixel, exluding alpha.
diff --git a/src/java/org/lwjgl/opengl/PixelFormatLWJGL.java b/src/java/org/lwjgl/opengl/PixelFormatLWJGL.java
new file mode 100644
index 0000000..d270dac
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/PixelFormatLWJGL.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+/**
+ * [INTERNAL USE ONLY]
+ *
+ * @author Spasi
+ */
+public interface PixelFormatLWJGL {
+ // Marker interface
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/SharedDrawable.java b/src/java/org/lwjgl/opengl/SharedDrawable.java
index f96d0f6..7227329 100644
--- a/src/java/org/lwjgl/opengl/SharedDrawable.java
+++ b/src/java/org/lwjgl/opengl/SharedDrawable.java
@@ -44,13 +44,13 @@
*
* @author Spasi
*/
-public final class SharedDrawable extends AbstractDrawable {
+public final class SharedDrawable extends DrawableGL {
public SharedDrawable(final Drawable drawable) throws LWJGLException {
- this.context = ((DrawableLWJGL)drawable).createSharedContext();
+ this.context = (ContextGL)((DrawableLWJGL)drawable).createSharedContext();
}
- public Context createSharedContext() {
+ public ContextGL createSharedContext() {
throw new UnsupportedOperationException();
}
diff --git a/src/java/org/lwjgl/opengl/Sync.java b/src/java/org/lwjgl/opengl/Sync.java
new file mode 100644
index 0000000..51560dd
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/Sync.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2002-2012 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengl;
+
+import org.lwjgl.Sys;
+
+/**
+* A highly accurate sync method that continually adapts to the system
+* it runs on to provide reliable results.
+*
+* @author Riven
+* @author kappaOne
+*/
+class Sync {
+
+ /** number of nano seconds in a second */
+ private static final long NANOS_IN_SECOND = 1000L * 1000L * 1000L;
+
+ /** The time to sleep/yield until the next frame */
+ private static long nextFrame = 0;
+
+ /** whether the initialisation code has run */
+ private static boolean initialised = false;
+
+ /** for calculating the averages the previous sleep/yield times are stored */
+ private static RunningAvg sleepDurations = new RunningAvg(10);
+ private static RunningAvg yieldDurations = new RunningAvg(10);
+
+
+ /**
+ * An accurate sync method that will attempt to run at a constant frame rate.
+ * It should be called once every frame.
+ *
+ * @param fps - the desired frame rate, in frames per second
+ */
+ public static void sync(int fps) {
+ if (fps <= 0) return;
+ if (!initialised) initialise();
+
+ try {
+ // sleep until the average sleep time is greater than the time remaining till nextFrame
+ for (long t0 = getTime(), t1; (nextFrame - t0) > sleepDurations.avg(); t0 = t1) {
+ Thread.sleep(1);
+ sleepDurations.add((t1 = getTime()) - t0); // update average sleep time
+ }
+
+ // slowly dampen sleep average if too high to avoid yielding too much
+ sleepDurations.dampenForLowResTicker();
+
+ // yield until the average yield time is greater than the time remaining till nextFrame
+ for (long t0 = getTime(), t1; (nextFrame - t0) > yieldDurations.avg(); t0 = t1) {
+ Thread.yield();
+ yieldDurations.add((t1 = getTime()) - t0); // update average yield time
+ }
+ } catch (InterruptedException e) {
+
+ }
+
+ // schedule next frame, drop frame(s) if already too late for next frame
+ nextFrame = Math.max(nextFrame + NANOS_IN_SECOND / fps, getTime());
+ }
+
+ /**
+ * This method will initialise the sync method by setting initial
+ * values for sleepDurations/yieldDurations and nextFrame.
+ *
+ * If running on windows it will start the sleep timer fix.
+ */
+ private static void initialise() {
+ initialised = true;
+
+ sleepDurations.init(1000 * 1000);
+ yieldDurations.init((int) (-(getTime() - getTime()) * 1.333));
+
+ nextFrame = getTime();
+
+ String osName = System.getProperty("os.name");
+
+ if (osName.startsWith("Win")) {
+ // On windows the sleep functions can be highly inaccurate by
+ // over 10ms making in unusable. However it can be forced to
+ // be a bit more accurate by running a separate sleeping daemon
+ // thread.
+ Thread timerAccuracyThread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ Thread.sleep(Long.MAX_VALUE);
+ } catch (Exception e) {}
+ }
+ });
+
+ timerAccuracyThread.setName("LWJGL Timer");
+ timerAccuracyThread.setDaemon(true);
+ timerAccuracyThread.start();
+ }
+ }
+
+ /**
+ * Get the system time in nano seconds
+ *
+ * @return will return the current time in nano's
+ */
+ private static long getTime() {
+ return (Sys.getTime() * NANOS_IN_SECOND) / Sys.getTimerResolution();
+ }
+
+ private static class RunningAvg {
+ private final long[] slots;
+ private int offset;
+
+ private static final long DAMPEN_THRESHOLD = 10 * 1000L * 1000L; // 10ms
+ private static final float DAMPEN_FACTOR = 0.9f; // don't change: 0.9f is exactly right!
+
+ public RunningAvg(int slotCount) {
+ this.slots = new long[slotCount];
+ this.offset = 0;
+ }
+
+ public void init(long value) {
+ while (this.offset < this.slots.length) {
+ this.slots[this.offset++] = value;
+ }
+ }
+
+ public void add(long value) {
+ this.slots[this.offset++ % this.slots.length] = value;
+ this.offset %= this.slots.length;
+ }
+
+ public long avg() {
+ long sum = 0;
+ for (int i = 0; i < this.slots.length; i++) {
+ sum += this.slots[i];
+ }
+ return sum / this.slots.length;
+ }
+
+ public void dampenForLowResTicker() {
+ if (this.avg() > DAMPEN_THRESHOLD) {
+ for (int i = 0; i < this.slots.length; i++) {
+ this.slots[i] *= DAMPEN_FACTOR;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/Util.java b/src/java/org/lwjgl/opengl/Util.java
index 0543792..8efa1c0 100644
--- a/src/java/org/lwjgl/opengl/Util.java
+++ b/src/java/org/lwjgl/opengl/Util.java
@@ -39,7 +39,7 @@
* Simple utility class.
*
* @author cix_foo
- * @version $Revision: 3418 $
+ * @version $Revision$
*/
public final class Util {
diff --git a/src/java/org/lwjgl/opengl/WindowsAWTGLCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/WindowsAWTGLCanvasPeerInfo.java
index 24b7a40..289c120 100644
--- a/src/java/org/lwjgl/opengl/WindowsAWTGLCanvasPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/WindowsAWTGLCanvasPeerInfo.java
@@ -40,8 +40,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3418 $
- * $Id: WindowsAWTGLCanvasPeerInfo.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class WindowsAWTGLCanvasPeerInfo extends WindowsPeerInfo {
private final Canvas component;
diff --git a/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java b/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java
index b3d58b7..846fe06 100644
--- a/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java
+++ b/src/java/org/lwjgl/opengl/WindowsCanvasImplementation.java
@@ -44,8 +44,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3418 $
- * $Id: WindowsCanvasImplementation.java 3418 2010-09-28 21:11:35Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class WindowsCanvasImplementation implements AWTCanvasImplementation {
static {
@@ -66,7 +66,7 @@
});
}
- public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
+ public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException {
return new WindowsAWTGLCanvasPeerInfo(component, pixel_format);
}
diff --git a/src/java/org/lwjgl/opengl/WindowsContextAttribs.java b/src/java/org/lwjgl/opengl/WindowsContextAttribs.java
deleted file mode 100644
index 3273144..0000000
--- a/src/java/org/lwjgl/opengl/WindowsContextAttribs.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2002-2008 LWJGL Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.lwjgl.opengl;
-
-/**
- * An implementation of ContextAttribs using WGL_create_context.
- *
- * @author spasi
- */
-final class WindowsContextAttribs implements ContextAttribsImplementation {
-
- private static final int WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
- private static final int WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092;
- private static final int WGL_CONTEXT_LAYER_PLANE_ARB = 0x2093;
- private static final int WGL_CONTEXT_FLAGS_ARB = 0x2094;
- private static final int WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126;
-
- private static final int WGL_CONTEXT_DEBUG_BIT_ARB = 0x0001;
- private static final int WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002;
-
- private static final int WGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
- private static final int WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
-
- WindowsContextAttribs() {
- }
-
- public int getMajorVersionAttrib() {
- return WGL_CONTEXT_MAJOR_VERSION_ARB;
- }
-
- public int getMinorVersionAttrib() {
- return WGL_CONTEXT_MINOR_VERSION_ARB;
- }
-
- public int getLayerPlaneAttrib() {
- return WGL_CONTEXT_LAYER_PLANE_ARB;
- }
-
- public int getFlagsAttrib() {
- return WGL_CONTEXT_FLAGS_ARB;
- }
-
- public int getDebugBit() {
- return WGL_CONTEXT_DEBUG_BIT_ARB;
- }
-
- public int getForwardCompatibleBit() {
- return WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
- }
-
- public int getProfileMaskAttrib() {
- return WGL_CONTEXT_PROFILE_MASK_ARB;
- }
-
- public int getProfileCoreBit() {
- return WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
- }
-
- public int getProfileCompatibilityBit() {
- return WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
- }
-
-}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/WindowsContextImplementation.java b/src/java/org/lwjgl/opengl/WindowsContextImplementation.java
index 6c84431..b81bc5e 100644
--- a/src/java/org/lwjgl/opengl/WindowsContextImplementation.java
+++ b/src/java/org/lwjgl/opengl/WindowsContextImplementation.java
@@ -39,8 +39,8 @@
/**
* @author elias_naur
- * @version $Revision: 3412 $
- * $Id: WindowsContextImplementation.java 3412 2010-09-26 23:43:24Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class WindowsContextImplementation implements ContextImplementation {
@@ -60,7 +60,7 @@
native long getHDC(ByteBuffer peer_info_handle);
public void swapBuffers() throws LWJGLException {
- Context current_context = Context.getCurrentContext();
+ ContextGL current_context = ContextGL.getCurrentContext();
if ( current_context == null )
throw new IllegalStateException("No context is current");
synchronized ( current_context ) {
diff --git a/src/java/org/lwjgl/opengl/WindowsDisplay.java b/src/java/org/lwjgl/opengl/WindowsDisplay.java
index e2e31da..e2d59af 100644
--- a/src/java/org/lwjgl/opengl/WindowsDisplay.java
+++ b/src/java/org/lwjgl/opengl/WindowsDisplay.java
@@ -38,21 +38,28 @@
* @author elias_naur
*/
-import java.nio.ByteBuffer;
-import java.nio.FloatBuffer;
-import java.nio.IntBuffer;
-import java.awt.Canvas;
+import java.awt.*;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.lang.reflect.Method;
+import java.nio.*;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.BufferUtils;
+import org.lwjgl.MemoryUtil;
import org.lwjgl.input.Cursor;
-import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
+import org.lwjgl.opengles.EGL;
+
+import javax.swing.*;
final class WindowsDisplay implements DisplayImplementation {
private static final int GAMMA_LENGTH = 256;
+ private static final int WM_WINDOWPOSCHANGED = 0x0047;
+ private static final int WM_MOVE = 0x0003;
private static final int WM_CANCELMODE = 0x001F;
private static final int WM_MOUSEMOVE = 0x0200;
private static final int WM_LBUTTONDOWN = 0x0201;
@@ -64,16 +71,25 @@
private static final int WM_MBUTTONDOWN = 0x0207;
private static final int WM_MBUTTONUP = 0x0208;
private static final int WM_MBUTTONDBLCLK = 0x0209;
+ private static final int WM_XBUTTONDOWN = 0x020B;
+ private static final int WM_XBUTTONUP = 0x020C;
+ private static final int WM_XBUTTONDBLCLK = 0x020D;
private static final int WM_MOUSEWHEEL = 0x020A;
private static final int WM_CAPTURECHANGED = 0x0215;
- private static final int WM_MOUSELEAVE = 0x02A3;
+ private static final int WM_MOUSELEAVE = 0x02A3;
+ private static final int WM_ENTERSIZEMOVE = 0x0231;
+ private static final int WM_EXITSIZEMOVE = 0x0232;
+ private static final int WM_SIZING = 0x0214;
private static final int WM_KEYDOWN = 256;
private static final int WM_KEYUP = 257;
private static final int WM_SYSKEYUP = 261;
private static final int WM_SYSKEYDOWN = 260;
private static final int WM_SYSCHAR = 262;
private static final int WM_CHAR = 258;
+ private static final int WM_GETICON = 0x007F;
private static final int WM_SETICON = 0x0080;
+ private static final int WM_SETCURSOR = 0x0020;
+ private static final int WM_MOUSEACTIVATE = 0x0021;
private static final int WM_QUIT = 0x0012;
private static final int WM_SYSCOMMAND = 0x0112;
@@ -115,23 +131,53 @@
private static final int WA_INACTIVE = 0;
private static final int WA_ACTIVE = 1;
private static final int WA_CLICKACTIVE = 2;
+ private static final int SW_NORMAL = 1;
private static final int SW_SHOWMINNOACTIVE = 7;
private static final int SW_SHOWDEFAULT = 10;
private static final int SW_RESTORE = 9;
+ private static final int SW_MAXIMIZE = 3;
private static final int ICON_SMALL = 0;
private static final int ICON_BIG = 1;
private static final IntBuffer rect_buffer = BufferUtils.createIntBuffer(4);
private static final Rect rect = new Rect();
- private static final Rect rect2 = new Rect();
+
+ private static final long HWND_TOP = 0;
+ private static final long HWND_BOTTOM = 1;
+ private static final long HWND_TOPMOST = -1;
+ private static final long HWND_NOTOPMOST = -2;
+
+ private static final int SWP_NOSIZE = 0x0001;
+ private static final int SWP_NOMOVE = 0x0002;
+ private static final int SWP_NOZORDER = 0x0004;
+ private static final int SWP_FRAMECHANGED = 0x0020;
+
+ private static final int GWL_STYLE = -16;
+ private static final int GWL_EXSTYLE = -20;
+
+ private static final int WS_THICKFRAME = 0x00040000;
+ private static final int WS_MAXIMIZEBOX = 0x00010000;
+
+ private static final int HTCLIENT = 0x01;
+
+ private static final int MK_XBUTTON1 = 0x0020;
+ private static final int MK_XBUTTON2 = 0x0040;
+ private static final int XBUTTON1 = 0x0001;
+ private static final int XBUTTON2 = 0x0002;
+
private static WindowsDisplay current_display;
private static boolean cursor_clipped;
private WindowsDisplayPeerInfo peer_info;
private Object current_cursor;
+
+ private static boolean hasParent;
+
private Canvas parent;
- private static boolean hasParent;
+ private long parent_hwnd;
+ private FocusAdapter parent_focus_tracker;
+ private AtomicBoolean parent_focused;
private WindowsKeyboard keyboard;
private WindowsMouse mouse;
@@ -146,33 +192,47 @@
private boolean mode_set;
private boolean isMinimized;
private boolean isFocused;
- private boolean did_maximize;
+ private boolean redoMakeContextCurrent;
private boolean inAppActivate;
+ private boolean resized;
+ private boolean resizable;
+ private int x;
+ private int y;
+ private int width;
+ private int height;
private long hwnd;
private long hdc;
private long small_icon;
private long large_icon;
+ private boolean iconsLoaded;
private int captureMouse = -1;
- private boolean trackingMouse;
private boolean mouseInside;
+
+ static {
+ try {
+ Method windowProc = WindowsDisplay.class.getDeclaredMethod("handleMessage", long.class, int.class, long.class, long.class, long.class);
+ setWindowProc(windowProc);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
WindowsDisplay() {
current_display = this;
}
- public void createWindow(DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
- close_requested = false;
- is_dirty = false;
- isMinimized = false;
- isFocused = false;
- did_maximize = false;
+ public void createWindow(DrawableLWJGL drawable, DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException {
this.parent = parent;
hasParent = parent != null;
- long parent_hwnd = parent != null ? getHwnd(parent) : 0;
+ parent_hwnd = parent != null ? getHwnd(parent) : 0;
this.hwnd = nCreateWindow(x, y, mode.getWidth(), mode.getHeight(), Display.isFullscreen() || isUndecorated(), parent != null, parent_hwnd);
+ if ( Display.isResizable() && parent == null ) {
+ setResizable(true);
+ }
+
if (hwnd == 0) {
throw new LWJGLException("Failed to create window");
}
@@ -181,21 +241,51 @@
nDestroyWindow(hwnd);
throw new LWJGLException("Failed to get dc");
}
+
try {
- int format = WindowsPeerInfo.choosePixelFormat(getHdc(), 0, 0, peer_info.getPixelFormat(), null, true, true, false, true);
- WindowsPeerInfo.setPixelFormat(getHdc(), format);
+ if ( drawable instanceof DrawableGL ) {
+ int format = WindowsPeerInfo.choosePixelFormat(getHdc(), 0, 0, (PixelFormat)drawable.getPixelFormat(), null, true, true, false, true);
+ WindowsPeerInfo.setPixelFormat(getHdc(), format);
+ } else {
+ peer_info = new WindowsDisplayPeerInfo(true);
+ ((DrawableGLES)drawable).initialize(hwnd, hdc, EGL.EGL_WINDOW_BIT, (org.lwjgl.opengles.PixelFormat)drawable.getPixelFormat());
+ }
peer_info.initDC(getHwnd(), getHdc());
showWindow(getHwnd(), SW_SHOWDEFAULT);
- if (parent == null) {
+
+ updateWidthAndHeight();
+
+ if ( parent == null ) {
setForegroundWindow(getHwnd());
- setFocus(getHwnd());
- }
+ } else {
+ parent_focused = new AtomicBoolean(false);
+ parent.addFocusListener(parent_focus_tracker = new FocusAdapter() {
+ public void focusGained(FocusEvent e) {
+ parent_focused.set(true);
+ clearAWTFocus();
+ }
+ });
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ clearAWTFocus();
+ }
+ });
+ }
+ grabFocus();
} catch (LWJGLException e) {
nReleaseDC(hwnd, hdc);
nDestroyWindow(hwnd);
throw e;
}
}
+
+ private void updateWidthAndHeight() {
+ getClientRect(hwnd, rect_buffer);
+ rect.copyFromBuffer(rect_buffer);
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+ }
+
private static native long nCreateWindow(int x, int y, int width, int height, boolean undecorated, boolean child_window, long parent_hwnd) throws LWJGLException;
private static boolean isUndecorated() {
@@ -204,7 +294,7 @@
private static long getHwnd(Canvas parent) throws LWJGLException {
AWTCanvasImplementation awt_impl = AWTGLCanvas.createImplementation();
- WindowsPeerInfo parent_peer_info = (WindowsPeerInfo)awt_impl.createPeerInfo(parent, null);
+ WindowsPeerInfo parent_peer_info = (WindowsPeerInfo)awt_impl.createPeerInfo(parent, null, null);
ByteBuffer parent_peer_info_handle = parent_peer_info.lockAndGetHandle();
try {
return parent_peer_info.getHwnd();
@@ -214,11 +304,24 @@
}
public void destroyWindow() {
+ if ( parent != null ) {
+ parent.removeFocusListener(parent_focus_tracker);
+ parent_focus_tracker = null;
+ }
+
nReleaseDC(hwnd, hdc);
nDestroyWindow(hwnd);
freeLargeIcon();
freeSmallIcon();
resetCursorClipping();
+
+ // reset state
+ close_requested = false;
+ is_dirty = false;
+ isMinimized = false;
+ isFocused = false;
+ redoMakeContextCurrent = false;
+ mouseInside = false;
}
private static native void nReleaseDC(long hwnd, long hdc);
private static native void nDestroyWindow(long hwnd);
@@ -261,7 +364,7 @@
/*
* Called when the application is alt-tabbed to or from
*/
- private void appActivate(boolean active) {
+ private void appActivate(boolean active, long millis) {
if (inAppActivate) {
return;
}
@@ -272,24 +375,47 @@
restoreDisplayMode();
}
if (parent == null) {
- showWindow(getHwnd(), SW_RESTORE);
setForegroundWindow(getHwnd());
- setFocus(getHwnd());
- }
- did_maximize = true;
+ }
+ setFocus(getHwnd());
+ redoMakeContextCurrent = true;
if (Display.isFullscreen())
updateClipping();
- } else if (Display.isFullscreen()) {
- showWindow(getHwnd(), SW_SHOWMINNOACTIVE);
- resetDisplayMode();
- } else
- updateClipping();
+ } else {
+ if ( keyboard != null )
+ keyboard.releaseAll(millis);
+ if ( Display.isFullscreen() ) {
+ showWindow(getHwnd(), SW_SHOWMINNOACTIVE);
+ resetDisplayMode();
+ } else
+ updateClipping();
+ }
updateCursor();
inAppActivate = false;
}
private static native void showWindow(long hwnd, int mode);
private static native void setForegroundWindow(long hwnd);
private static native void setFocus(long hwnd);
+
+ private void clearAWTFocus() {
+ // This is needed so that the last focused component AWT remembers is NOT our Canvas
+ WindowsDisplay.this.parent.setFocusable(false);
+ WindowsDisplay.this.parent.setFocusable(true);
+
+ // Clear AWT focus owner
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ }
+
+ private void grabFocus() {
+ if ( parent == null )
+ setFocus(getHwnd());
+ else
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ parent.requestFocus();
+ }
+ });
+ }
private void restoreDisplayMode() {
try {
@@ -395,9 +521,10 @@
private static native DisplayMode getCurrentDisplayMode() throws LWJGLException;
public void setTitle(String title) {
- nSetTitle(hwnd, title);
- }
- private static native void nSetTitle(long hwnd, String title);
+ ByteBuffer buffer = MemoryUtil.encodeUTF16(title);
+ nSetTitle(hwnd, MemoryUtil.getAddress0(buffer));
+ }
+ private static native void nSetTitle(long hwnd, long title);
public boolean isCloseRequested() {
boolean saved = close_requested;
@@ -419,18 +546,20 @@
return saved;
}
- public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException {
- peer_info = new WindowsDisplayPeerInfo(pixel_format);
+ public PeerInfo createPeerInfo(PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException {
+ peer_info = new WindowsDisplayPeerInfo(false);
return peer_info;
}
public void update() {
nUpdate();
- if (parent != null && parent.isFocusOwner()) {
+
+ if ( !isFocused && parent != null && parent_focused.compareAndSet(true, false) ) {
setFocus(getHwnd());
}
- if (did_maximize) {
- did_maximize = false;
+
+ if (redoMakeContextCurrent) {
+ redoMakeContextCurrent = false;
/**
* WORKAROUND:
* Making the context current (redundantly) when the window
@@ -473,7 +602,7 @@
}
public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons) {
- mouse.poll(coord_buffer, buttons);
+ mouse.poll(coord_buffer, buttons, this);
}
public void readMouse(ByteBuffer buffer) {
@@ -565,11 +694,10 @@
/* Keyboard */
public void createKeyboard() throws LWJGLException {
- keyboard = new WindowsKeyboard(getHwnd());
+ keyboard = new WindowsKeyboard();
}
public void destroyKeyboard() {
- keyboard.destroy();
keyboard = null;
}
@@ -613,7 +741,7 @@
return ((WindowsPbufferPeerInfo)handle).isBufferLost();
}
- public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format,
+ public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, ContextAttribs attribs,
IntBuffer pixelFormatCaps,
IntBuffer pBufferAttribs) throws LWJGLException {
return new WindowsPbufferPeerInfo(width, height, pixel_format, pixelFormatCaps, pBufferAttribs);
@@ -668,18 +796,37 @@
int size = icon.limit() / 4;
if ( (((int)Math.sqrt(size)) == small_icon_size) && (!done_small) ) {
+ long small_new_icon = createIcon(small_icon_size, small_icon_size, icon.asIntBuffer());
+ sendMessage(hwnd, WM_SETICON, ICON_SMALL, small_new_icon);
freeSmallIcon();
- small_icon = createIcon(small_icon_size, small_icon_size, icon.asIntBuffer());
- sendMessage(hwnd, WM_SETICON, ICON_SMALL, small_icon);
+ small_icon = small_new_icon;
used++;
done_small = true;
}
if ( (((int)Math.sqrt(size)) == large_icon_size) && (!done_large) ) {
+ long large_new_icon = createIcon(large_icon_size, large_icon_size, icon.asIntBuffer());
+ sendMessage(hwnd, WM_SETICON, ICON_BIG, large_new_icon);
freeLargeIcon();
- large_icon = createIcon(large_icon_size, large_icon_size, icon.asIntBuffer());
- sendMessage(hwnd, WM_SETICON, ICON_BIG, large_icon);
+ large_icon = large_new_icon;
used++;
done_large = true;
+
+ // Problem: The taskbar icon won't update until Windows sends a WM_GETICON to our window proc and we reply. But this method is usually called
+ // on init and it might take a while before the next call to nUpdate (because of resources being loaded, etc). So we wait for the next
+ // WM_GETICON message (usually received about 100ms after WM_SETICON) to make sure the taskbar icon has updated before we return to the user.
+ // (We wouldn't need to do this if the event loop was running continuously on its own thread.)
+ iconsLoaded = false;
+
+ // Track how long the wait takes and give up at 500ms, just in case.
+ long time = System.nanoTime();
+ long MAX_WAIT = 500L * 1000L * 1000L;
+ while ( true ) {
+ nUpdate();
+ if ( iconsLoaded || MAX_WAIT < System.nanoTime() - time )
+ break;
+
+ Thread.yield();
+ }
}
}
@@ -688,6 +835,9 @@
private static native long createIcon(int width, int height, IntBuffer icon);
private static native void destroyIcon(long handle);
private static native long sendMessage(long hwnd, long msg, long wparam, long lparam);
+ private static native long setWindowLongPtr(long hwnd, int nindex, long longPtr);
+ private static native long getWindowLongPtr(long hwnd, int nindex);
+ private static native boolean setWindowPos(long hwnd, long hwnd_after, int x, int y, int cx, int cy, long uflags);
private void handleMouseButton(int button, int state, long millis) {
if (mouse != null) {
@@ -705,20 +855,10 @@
nReleaseCapture();
}
}
-
- if (parent != null && !isFocused) {
- setFocus(getHwnd());
- }
}
private boolean shouldGrab() {
return !isMinimized && isFocused && Mouse.isGrabbed();
- }
-
- private void handleMouseMoved(int x, int y, long millis) {
- if (mouse != null) {
- mouse.handleMouseMoved(x, y, millis, shouldGrab());
- }
}
private static native long nSetCapture(long hwnd);
@@ -736,18 +876,20 @@
byte state = (byte)(1 - ((lParam >>> 31) & 0x1));
boolean repeat = state == previous_state;
if (keyboard != null)
- keyboard.handleChar((int)(wParam & 0xFF), millis, repeat);
+ keyboard.handleChar((int)(wParam & 0xFFFF), millis, repeat);
}
private void handleKeyButton(long wParam, long lParam, long millis) {
+ if ( keyboard == null )
+ return;
+
byte previous_state = (byte)((lParam >>> 30) & 0x1);
byte state = (byte)(1 - ((lParam >>> 31) & 0x1));
boolean repeat = state == previous_state; // Repeat message
byte extended = (byte)((lParam >>> 24) & 0x1);
int scan_code = (int)((lParam >>> 16) & 0xFF);
- if (keyboard != null) {
- keyboard.handleKey((int)wParam, scan_code, extended != 0, state, millis, repeat);
- }
+
+ keyboard.handleKey((int)wParam, scan_code, extended != 0, state, millis, repeat);
}
private static int transformY(long hwnd, int y) {
@@ -758,18 +900,16 @@
private static native void clientToScreen(long hwnd, IntBuffer point);
- private static int handleMessage(long hwnd, int msg, long wParam, long lParam, long millis) {
+ private static native void setWindowProc(Method windowProc);
+
+ private static long handleMessage(long hwnd, int msg, long wParam, long lParam, long millis) {
if (current_display != null)
return current_display.doHandleMessage(hwnd, msg, wParam, lParam, millis);
else
return defWindowProc(hwnd, msg, wParam, lParam);
}
- private static native int defWindowProc(long hwnd, int msg, long wParam, long lParam);
-
- private void checkCursorState() {
- updateClipping();
- }
+ private static native long defWindowProc(long hwnd, int msg, long wParam, long lParam);
private void updateClipping() {
if ((Display.isFullscreen() || (mouse != null && mouse.isGrabbed())) && !isMinimized && isFocused && (getForegroundWindow() == getHwnd() || hasParent)) {
@@ -784,15 +924,37 @@
}
private void setMinimized(boolean m) {
- isMinimized = m;
- checkCursorState();
- }
-
- private int doHandleMessage(long hwnd, int msg, long wParam, long lParam, long millis) {
+ if ( m != isMinimized ) {
+ isMinimized = m;
+ updateClipping();
+ }
+ }
+
+ private long doHandleMessage(long hwnd, int msg, long wParam, long lParam, long millis) {
+ /*switch ( msg ) {
+ case 0x0:
+ case 0x0020:
+ case 0x0084:
+ case WM_MOUSEMOVE:
+ break;
+ default:
+ WindowsEventDebug.printMessage(msg, wParam, lParam);
+ }*/
+
+ if ( parent != null && !isFocused ) {
+ switch ( msg ) {
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_XBUTTONDOWN:
+ sendMessage(parent_hwnd, msg, wParam, lParam);
+ }
+ }
+
switch (msg) {
// disable screen saver and monitor power down messages which wreak havoc
case WM_ACTIVATE:
- switch ((int)wParam) {
+ /*switch ((int)wParam) {
case WA_ACTIVE:
case WA_CLICKACTIVE:
appActivate(true);
@@ -800,62 +962,106 @@
case WA_INACTIVE:
appActivate(false);
break;
- }
- return 0;
+ }*/
+ return 0L;
case WM_SIZE:
switch ((int)wParam) {
case SIZE_RESTORED:
case SIZE_MAXIMIZED:
+ resized = true;
+ updateWidthAndHeight();
setMinimized(false);
break;
case SIZE_MINIMIZED:
setMinimized(true);
break;
}
- return defWindowProc(hwnd, msg, wParam, lParam);
+ break;
+ case WM_SIZING:
+ resized = true;
+ updateWidthAndHeight();
+ break;
+ case WM_SETCURSOR:
+ if((lParam & 0xFFFF) == HTCLIENT) {
+ // if the cursor is inside the client area, reset it
+ // to the current LWJGL-cursor
+ updateCursor();
+ return -1; //TRUE
+ } else {
+ // let Windows handle cursors outside the client area for resizing, etc.
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ }
case WM_KILLFOCUS:
- appActivate(false);
- return 0;
+ appActivate(false, millis);
+ return 0L;
case WM_SETFOCUS:
- appActivate(true);
- return 0;
+ appActivate(true, millis);
+ return 0L;
+ case WM_MOUSEACTIVATE:
+ if ( parent != null ) {
+ if ( !isFocused )
+ grabFocus();
+ return 3L; // MA_NOACTIVATE
+ }
+ break;
case WM_MOUSEMOVE:
- int xPos = (int)(short)(lParam & 0xFFFF);
- int yPos = transformY(getHwnd(), (int)(short)((lParam >> 16) & 0xFFFF));
- handleMouseMoved(xPos, yPos, millis);
- checkCursorState();
- mouseInside = true;
- if(!trackingMouse) {
- trackingMouse = nTrackMouseEvent(hwnd);
- }
- return 0;
+ if ( mouse != null ) {
+ int xPos = (short)(lParam & 0xFFFF);
+ int yPos = transformY(getHwnd(), (short)(lParam >>> 16));
+ mouse.handleMouseMoved(xPos, yPos, millis);
+ }
+ if ( !mouseInside ) {
+ mouseInside = true;
+ updateClipping();
+ nTrackMouseEvent(hwnd);
+ }
+ return 0L;
case WM_MOUSEWHEEL:
int dwheel = (int)(short)((wParam >> 16) & 0xFFFF);
handleMouseScrolled(dwheel, millis);
- return 0;
+ return 0L;
case WM_LBUTTONDOWN:
handleMouseButton(0, 1, millis);
- return 0;
+ return 0L;
case WM_LBUTTONUP:
handleMouseButton(0, 0, millis);
- return 0;
+ return 0L;
case WM_RBUTTONDOWN:
handleMouseButton(1, 1, millis);
- return 0;
+ return 0L;
case WM_RBUTTONUP:
handleMouseButton(1, 0, millis);
- return 0;
+ return 0L;
case WM_MBUTTONDOWN:
handleMouseButton(2, 1, millis);
- return 0;
+ return 0L;
case WM_MBUTTONUP:
handleMouseButton(2, 0, millis);
- return 0;
+ return 0L;
+ case WM_XBUTTONUP:
+ if((wParam >> 16) == XBUTTON1) {
+ handleMouseButton(3, 0, millis);
+ } else {
+ handleMouseButton(4, 0, millis);
+ }
+ return 1;
+ case WM_XBUTTONDOWN:
+ if((wParam & 0xFF) == MK_XBUTTON1) {
+ handleMouseButton(3, 1, millis);
+ } else {
+ handleMouseButton(4, 1, millis);
+ }
+ return 1;
case WM_SYSCHAR:
case WM_CHAR:
handleChar(wParam, lParam, millis);
- return 0;
+ return 0L;
case WM_SYSKEYUP:
+ // Disable WM_SYSCOMMAND/SC_KEYMENU
+ if ( wParam == WindowsKeycodes.VK_MENU || wParam == WindowsKeycodes.VK_F10 ) {
+ handleKeyButton(wParam, lParam, millis);
+ return 0L;
+ }
/* Fall through */
case WM_KEYUP:
// SysRq apparently only generates WM_KEYUP, so we'll fake a WM_KEYDOWN
@@ -872,31 +1078,26 @@
/* Fall through */
case WM_KEYDOWN:
handleKeyButton(wParam, lParam, millis);
- return defWindowProc(hwnd, msg, wParam, lParam);
+ break;
case WM_QUIT:
close_requested = true;
- return 0;
+ return 0L;
case WM_SYSCOMMAND:
switch ((int)(wParam & 0xfff0)) {
- case SC_KEYMENU:
- case SC_MOUSEMENU:
case SC_SCREENSAVE:
case SC_MONITORPOWER:
- return 0;
+ return 0L;
case SC_CLOSE:
close_requested = true;
- return 0;
- default:
- break;
- }
- return defWindowProc(hwnd, msg, wParam, lParam);
+ return 0L;
+ }
+ break;
case WM_PAINT:
is_dirty = true;
- return defWindowProc(hwnd, msg, wParam, lParam);
- case WM_MOUSELEAVE:
- mouseInside = false;
- trackingMouse = false;
- return defWindowProc(hwnd, msg, wParam, lParam);
+ break;
+ case WM_MOUSELEAVE:
+ mouseInside = false;
+ break;
case WM_CANCELMODE:
nReleaseCapture();
/* fall through */
@@ -905,68 +1106,140 @@
handleMouseButton(captureMouse, 0, millis);
captureMouse = -1;
}
- return 0;
- default:
- return defWindowProc(hwnd, msg, wParam, lParam);
- }
+ return 0L;
+ case WM_WINDOWPOSCHANGED:
+ if(getWindowRect(hwnd, rect_buffer)) {
+ rect.copyFromBuffer(rect_buffer);
+ x = rect.left;
+ y = rect.top;
+ } else {
+ LWJGLUtil.log("WM_WINDOWPOSCHANGED: Unable to get window rect");
+ }
+ break;
+ case WM_GETICON:
+ iconsLoaded = true;
+ break;
+ }
+
+ return defWindowProc(hwnd, msg, wParam, lParam);
+ }
+
+ private native boolean getWindowRect(long hwnd, IntBuffer rectBuffer);
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
}
public int getWidth() {
- return Display.getDisplayMode().getWidth();
+ return width;
}
public int getHeight() {
- return Display.getDisplayMode().getHeight();
- }
-
- private int firstMouseButtonDown() {
- for(int i=0; i
- * @version $Revision: 3116 $
- * $Id: WindowsDisplayPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class WindowsDisplayPeerInfo extends WindowsPeerInfo {
- private final PixelFormat pixel_format;
- WindowsDisplayPeerInfo(PixelFormat pixel_format) throws LWJGLException {
- this.pixel_format = pixel_format;
- GLContext.loadOpenGLLibrary();
- }
+ final boolean egl;
- PixelFormat getPixelFormat() {
- return pixel_format;
+ WindowsDisplayPeerInfo(boolean egl) throws LWJGLException {
+ this.egl = egl;
+
+ if ( egl)
+ org.lwjgl.opengles.GLContext.loadOpenGLLibrary();
+ else
+ GLContext.loadOpenGLLibrary();
}
void initDC(long hwnd, long hdc) throws LWJGLException {
@@ -68,6 +69,10 @@
public void destroy() {
super.destroy();
- GLContext.unloadOpenGLLibrary();
+
+ if ( egl )
+ org.lwjgl.opengles.GLContext.unloadOpenGLLibrary();
+ else
+ GLContext.unloadOpenGLLibrary();
}
}
diff --git a/src/java/org/lwjgl/opengl/WindowsEventDebug.java b/src/java/org/lwjgl/opengl/WindowsEventDebug.java
new file mode 100644
index 0000000..61ec239
--- /dev/null
+++ b/src/java/org/lwjgl/opengl/WindowsEventDebug.java
@@ -0,0 +1,483 @@
+package org.lwjgl.opengl;
+
+import org.lwjgl.LWJGLUtil;
+
+final class WindowsEventDebug {
+
+ private WindowsEventDebug() {
+ }
+
+ static int printMessage(String msg, long wParam, long lParam) {
+ System.out.println(msg + ": 0x" + Long.toHexString(wParam).toUpperCase() + " | " + Long.toHexString(lParam).toUpperCase());
+ return 0;
+ }
+
+ static int printMessage(int msg, long wParam, long lParam) {
+ System.out.print(LWJGLUtil.toHexString(msg) + ": ");
+ switch ( msg ) {
+ case 0x0000:
+ return printMessage("WM_NULL", wParam, lParam);
+ case 0x0001:
+ return printMessage("WM_CREATE", wParam, lParam);
+ case 0x0002:
+ return printMessage("WM_DESTROY", wParam, lParam);
+ case 0x0003:
+ return printMessage("WM_MOVE", wParam, lParam);
+ case 0x0005:
+ return printMessage("WM_SIZE", wParam, lParam);
+ case 0x0006:
+ return printMessage("WM_ACTIVATE", wParam, lParam);
+ case 0x0007:
+ return printMessage("WM_SETFOCUS", wParam, lParam);
+ case 0x0008:
+ return printMessage("WM_KILLFOCUS", wParam, lParam);
+ case 0x000A:
+ return printMessage("WM_ENABLE", wParam, lParam);
+ case 0x000B:
+ return printMessage("WM_SETREDRAW", wParam, lParam);
+ case 0x000C:
+ return printMessage("WM_SETTEXT", wParam, lParam);
+ case 0x000D:
+ return printMessage("WM_GETTEXT", wParam, lParam);
+ case 0x000E:
+ return printMessage("WM_GETTEXTLENGTH", wParam, lParam);
+ case 0x000F:
+ return printMessage("WM_PAINT", wParam, lParam);
+ case 0x0010:
+ return printMessage("WM_CLOSE", wParam, lParam);
+ case 0x0011:
+ return printMessage("WM_QUERYENDSESSION", wParam, lParam);
+ case 0x0013:
+ return printMessage("WM_QUERYOPEN", wParam, lParam);
+ case 0x0016:
+ return printMessage("WM_ENDSESSION", wParam, lParam);
+ case 0x0012:
+ return printMessage("WM_QUIT", wParam, lParam);
+ case 0x0014:
+ return printMessage("WM_ERASEBKGND", wParam, lParam);
+ case 0x0015:
+ return printMessage("WM_SYSCOLORCHANGE", wParam, lParam);
+ case 0x0018:
+ return printMessage("WM_SHOWWINDOW", wParam, lParam);
+ case 0x001A:
+ return printMessage("WM_WININICHANGE", wParam, lParam);
+ case 0x001B:
+ return printMessage("WM_DEVMODECHANGE", wParam, lParam);
+ case 0x001C:
+ return printMessage("WM_ACTIVATEAPP", wParam, lParam);
+ case 0x001D:
+ return printMessage("WM_FONTCHANGE", wParam, lParam);
+ case 0x001E:
+ return printMessage("WM_TIMECHANGE", wParam, lParam);
+ case 0x001F:
+ return printMessage("WM_CANCELMODE", wParam, lParam);
+ case 0x0020:
+ return printMessage("WM_SETCURSOR", wParam, lParam);
+ case 0x0021:
+ return printMessage("WM_MOUSEACTIVATE", wParam, lParam);
+ case 0x0022:
+ return printMessage("WM_CHILDACTIVATE", wParam, lParam);
+ case 0x0023:
+ return printMessage("WM_QUEUESYNC", wParam, lParam);
+ case 0x0024:
+ return printMessage("WM_GETMINMAXINFO", wParam, lParam);
+ case 0x0026:
+ return printMessage("WM_PAINTICON", wParam, lParam);
+ case 0x0027:
+ return printMessage("WM_ICONERASEBKGND", wParam, lParam);
+ case 0x0028:
+ return printMessage("WM_NEXTDLGCTL", wParam, lParam);
+ case 0x002A:
+ return printMessage("WM_SPOOLERSTATUS", wParam, lParam);
+ case 0x002B:
+ return printMessage("WM_DRAWITEM", wParam, lParam);
+ case 0x002C:
+ return printMessage("WM_MEASUREITEM", wParam, lParam);
+ case 0x002D:
+ return printMessage("WM_DELETEITEM", wParam, lParam);
+ case 0x002E:
+ return printMessage("WM_VKEYTOITEM", wParam, lParam);
+ case 0x002F:
+ return printMessage("WM_CHARTOITEM", wParam, lParam);
+ case 0x0030:
+ return printMessage("WM_SETFONT", wParam, lParam);
+ case 0x0031:
+ return printMessage("WM_GETFONT", wParam, lParam);
+ case 0x0032:
+ return printMessage("WM_SETHOTKEY", wParam, lParam);
+ case 0x0033:
+ return printMessage("WM_GETHOTKEY", wParam, lParam);
+ case 0x0037:
+ return printMessage("WM_QUERYDRAGICON", wParam, lParam);
+ case 0x0039:
+ return printMessage("WM_COMPAREITEM", wParam, lParam);
+ case 0x003D:
+ return printMessage("WM_GETOBJECT", wParam, lParam);
+ case 0x0041:
+ return printMessage("WM_COMPACTING", wParam, lParam);
+ case 0x0044:
+ return printMessage("WM_COMMNOTIFY", wParam, lParam);
+ case 0x0046:
+ return printMessage("WM_WINDOWPOSCHANGING", wParam, lParam);
+ case 0x0047:
+ return printMessage("WM_WINDOWPOSCHANGED", wParam, lParam);
+ case 0x0048:
+ return printMessage("WM_POWER", wParam, lParam);
+ case 0x004A:
+ return printMessage("WM_COPYDATA", wParam, lParam);
+ case 0x004B:
+ return printMessage("WM_CANCELJOURNAL", wParam, lParam);
+ case 0x004E:
+ return printMessage("WM_NOTIFY", wParam, lParam);
+ case 0x0050:
+ return printMessage("WM_INPUTLANGCHANGEREQUEST", wParam, lParam);
+ case 0x0051:
+ return printMessage("WM_INPUTLANGCHANGE", wParam, lParam);
+ case 0x0052:
+ return printMessage("WM_TCARD", wParam, lParam);
+ case 0x0053:
+ return printMessage("WM_HELP", wParam, lParam);
+ case 0x0054:
+ return printMessage("WM_USERCHANGED", wParam, lParam);
+ case 0x0055:
+ return printMessage("WM_NOTIFYFORMAT", wParam, lParam);
+ case 0x007B:
+ return printMessage("WM_CONTEXTMENU", wParam, lParam);
+ case 0x007C:
+ return printMessage("WM_STYLECHANGING", wParam, lParam);
+ case 0x007D:
+ return printMessage("WM_STYLECHANGED", wParam, lParam);
+ case 0x007E:
+ return printMessage("WM_DISPLAYCHANGE", wParam, lParam);
+ case 0x007F:
+ return printMessage("WM_GETICON", wParam, lParam);
+ case 0x0080:
+ return printMessage("WM_SETICON", wParam, lParam);
+ case 0x0081:
+ return printMessage("WM_NCCREATE", wParam, lParam);
+ case 0x0082:
+ return printMessage("WM_NCDESTROY", wParam, lParam);
+ case 0x0083:
+ return printMessage("WM_NCCALCSIZE", wParam, lParam);
+ case 0x0084:
+ return printMessage("WM_NCHITTEST", wParam, lParam);
+ case 0x0085:
+ return printMessage("WM_NCPAINT", wParam, lParam);
+ case 0x0086:
+ return printMessage("WM_NCACTIVATE", wParam, lParam);
+ case 0x0087:
+ return printMessage("WM_GETDLGCODE", wParam, lParam);
+ case 0x0088:
+ return printMessage("WM_SYNCPAINT", wParam, lParam);
+ case 0x00A0:
+ return printMessage("WM_NCMOUSEMOVE", wParam, lParam);
+ case 0x00A1:
+ return printMessage("WM_NCLBUTTONDOWN", wParam, lParam);
+ case 0x00A2:
+ return printMessage("WM_NCLBUTTONUP", wParam, lParam);
+ case 0x00A3:
+ return printMessage("WM_NCLBUTTONDBLCLK", wParam, lParam);
+ case 0x00A4:
+ return printMessage("WM_NCRBUTTONDOWN", wParam, lParam);
+ case 0x00A5:
+ return printMessage("WM_NCRBUTTONUP", wParam, lParam);
+ case 0x00A6:
+ return printMessage("WM_NCRBUTTONDBLCLK", wParam, lParam);
+ case 0x00A7:
+ return printMessage("WM_NCMBUTTONDOWN", wParam, lParam);
+ case 0x00A8:
+ return printMessage("WM_NCMBUTTONUP", wParam, lParam);
+ case 0x00A9:
+ return printMessage("WM_NCMBUTTONDBLCLK", wParam, lParam);
+ case 0x00AB:
+ return printMessage("WM_NCXBUTTONDOWN", wParam, lParam);
+ case 0x00AC:
+ return printMessage("WM_NCXBUTTONUP", wParam, lParam);
+ case 0x00AD:
+ return printMessage("WM_NCXBUTTONDBLCLK", wParam, lParam);
+ case 0x00FE:
+ return printMessage("WM_INPUT_DEVICE_CHANGE", wParam, lParam);
+ case 0x00FF:
+ return printMessage("WM_INPUT", wParam, lParam);
+ case 0x0100:
+ return printMessage("WM_KEYDOWN", wParam, lParam);
+ case 0x0101:
+ return printMessage("WM_KEYUP", wParam, lParam);
+ case 0x0102:
+ return printMessage("WM_CHAR", wParam, lParam);
+ case 0x0103:
+ return printMessage("WM_DEADCHAR", wParam, lParam);
+ case 0x0104:
+ return printMessage("WM_SYSKEYDOWN", wParam, lParam);
+ case 0x0105:
+ return printMessage("WM_SYSKEYUP", wParam, lParam);
+ case 0x0106:
+ return printMessage("WM_SYSCHAR", wParam, lParam);
+ case 0x0107:
+ return printMessage("WM_SYSDEADCHAR", wParam, lParam);
+ case 0x0109:
+ return printMessage("WM_UNICHAR", wParam, lParam);
+ case 0xFFFF:
+ return printMessage("UNICODE_NOCHAR", wParam, lParam);
+ case 0x0108:
+ return printMessage("WM_KEYLAST", wParam, lParam);
+ case 0x010D:
+ return printMessage("WM_IME_STARTCOMPOSITION", wParam, lParam);
+ case 0x010E:
+ return printMessage("WM_IME_ENDCOMPOSITION", wParam, lParam);
+ case 0x010F:
+ return printMessage("WM_IME_COMPOSITION", wParam, lParam);
+ case 0x0110:
+ return printMessage("WM_INITDIALOG", wParam, lParam);
+ case 0x0111:
+ return printMessage("WM_COMMAND", wParam, lParam);
+ case 0x0112:
+ return printMessage("WM_SYSCOMMAND", wParam, lParam);
+ case 0x0113:
+ return printMessage("WM_TIMER", wParam, lParam);
+ case 0x0114:
+ return printMessage("WM_HSCROLL", wParam, lParam);
+ case 0x0115:
+ return printMessage("WM_VSCROLL", wParam, lParam);
+ case 0x0116:
+ return printMessage("WM_INITMENU", wParam, lParam);
+ case 0x0117:
+ return printMessage("WM_INITMENUPOPUP", wParam, lParam);
+ case 0x0119:
+ return printMessage("WM_GESTURE", wParam, lParam);
+ case 0x011A:
+ return printMessage("WM_GESTURENOTIFY", wParam, lParam);
+ case 0x011F:
+ return printMessage("WM_MENUSELECT", wParam, lParam);
+ case 0x0120:
+ return printMessage("WM_MENUCHAR", wParam, lParam);
+ case 0x0121:
+ return printMessage("WM_ENTERIDLE", wParam, lParam);
+ case 0x0122:
+ return printMessage("WM_MENURBUTTONUP", wParam, lParam);
+ case 0x0123:
+ return printMessage("WM_MENUDRAG", wParam, lParam);
+ case 0x0124:
+ return printMessage("WM_MENUGETOBJECT", wParam, lParam);
+ case 0x0125:
+ return printMessage("WM_UNINITMENUPOPUP", wParam, lParam);
+ case 0x0126:
+ return printMessage("WM_MENUCOMMAND", wParam, lParam);
+ case 0x0127:
+ return printMessage("WM_CHANGEUISTATE", wParam, lParam);
+ case 0x0128:
+ return printMessage("WM_UPDATEUISTATE", wParam, lParam);
+ case 0x0129:
+ return printMessage("WM_QUERYUISTATE", wParam, lParam);
+ case 0x0132:
+ return printMessage("WM_CTLCOLORMSGBOX", wParam, lParam);
+ case 0x0133:
+ return printMessage("WM_CTLCOLOREDIT", wParam, lParam);
+ case 0x0134:
+ return printMessage("WM_CTLCOLORLISTBOX", wParam, lParam);
+ case 0x0135:
+ return printMessage("WM_CTLCOLORBTN", wParam, lParam);
+ case 0x0136:
+ return printMessage("WM_CTLCOLORDLG", wParam, lParam);
+ case 0x0137:
+ return printMessage("WM_CTLCOLORSCROLLBAR", wParam, lParam);
+ case 0x0138:
+ return printMessage("WM_CTLCOLORSTATIC", wParam, lParam);
+ case 0x01E1:
+ return printMessage("MN_GETHMENU", wParam, lParam);
+ case 0x0200:
+ return printMessage("WM_MOUSEMOVE", wParam, lParam);
+ case 0x0201:
+ return printMessage("WM_LBUTTONDOWN", wParam, lParam);
+ case 0x0202:
+ return printMessage("WM_LBUTTONUP", wParam, lParam);
+ case 0x0203:
+ return printMessage("WM_LBUTTONDBLCLK", wParam, lParam);
+ case 0x0204:
+ return printMessage("WM_RBUTTONDOWN", wParam, lParam);
+ case 0x0205:
+ return printMessage("WM_RBUTTONUP", wParam, lParam);
+ case 0x0206:
+ return printMessage("WM_RBUTTONDBLCLK", wParam, lParam);
+ case 0x0207:
+ return printMessage("WM_MBUTTONDOWN", wParam, lParam);
+ case 0x0208:
+ return printMessage("WM_MBUTTONUP", wParam, lParam);
+ case 0x0209:
+ return printMessage("WM_MBUTTONDBLCLK", wParam, lParam);
+ case 0x020A:
+ return printMessage("WM_MOUSEWHEEL", wParam, lParam);
+ case 0x020B:
+ return printMessage("WM_XBUTTONDOWN", wParam, lParam);
+ case 0x020C:
+ return printMessage("WM_XBUTTONUP", wParam, lParam);
+ case 0x020D:
+ return printMessage("WM_XBUTTONDBLCLK", wParam, lParam);
+ case 0x020E:
+ return printMessage("WM_MOUSEHWHEEL", wParam, lParam);
+ case 0x0210:
+ return printMessage("WM_PARENTNOTIFY", wParam, lParam);
+ case 0x0211:
+ return printMessage("WM_ENTERMENULOOP", wParam, lParam);
+ case 0x0212:
+ return printMessage("WM_EXITMENULOOP", wParam, lParam);
+ case 0x0213:
+ return printMessage("WM_NEXTMENU", wParam, lParam);
+ case 0x0214:
+ return printMessage("WM_SIZING", wParam, lParam);
+ case 0x0215:
+ return printMessage("WM_CAPTURECHANGED", wParam, lParam);
+ case 0x0216:
+ return printMessage("WM_MOVING", wParam, lParam);
+ case 0x0218:
+ return printMessage("WM_POWERBROADCAST", wParam, lParam);
+ case 0x8013:
+ return printMessage("PBT_POWERSETTINGCHANGE", wParam, lParam);
+ case 0x0219:
+ return printMessage("WM_DEVICECHANGE", wParam, lParam);
+ case 0x0220:
+ return printMessage("WM_MDICREATE", wParam, lParam);
+ case 0x0221:
+ return printMessage("WM_MDIDESTROY", wParam, lParam);
+ case 0x0222:
+ return printMessage("WM_MDIACTIVATE", wParam, lParam);
+ case 0x0223:
+ return printMessage("WM_MDIRESTORE", wParam, lParam);
+ case 0x0224:
+ return printMessage("WM_MDINEXT", wParam, lParam);
+ case 0x0225:
+ return printMessage("WM_MDIMAXIMIZE", wParam, lParam);
+ case 0x0226:
+ return printMessage("WM_MDITILE", wParam, lParam);
+ case 0x0227:
+ return printMessage("WM_MDICASCADE", wParam, lParam);
+ case 0x0228:
+ return printMessage("WM_MDIICONARRANGE", wParam, lParam);
+ case 0x0229:
+ return printMessage("WM_MDIGETACTIVE", wParam, lParam);
+ case 0x0230:
+ return printMessage("WM_MDISETMENU", wParam, lParam);
+ case 0x0231:
+ return printMessage("WM_ENTERSIZEMOVE", wParam, lParam);
+ case 0x0232:
+ return printMessage("WM_EXITSIZEMOVE", wParam, lParam);
+ case 0x0233:
+ return printMessage("WM_DROPFILES", wParam, lParam);
+ case 0x0234:
+ return printMessage("WM_MDIREFRESHMENU", wParam, lParam);
+ case 0x0240:
+ return printMessage("WM_TOUCH", wParam, lParam);
+ case 0x0281:
+ return printMessage("WM_IME_SETCONTEXT", wParam, lParam);
+ case 0x0282:
+ return printMessage("WM_IME_NOTIFY", wParam, lParam);
+ case 0x0283:
+ return printMessage("WM_IME_CONTROL", wParam, lParam);
+ case 0x0284:
+ return printMessage("WM_IME_COMPOSITIONFULL", wParam, lParam);
+ case 0x0285:
+ return printMessage("WM_IME_SELECT", wParam, lParam);
+ case 0x0286:
+ return printMessage("WM_IME_CHAR", wParam, lParam);
+ case 0x0288:
+ return printMessage("WM_IME_REQUEST", wParam, lParam);
+ case 0x0290:
+ return printMessage("WM_IME_KEYDOWN", wParam, lParam);
+ case 0x0291:
+ return printMessage("WM_IME_KEYUP", wParam, lParam);
+ case 0x02A1:
+ return printMessage("WM_MOUSEHOVER", wParam, lParam);
+ case 0x02A3:
+ return printMessage("WM_MOUSELEAVE", wParam, lParam);
+ case 0x02A0:
+ return printMessage("WM_NCMOUSEHOVER", wParam, lParam);
+ case 0x02A2:
+ return printMessage("WM_NCMOUSELEAVE", wParam, lParam);
+ case 0x02B1:
+ return printMessage("WM_WTSSESSION_CHANGE", wParam, lParam);
+ case 0x02c0:
+ return printMessage("WM_TABLET_FIRST", wParam, lParam);
+ case 0x02df:
+ return printMessage("WM_TABLET_LAST", wParam, lParam);
+ case 0x0300:
+ return printMessage("WM_CUT", wParam, lParam);
+ case 0x0301:
+ return printMessage("WM_COPY", wParam, lParam);
+ case 0x0302:
+ return printMessage("WM_PASTE", wParam, lParam);
+ case 0x0303:
+ return printMessage("WM_CLEAR", wParam, lParam);
+ case 0x0304:
+ return printMessage("WM_UNDO", wParam, lParam);
+ case 0x0305:
+ return printMessage("WM_RENDERFORMAT", wParam, lParam);
+ case 0x0306:
+ return printMessage("WM_RENDERALLFORMATS", wParam, lParam);
+ case 0x0307:
+ return printMessage("WM_DESTROYCLIPBOARD", wParam, lParam);
+ case 0x0308:
+ return printMessage("WM_DRAWCLIPBOARD", wParam, lParam);
+ case 0x0309:
+ return printMessage("WM_PAINTCLIPBOARD", wParam, lParam);
+ case 0x030A:
+ return printMessage("WM_VSCROLLCLIPBOARD", wParam, lParam);
+ case 0x030B:
+ return printMessage("WM_SIZECLIPBOARD", wParam, lParam);
+ case 0x030C:
+ return printMessage("WM_ASKCBFORMATNAME", wParam, lParam);
+ case 0x030D:
+ return printMessage("WM_CHANGECBCHAIN", wParam, lParam);
+ case 0x030E:
+ return printMessage("WM_HSCROLLCLIPBOARD", wParam, lParam);
+ case 0x030F:
+ return printMessage("WM_QUERYNEWPALETTE", wParam, lParam);
+ case 0x0310:
+ return printMessage("WM_PALETTEISCHANGING", wParam, lParam);
+ case 0x0311:
+ return printMessage("WM_PALETTECHANGED", wParam, lParam);
+ case 0x0312:
+ return printMessage("WM_HOTKEY", wParam, lParam);
+ case 0x0317:
+ return printMessage("WM_PRINT", wParam, lParam);
+ case 0x0318:
+ return printMessage("WM_PRINTCLIENT", wParam, lParam);
+ case 0x0319:
+ return printMessage("WM_APPCOMMAND", wParam, lParam);
+ case 0x031A:
+ return printMessage("WM_THEMECHANGED", wParam, lParam);
+ case 0x031D:
+ return printMessage("WM_CLIPBOARDUPDATE", wParam, lParam);
+ case 0x031E:
+ return printMessage("WM_DWMCOMPOSITIONCHANGED", wParam, lParam);
+ case 0x031F:
+ return printMessage("WM_DWMNCRENDERINGCHANGED", wParam, lParam);
+ case 0x0320:
+ return printMessage("WM_DWMCOLORIZATIONCOLORCHANGED", wParam, lParam);
+ case 0x0321:
+ return printMessage("WM_DWMWINDOWMAXIMIZEDCHANGE", wParam, lParam);
+ case 0x0323:
+ return printMessage("WM_DWMSENDICONICTHUMBNAIL", wParam, lParam);
+ case 0x0326:
+ return printMessage("WM_DWMSENDICONICLIVEPREVIEWBITMAP", wParam, lParam);
+ case 0x033F:
+ return printMessage("WM_GETTITLEBARINFOEX", wParam, lParam);
+ case 0x0358:
+ return printMessage("WM_HANDHELDFIRST", wParam, lParam);
+ case 0x035F:
+ return printMessage("WM_HANDHELDLAST", wParam, lParam);
+ case 0x0360:
+ return printMessage("WM_AFXFIRST", wParam, lParam);
+ case 0x037F:
+ return printMessage("WM_AFXLAST", wParam, lParam);
+ case 0x0380:
+ return printMessage("WM_PENWINFIRST", wParam, lParam);
+ case 0x038F:
+ return printMessage("WM_PENWINLAST", wParam, lParam);
+ case 0x8000:
+ return printMessage("WM_APP", wParam, lParam);
+ default:
+ return printMessage("", wParam, lParam);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengl/WindowsKeyboard.java b/src/java/org/lwjgl/opengl/WindowsKeyboard.java
index 92ab149..ed1c932 100644
--- a/src/java/org/lwjgl/opengl/WindowsKeyboard.java
+++ b/src/java/org/lwjgl/opengl/WindowsKeyboard.java
@@ -39,22 +39,15 @@
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
-import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
final class WindowsKeyboard {
- private static final int MAPVK_VK_TO_VSC = 0;
- private static final int BUFFER_SIZE = 50;
-
- private final long hwnd;
- private final ByteBuffer keyboard_state;
private final byte[] key_down_buffer = new byte[Keyboard.KEYBOARD_SIZE];
+ private final byte[] virt_key_down_buffer = new byte[Keyboard.KEYBOARD_SIZE];
private final EventQueue event_queue = new EventQueue(Keyboard.EVENT_SIZE);
private final ByteBuffer tmp_event = ByteBuffer.allocate(Keyboard.EVENT_SIZE);
-
- private boolean grabbed;
private boolean has_retained_event; // Indicates if we're waiting for a WM_CHAR
private int retained_key_code;
@@ -63,32 +56,26 @@
private long retained_millis;
private boolean retained_repeat;
- WindowsKeyboard(long hwnd) throws LWJGLException {
- this.hwnd = hwnd;
- keyboard_state = BufferUtils.createByteBuffer(256);
+ WindowsKeyboard() throws LWJGLException {
}
+
private static native boolean isWindowsNT();
-
- public void destroy() {
- }
boolean isKeyDown(int lwjgl_keycode) {
return key_down_buffer[lwjgl_keycode] == 1;
}
- public void grab(boolean grab) {
- if(grab) {
- if (!grabbed) {
- grabbed = true;
- }
- } else {
- if (grabbed) {
- grabbed = false;
- }
- }
- }
+ void poll(ByteBuffer keyDownBuffer) {
+ // Handle shift key release while both are pressed.
+ // Windows will not send an up event for the first button that was released in this case.
+ // There will only be one up event, for the last button only. We handle this problem
+ // here, using asynchronous state queries.
+ if ( isKeyDown(Keyboard.KEY_LSHIFT) && !isKeyPressedAsync(WindowsKeycodes.VK_LSHIFT) )
+ handleKey(WindowsKeycodes.VK_SHIFT, Keyboard.KEY_LSHIFT, false, (byte)0, 0L, false);
- public void poll(ByteBuffer keyDownBuffer) {
+ if ( isKeyDown(Keyboard.KEY_RSHIFT) && !isKeyPressedAsync(WindowsKeycodes.VK_RSHIFT) )
+ handleKey(WindowsKeycodes.VK_SHIFT, Keyboard.KEY_RSHIFT, false, (byte)0, 0L, false);
+
int old_position = keyDownBuffer.position();
keyDownBuffer.put(key_down_buffer);
keyDownBuffer.position(old_position);
@@ -98,7 +85,8 @@
private static native int ToUnicode(int wVirtKey, int wScanCode, ByteBuffer lpKeyState, CharBuffer pwszBuff, int cchBuff, int flags);
private static native int ToAscii(int wVirtKey, int wScanCode, ByteBuffer lpKeyState, ByteBuffer lpChar, int flags);
private static native int GetKeyboardState(ByteBuffer lpKeyState);
- private static native int GetKeyState(int virt_key);
+ private static native short GetKeyState(int virt_key);
+ private static native short GetAsyncKeyState(int virt_key);
private void putEvent(int keycode, byte state, int ch, long millis, boolean repeat) {
tmp_event.clear();
@@ -107,33 +95,10 @@
event_queue.putEvent(tmp_event);
}
- private boolean checkShiftKey(int virt_key, byte state) {
- int key_state = (GetKeyState(virt_key) >>> 15) & 0x1;
- int lwjgl_code = WindowsKeycodes.mapVirtualKeyToLWJGLCode(virt_key);
- return (key_down_buffer[lwjgl_code] == 1 - state) && (key_state == state);
- }
-
- private int translateShift(int scan_code, byte state) {
- if (checkShiftKey(WindowsKeycodes.VK_LSHIFT, state)) {
- return WindowsKeycodes.VK_LSHIFT;
- } else if (checkShiftKey(WindowsKeycodes.VK_RSHIFT, state)) {
- return WindowsKeycodes.VK_RSHIFT;
- } else {
- if (scan_code== 0x2A)
- return WindowsKeycodes.VK_LSHIFT;
- else {
- if (scan_code == 0x36)
- return WindowsKeycodes.VK_RSHIFT;
- else
- return WindowsKeycodes.VK_LSHIFT;
- }
- }
- }
-
- private int translateExtended(int virt_key, int scan_code, byte state, boolean extended) {
+ private static int translateExtended(int virt_key, int scan_code, boolean extended) {
switch (virt_key) {
case WindowsKeycodes.VK_SHIFT:
- return translateShift(scan_code, state);
+ return scan_code == 0x36 ? WindowsKeycodes.VK_RSHIFT : WindowsKeycodes.VK_LSHIFT;
case WindowsKeycodes.VK_CONTROL:
return extended ? WindowsKeycodes.VK_RCONTROL : WindowsKeycodes.VK_LCONTROL;
case WindowsKeycodes.VK_MENU:
@@ -150,13 +115,39 @@
}
}
- public void handleKey(int virt_key, int scan_code, boolean extended, byte event_state, long millis, boolean repeat) {
- virt_key = translateExtended(virt_key, scan_code, event_state, extended);
+ private static boolean isKeyPressed(int state) {
+ return (state & 1) == 1;
+ }
+
+ private static boolean isKeyPressedAsync(int virt_key) {
+ return (GetAsyncKeyState(virt_key) & 0x8000) != 0;
+ }
+
+ /**
+ * This is called when the window loses focus: we release all currently pressed keys. If a key has been pressed (or hasn't been released at all), before we
+ * regain focus, we'll start receiving repeat press events. We'll treat the first of those as a non-repeat press.
+ */
+ void releaseAll(long millis) {
+ for ( int i = 0; i < virt_key_down_buffer.length; i++ ) {
+ if ( isKeyPressed(virt_key_down_buffer[i]) ) {
+ handleKey(i, 0, false, (byte)0, millis, false);
+ }
+ }
+ }
+
+ void handleKey(int virt_key, int scan_code, boolean extended, byte event_state, long millis, boolean repeat) {
+ virt_key = translateExtended(virt_key, scan_code, extended);
+ if ( !repeat && isKeyPressed(event_state) == isKeyPressed(virt_key_down_buffer[virt_key]) )
+ return;
+
flushRetained();
has_retained_event = true;
int keycode = WindowsKeycodes.mapVirtualKeyToLWJGLCode(virt_key);
- if (keycode < key_down_buffer.length)
+ if (keycode < key_down_buffer.length) {
key_down_buffer[keycode] = event_state;
+ repeat &= isKeyPressed(virt_key_down_buffer[virt_key]); // Treat the first repeat event after releaseAll() as a non-repeat press.
+ virt_key_down_buffer[virt_key] = event_state;
+ }
retained_key_code = keycode;
retained_state = event_state;
retained_millis = millis;
@@ -164,7 +155,7 @@
retained_repeat = repeat;
}
- public void handleChar(int event_char, long millis, boolean repeat) {
+ void handleChar(int event_char, long millis, boolean repeat) {
if (has_retained_event && retained_char != 0)
flushRetained();
if (!has_retained_event) {
@@ -173,7 +164,7 @@
retained_char = event_char;
}
- public void read(ByteBuffer buffer) {
+ void read(ByteBuffer buffer) {
flushRetained();
event_queue.copyEvents(buffer);
}
diff --git a/src/java/org/lwjgl/opengl/WindowsMouse.java b/src/java/org/lwjgl/opengl/WindowsMouse.java
index 50d556a..0369e32 100644
--- a/src/java/org/lwjgl/opengl/WindowsMouse.java
+++ b/src/java/org/lwjgl/opengl/WindowsMouse.java
@@ -65,7 +65,7 @@
WindowsMouse(long hwnd) throws LWJGLException {
this.hwnd = hwnd;
- this.mouse_button_count = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_CMOUSEBUTTONS);
+ this.mouse_button_count = Math.min(5, WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_CMOUSEBUTTONS));
this.has_wheel = WindowsDisplay.getSystemMetrics(WindowsDisplay.SM_MOUSEWHEELPRESENT) != 0;
this.blank_cursor = createBlankCursor();
this.button_states = new byte[mouse_button_count];
@@ -90,7 +90,7 @@
return mouse_button_count;
}
- public void poll(IntBuffer coord_buffer, ByteBuffer buttons) {
+ public void poll(IntBuffer coord_buffer, ByteBuffer buttons, WindowsDisplay display) {
for (int i = 0; i < coord_buffer.remaining(); i++)
coord_buffer.put(coord_buffer.position() + i, 0);
int num_buttons = mouse_button_count;
@@ -103,6 +103,9 @@
if (isGrabbed()) {
coord_buffer.put(coord_buffer.position() + 0, accum_dx);
coord_buffer.put(coord_buffer.position() + 1, accum_dy);
+
+ if ( display.isActive() && display.isVisible() && (accum_dx != 0 || accum_dy != 0) )
+ centerCursor();
} else {
coord_buffer.put(coord_buffer.position() + 0, last_x);
coord_buffer.put(coord_buffer.position() + 1, last_y);
@@ -172,7 +175,7 @@
WindowsDisplay.doDestroyCursor(blank_cursor);
}
- public void handleMouseMoved(int x, int y, long millis, boolean should_center) {
+ public void handleMouseMoved(int x, int y, long millis) {
int dx = x - last_x;
int dy = y - last_y;
if (dx != 0 || dy != 0) {
@@ -183,8 +186,6 @@
long nanos = millis*1000000;
if (mouse_grabbed) {
putMouseEventWithCoords((byte)-1, (byte)0, dx, dy, 0, nanos);
- if (should_center)
- centerCursor();
} else {
putMouseEventWithCoords((byte)-1, (byte)0, x, y, 0, nanos);
}
diff --git a/src/java/org/lwjgl/opengl/WindowsPbufferPeerInfo.java b/src/java/org/lwjgl/opengl/WindowsPbufferPeerInfo.java
index 944094e..840cdf3 100644
--- a/src/java/org/lwjgl/opengl/WindowsPbufferPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/WindowsPbufferPeerInfo.java
@@ -39,8 +39,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: WindowsPbufferPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
final class WindowsPbufferPeerInfo extends WindowsPeerInfo {
WindowsPbufferPeerInfo(int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs) throws LWJGLException {
diff --git a/src/java/org/lwjgl/opengl/WindowsPeerInfo.java b/src/java/org/lwjgl/opengl/WindowsPeerInfo.java
index 83c04a6..89fcaab 100644
--- a/src/java/org/lwjgl/opengl/WindowsPeerInfo.java
+++ b/src/java/org/lwjgl/opengl/WindowsPeerInfo.java
@@ -39,8 +39,8 @@
/**
*
* @author elias_naur
- * @version $Revision: 3116 $
- * $Id: WindowsPeerInfo.java 3116 2008-08-19 16:46:03Z spasi $
+ * @version $Revision$
+ * $Id$
*/
abstract class WindowsPeerInfo extends PeerInfo {
protected WindowsPeerInfo() {
diff --git a/src/java/org/lwjgl/opengl/XRandR.java b/src/java/org/lwjgl/opengl/XRandR.java
index 0df903f..abd3c6e 100644
--- a/src/java/org/lwjgl/opengl/XRandR.java
+++ b/src/java/org/lwjgl/opengl/XRandR.java
@@ -27,17 +27,14 @@
package org.lwjgl.opengl;
+import org.lwjgl.LWJGLUtil;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
-import org.lwjgl.LWJGLUtil;
/**
* Utility for working with the xrandr commmand-line utility. Assumes
@@ -45,108 +42,145 @@
*
* @author ryanm
*/
-public class XRandR
-{
+public class XRandR {
+
private static Screen[] current;
+ /**
+ * Either the screen marked as "primary" (if it is turned on)
+ * or the one with the largest (current) resolution.
+ */
+ private static String primaryScreenIdentifier;
+
+ /**
+ * Used to save the configuration of all output devices to
+ * restore it on exit or in case of crash.
+ */
+ private static Screen[] savedConfiguration;
+
private static Map screens;
- private static void populate()
- {
- if( screens == null )
- {
- screens = new HashMap();
-
- // ProcessBuilder pb = new ProcessBuilder( "xrandr", "-q" );
- // pb.redirectErrorStream();
- try
- {
- // Process p= pb.start();
- Process p = Runtime.getRuntime().exec( new String[] { "xrandr", "-q" } );
-
- List currentList = new ArrayList();
- List possibles = new ArrayList();
- String name = null;
-
- BufferedReader br = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
- String line;
- while( ( line = br.readLine() ) != null )
- {
- line = line.trim();
- String[] sa = line.split( "\\s+" );
-
- if( "connected".equals(sa[1]) )
- {
- // found a new screen block
- if( name != null )
- {
- screens.put( name, possibles.toArray( new Screen[ possibles.size() ] ) );
- possibles.clear();
- }
- name = sa[ 0 ];
-
- // record the current config
- parseScreen( currentList, name, sa[ 2 ] );
- }
- else if( Pattern.matches( "\\d*x\\d*", sa[ 0 ] ) )
- {
+ private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
+
+ private static void populate() {
+ if ( screens != null )
+ return;
+
+ screens = new HashMap();
+
+ try {
+ Process p = Runtime.getRuntime().exec(new String[] { "xrandr", "-q" });
+
+ List currentList = new ArrayList();
+ List possibles = new ArrayList();
+ String name = null;
+ // saves the position of the current screen. this is specified in the header of the screen block,
+ // but required later when parsing the screen modelines
+ int[] currentScreenPosition = new int[2];
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ while ( (line = br.readLine()) != null ) {
+ line = line.trim();
+ String[] sa = WHITESPACE_PATTERN.split(line);
+
+ if ( "connected".equals(sa[1]) ) {
+ // found a new screen block
+ if ( name != null ) {
+ screens.put(name, possibles.toArray(new Screen[possibles.size()]));
+ possibles.clear();
+ }
+ name = sa[0];
+
+ // save position of this screen, will be used later when current modeline is parsed
+ if ( "primary".equals(sa[2]) ) {
+ parseScreenHeader(currentScreenPosition, sa[3]);
+ // save primary
+ primaryScreenIdentifier = name;
+ } else {
+ parseScreenHeader(currentScreenPosition, sa[2]);
+ }
+ } else {
+ Matcher m = SCREEN_MODELINE_PATTERN.matcher(sa[0]);
+ if ( m.matches() ) {
// found a new mode line
- parseScreen( possibles, name, sa[ 0 ] );
+ parseScreenModeline(
+ possibles, currentList, name,
+ Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)),
+ sa, currentScreenPosition
+ );
}
}
-
- screens.put( name, possibles.toArray( new Screen[ possibles.size() ] ) );
-
- current = currentList.toArray(new Screen[currentList.size()]);
- }
- catch( Throwable e )
- {
- LWJGLUtil.log( "Exception in XRandR.populate(): " + e.getMessage() );
- screens.clear();
- current = new Screen[ 0 ];
- }
- }
- }
-
- /**
- * @return The current screen configuration, or an empty array if
- * xrandr is not supported
- */
- public static Screen[] getConfiguration()
- {
- populate();
-
+ }
+
+ screens.put(name, possibles.toArray(new Screen[possibles.size()]));
+
+ current = currentList.toArray(new Screen[currentList.size()]);
+
+ // set primary to largest screen if not set yet
+ if ( primaryScreenIdentifier == null ) {
+ long totalPixels = Long.MIN_VALUE;
+ for ( Screen screen : current ) {
+ if ( 1l * screen.width * screen.height > totalPixels ) {
+ primaryScreenIdentifier = screen.name;
+ totalPixels = 1l * screen.width * screen.height;
+ }
+ }
+ }
+ } catch (Throwable e) {
+ LWJGLUtil.log("Exception in XRandR.populate(): " + e.getMessage());
+ screens.clear();
+ current = new Screen[0];
+ }
+ }
+
+ /**
+ * @return The current screen configuration of the primary device,
+ * or an empty array if xrandr is not supported
+ */
+ public static Screen[] getConfiguration() {
+ populate();
+
+ // find and return primary
+ for ( Screen screen : current ) {
+ if ( screen.name.equals(primaryScreenIdentifier) ) {
+ return new Screen[] { screen };
+ }
+ }
+
+ // problem with primary device, fall back to old behaviour
return current.clone();
}
/**
- * @param screens
- * The desired screen set, may not be null
- * @throws IllegalArgumentException
- * if no screens are specified
- */
- public static void setConfiguration(Screen... screens)
- {
- if( screens.length == 0 )
- throw new IllegalArgumentException( "Must specify at least one screen" );
+ * @param disableOthers if screens not included in screens should be turned off (true) or left alone (false)
+ * @param screens The desired screen set, may not be null
+ *
+ * @throws IllegalArgumentException if no screens are specified
+ */
+ public static void setConfiguration(boolean disableOthers, Screen... screens) {
+ if ( screens.length == 0 )
+ throw new IllegalArgumentException("Must specify at least one screen");
List cmd = new ArrayList();
- cmd.add( "xrandr" );
-
- // switch off those in the current set not in the new set
- for ( Screen screen : current ) {
- boolean found = false;
- for ( Screen screen1 : screens ) {
- if ( screen1.name.equals(screen.name) ) {
- found = true;
- break;
+ cmd.add("xrandr");
+
+ if ( disableOthers ) {
+ // switch off those in the current set not in the new set
+ for ( Screen screen : current ) {
+ boolean disable = true;
+ for ( Screen screen1 : screens ) {
+ if ( screen1.name.equals(screen.name) ) {
+ disable = false;
+ break;
+ }
}
- }
-
- if ( !found ) {
- cmd.add("--output");
- cmd.add(screen.name);
- cmd.add("--off");
+
+ if ( disable ) {
+ cmd.add("--output");
+ cmd.add(screen.name);
+ cmd.add("--off");
+ }
}
}
@@ -154,151 +188,192 @@
for ( Screen screen : screens )
screen.getArgs(cmd);
- try
- {
- // ProcessBuilder pb = new ProcessBuilder( cmd );
- // pb.redirectErrorStream();
- // Process p = pb.start();
- Process p =
- Runtime.getRuntime().exec( cmd.toArray( new String[ cmd.size() ] ) );
+ try {
+ Process p = Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));
// no output is expected, but check anyway
- BufferedReader br = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
+ BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
- while( ( line = br.readLine() ) != null )
- {
- LWJGLUtil.log( "Unexpected output from xrandr process: " + line );
+ while ( (line = br.readLine()) != null ) {
+ LWJGLUtil.log("Unexpected output from xrandr process: " + line);
}
current = screens;
- }
- catch( IOException e )
- {
- LWJGLUtil.log( "XRandR exception in setConfiguration(): " + e.getMessage() );
+ } catch (IOException e) {
+ LWJGLUtil.log("XRandR exception in setConfiguration(): " + e.getMessage());
+ }
+ }
+
+ /**
+ * Saves the current configuration for all connected display devices.
+ * This configuration can be restored on exit/crash by calling
+ * restoreConfiguration()
+ */
+ public static void saveConfiguration() {
+ populate();
+ savedConfiguration = current.clone();
+ }
+
+ /**
+ * Restores the configuration for all connected display devices.
+ * Used on exit or in case of a crash to reset all devices.
+ */
+ public static void restoreConfiguration() {
+ if ( savedConfiguration != null ) {
+ setConfiguration(true, savedConfiguration);
}
}
/**
* @return the name of connected screens, or an empty array if
- * xrandr is not supported
- */
- public static String[] getScreenNames()
- {
- populate();
- return screens.keySet().toArray( new String[ screens.size() ] );
+ * xrandr is not supported
+ */
+ public static String[] getScreenNames() {
+ populate();
+ return screens.keySet().toArray(new String[screens.size()]);
}
/**
* @param name
+ *
* @return the possible resolutions of the named screen, or
- * null
if there is no such screen
- */
- public static Screen[] getResolutions( String name )
- {
+ * null
if there is no such screen
+ */
+ public static Screen[] getResolutions(String name) {
populate();
// clone the array to prevent held copies being altered
return screens.get(name).clone();
}
- private static final Pattern SCREEN_PATTERN1 =
- Pattern.compile( "^(\\d+)x(\\d+)\\+(\\d+)\\+(\\d+)$" );
-
- private static final Pattern SCREEN_PATTERN2 = Pattern.compile( "^(\\d+)x(\\d+)$" );
-
- /**
- * Parses a screen configuration and adds it to the list if it's
- * valid.
- *
- * @param list
- * the list to add the Screen to if it's valid
- * @param name
- * the name of this screen
- * @param what
- * config string, format either widthxheight or
- * widthxheight+xPos+yPos
- */
- private static void parseScreen( List list, String name, String what )
- {
- Matcher m = SCREEN_PATTERN1.matcher( what );
- if( !m.matches() )
- {
- m = SCREEN_PATTERN2.matcher( what );
- if( !m.matches() )
- {
- LWJGLUtil.log( "Did not match: " + what );
+ private static final Pattern SCREEN_HEADER_PATTERN = Pattern.compile("^(\\d+)x(\\d+)[+](\\d+)[+](\\d+)$");
+ private static final Pattern SCREEN_MODELINE_PATTERN = Pattern.compile("^(\\d+)x(\\d+)$");
+ private static final Pattern FREQ_PATTERN = Pattern.compile("^(\\d+)[.](\\d+)(?:\\s*[*])?(?:\\s*[+])?$");
+
+ /**
+ * Parses a screen configuration and adds it to one of the lists if valid.
+ *
+ * @param allModes the list to add the Screen to if it's valid
+ * @param current the list to add the current screen config to
+ * @param name the name of this screen
+ * @param modeLine config string
+ * @param screenPosition position of this screen
+ */
+ private static void parseScreenModeline(List allModes, List current, String name, int width, int height, String[] modeLine, int[] screenPosition) {
+ for ( int i = 1; i < modeLine.length; i++ ) {
+ String freqS = modeLine[i];
+ if ( "+".equals(freqS) ) {
+ // previous rate was the "preferred" refresh rate
+ // no way to get this info to the application, so ignore it
+ continue;
+ }
+
+ Matcher m = FREQ_PATTERN.matcher(freqS);
+ if ( !m.matches() ) {
+ LWJGLUtil.log("Frequency match failed: " + Arrays.toString(modeLine));
return;
}
- }
- int width = Integer.parseInt( m.group( 1 ) );
- int height = Integer.parseInt( m.group( 2 ) );
- int xpos, ypos;
- if( m.groupCount() > 3 )
- {
- xpos = Integer.parseInt( m.group( 3 ) );
- ypos = Integer.parseInt( m.group( 4 ) );
- }
- else
- {
- xpos = 0;
- ypos = 0;
- }
- list.add( new Screen( name, width, height, xpos, ypos ) );
- }
-
- /**
- * Encapsulates the configuration of a monitor. Resolution is
- * fixed, position is mutable
+
+ int freq = Integer.parseInt(m.group(1));
+
+ Screen s = new Screen(name, width, height, freq, 0, 0);
+ if ( freqS.contains("*") ) {
+ // current mode, save to current list with screen position
+ current.add(new Screen(name, width, height, freq, screenPosition[0], screenPosition[1]));
+ // make sure the current mode is always first
+ allModes.add(0, s);
+ } else {
+ // always add to List of all modes without screen position
+ allModes.add(s);
+ }
+ }
+ }
+
+ /**
+ * Parses a screen configuration header and extracts information about the position of the screen.
+ *
+ * @param screenPosition the int-array to write the position into
+ * @param resPos String containing resolution and position, from xrandr
+ */
+ private static void parseScreenHeader(int[] screenPosition, String resPos) {
+ Matcher m = SCREEN_HEADER_PATTERN.matcher(resPos);
+ if ( !m.matches() ) {
+ // screen not active!
+ screenPosition[0] = 0;
+ screenPosition[1] = 0;
+ return;
+ }
+ screenPosition[0] = Integer.parseInt(m.group(3));
+ screenPosition[1] = Integer.parseInt(m.group(4));
+ }
+
+ static Screen DisplayModetoScreen(DisplayMode mode) {
+ populate();
+ Screen primary = findPrimary(current);
+ return new Screen(primary.name, mode.getWidth(), mode.getHeight(), mode.getFrequency(), primary.xPos, primary.yPos);
+ }
+
+ static DisplayMode ScreentoDisplayMode(Screen... screens) {
+ populate();
+ Screen primary = findPrimary(screens);
+ return new DisplayMode(primary.width, primary.height, 24, primary.freq);
+ }
+
+ private static Screen findPrimary(Screen... screens) {
+ for ( Screen screen : screens ) {
+ if ( screen.name.equals(primaryScreenIdentifier) ) {
+ return screen;
+ }
+ }
+ // fallback
+ return screens[0];
+ }
+
+ /**
+ * Encapsulates the configuration of a monitor.
+ * Resolution and freq are fixed, position is mutable
*
* @author ryanm
*/
- public static class Screen implements Cloneable
- {
- /**
- * Name for this output
- */
+ public static class Screen implements Cloneable {
+ /** Name for this output */
public final String name;
- /**
- * Width in pixels
- */
+ /** Width in pixels */
public final int width;
- /**
- * Height in pixels
- */
+ /** Height in pixels */
public final int height;
- /**
- * Position on the x-axis, in pixels
- */
+ /** Frequency in Hz */
+ public final int freq;
+
+ /** Position on the x-axis, in pixels */
public int xPos;
- /**
- * Position on the y-axis, in pixels
- */
+ /** Position on the y-axis, in pixels */
public int yPos;
- private Screen( String name, int width, int height, int xPos, int yPos )
- {
+ Screen(String name, int width, int height, int freq, int xPos, int yPos) {
this.name = name;
this.width = width;
this.height = height;
+ this.freq = freq;
this.xPos = xPos;
this.yPos = yPos;
}
- private void getArgs( List argList )
- {
- argList.add( "--output" );
- argList.add( name );
- argList.add( "--mode" );
- argList.add( width + "x" + height );
- argList.add( "--pos" );
- argList.add( xPos + "x" + yPos );
+ private void getArgs(List argList) {
+ argList.add("--output");
+ argList.add(name);
+ argList.add("--mode");
+ argList.add(width + "x" + height);
+ argList.add("--rate");
+ argList.add(Integer.toString(freq));
+ argList.add("--pos");
+ argList.add(xPos + "x" + yPos);
}
//@Override
- public String toString()
- {
- return name + " " + width + "x" + height + " @ " + xPos + "x" + yPos;
+ public String toString() {
+ return name + " " + width + "x" + height + " @ " + xPos + "x" + yPos + " with " + freq + "Hz";
}
}
}diff --git a/src/java/org/lwjgl/opengles/APIUtil.java b/src/java/org/lwjgl/opengles/APIUtil.java
new file mode 100644
index 0000000..baa3a36
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/APIUtil.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.MemoryUtil;
+import org.lwjgl.PointerBuffer;
+
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+
+/**
+ * Utility class for OpenGL ES API calls.
+ *
+ * @author spasi
+ */
+final class APIUtil {
+
+ private static final int INITIAL_BUFFER_SIZE = 256;
+ private static final int INITIAL_LENGTHS_SIZE = 4;
+
+ private static final int BUFFERS_SIZE = 32;
+
+ private static final ThreadLocal arrayTL = new ThreadLocal() {
+ protected char[] initialValue() { return new char[INITIAL_BUFFER_SIZE]; }
+ };
+
+ private static final ThreadLocal bufferTL = new ThreadLocal() {
+ protected ByteBuffer initialValue() { return BufferUtils.createByteBuffer(INITIAL_BUFFER_SIZE); }
+ };
+
+ private static final ThreadLocal bufferPointerTL = new ThreadLocal() {
+ protected PointerBuffer initialValue() { return BufferUtils.createPointerBuffer(INITIAL_BUFFER_SIZE); }
+ };
+
+ private static final ThreadLocal lengthsTL = new ThreadLocal() {
+ protected IntBuffer initialValue() { return BufferUtils.createIntBuffer(INITIAL_LENGTHS_SIZE); }
+ };
+
+ private static final ThreadLocal buffersTL = new ThreadLocal() {
+ protected Buffers initialValue() { return new Buffers(); }
+ };
+
+ private APIUtil() {
+ }
+
+ private static char[] getArray(final int size) {
+ char[] array = arrayTL.get();
+
+ if ( array.length < size ) {
+ int sizeNew = array.length << 1;
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ array = new char[size];
+ arrayTL.set(array);
+ }
+
+ return array;
+ }
+
+ static ByteBuffer getBufferByte(final int size) {
+ ByteBuffer buffer = bufferTL.get();
+
+ if ( buffer.capacity() < size ) {
+ int sizeNew = buffer.capacity() << 1;
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ buffer = BufferUtils.createByteBuffer(size);
+ bufferTL.set(buffer);
+ } else
+ buffer.clear();
+
+ return buffer;
+ }
+
+ private static ByteBuffer getBufferByteOffset(final int size) {
+ ByteBuffer buffer = bufferTL.get();
+
+ if ( buffer.capacity() < size ) {
+ int sizeNew = buffer.capacity() << 1;
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ final ByteBuffer bufferNew = BufferUtils.createByteBuffer(size);
+ bufferNew.put(buffer);
+ bufferTL.set(buffer = bufferNew);
+ } else {
+ buffer.position(buffer.limit());
+ buffer.limit(buffer.capacity());
+ }
+
+ return buffer;
+ }
+
+ static PointerBuffer getBufferPointer(final int size) {
+ PointerBuffer buffer = bufferPointerTL.get();
+
+ if ( buffer.capacity() < size ) {
+ int sizeNew = buffer.capacity() << 1;
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ buffer = BufferUtils.createPointerBuffer(size);
+ bufferPointerTL.set(buffer);
+ } else
+ buffer.clear();
+
+ return buffer;
+ }
+
+ static IntBuffer getBufferInt() { return buffersTL.get().ints; }
+
+ static LongBuffer getBufferLong() { return buffersTL.get().longs; }
+
+ static FloatBuffer getBufferFloat() { return buffersTL.get().floats; }
+
+ static IntBuffer getLengths() {
+ return getLengths(1);
+ }
+
+ static IntBuffer getLengths(final int size) {
+ IntBuffer lengths = lengthsTL.get();
+
+ if ( lengths.capacity() < size ) {
+ int sizeNew = lengths.capacity();
+ while ( sizeNew < size )
+ sizeNew <<= 1;
+
+ lengths = BufferUtils.createIntBuffer(size);
+ lengthsTL.set(lengths);
+ } else
+ lengths.clear();
+
+ return lengths;
+ }
+
+ /**
+ * Simple ASCII encoding.
+ *
+ * @param buffer The target buffer
+ * @param string The source string
+ */
+ private static ByteBuffer encode(final ByteBuffer buffer, final CharSequence string) {
+ for ( int i = 0; i < string.length(); i++ ) {
+ final char c = string.charAt(i);
+ if ( LWJGLUtil.DEBUG && 0x80 <= c ) // Silently ignore and map to 0x1A.
+ buffer.put((byte)0x1A);
+ else
+ buffer.put((byte)c);
+ }
+
+ return buffer;
+ }
+
+ /**
+ * Reads a byte string from the specified buffer.
+ *
+ * @param buffer
+ *
+ * @return the buffer as a String.
+ */
+ static String getString(final ByteBuffer buffer) {
+ final int length = buffer.remaining();
+ final char[] charArray = getArray(length);
+
+ for ( int i = buffer.position(); i < buffer.limit(); i++ )
+ charArray[i - buffer.position()] = (char)buffer.get(i);
+
+ return new String(charArray, 0, length);
+ }
+
+ /**
+ * Returns a buffer containing the specified string as bytes.
+ *
+ * @param string
+ *
+ * @return the String as a ByteBuffer
+ */
+ static long getBuffer(final CharSequence string) {
+ final ByteBuffer buffer = encode(getBufferByte(string.length()), string);
+ buffer.flip();
+ return MemoryUtil.getAddress0(buffer);
+ }
+
+ /**
+ * Returns a buffer containing the specified string as bytes, starting at the specified offset.
+ *
+ * @param string
+ *
+ * @return the String as a ByteBuffer
+ */
+ static long getBuffer(final CharSequence string, final int offset) {
+ final ByteBuffer buffer = encode(getBufferByteOffset(offset + string.length()), string);
+ buffer.flip();
+ return MemoryUtil.getAddress(buffer);
+ }
+
+ /**
+ * Returns a buffer containing the specified string as bytes, including null-termination.
+ *
+ * @param string
+ *
+ * @return the String as a ByteBuffer
+ */
+ static long getBufferNT(final CharSequence string) {
+ final ByteBuffer buffer = encode(getBufferByte(string.length() + 1), string);
+ buffer.put((byte)0);
+ buffer.flip();
+ return MemoryUtil.getAddress0(buffer);
+ }
+
+ static int getTotalLength(final CharSequence[] strings) {
+ int length = 0;
+ for ( CharSequence string : strings )
+ length += string.length();
+
+ return length;
+ }
+
+ /**
+ * Returns a buffer containing the specified strings as bytes.
+ *
+ * @param strings
+ *
+ * @return the Strings as a ByteBuffer
+ */
+ static long getBuffer(final CharSequence[] strings) {
+ final ByteBuffer buffer = getBufferByte(getTotalLength(strings));
+
+ for ( CharSequence string : strings )
+ encode(buffer, string);
+
+ buffer.flip();
+ return MemoryUtil.getAddress0(buffer);
+ }
+
+ /**
+ * Returns a buffer containing the specified strings as bytes, including null-termination.
+ *
+ * @param strings
+ *
+ * @return the Strings as a ByteBuffer
+ */
+ static long getBufferNT(final CharSequence[] strings) {
+ final ByteBuffer buffer = getBufferByte(getTotalLength(strings) + strings.length);
+
+ for ( CharSequence string : strings ) {
+ encode(buffer, string);
+ buffer.put((byte)0);
+ }
+
+ buffer.flip();
+ return MemoryUtil.getAddress0(buffer);
+ }
+
+ /**
+ * Returns a buffer containing the lengths of the specified strings.
+ *
+ * @param strings
+ *
+ * @return the String lengths in an IntBuffer
+ */
+ static long getLengths(final CharSequence[] strings) {
+ IntBuffer buffer = getLengths(strings.length);
+
+ for ( CharSequence string : strings )
+ buffer.put(string.length());
+
+ buffer.flip();
+ return MemoryUtil.getAddress0(buffer);
+ }
+
+ static long getInt(final int value) {
+ return MemoryUtil.getAddress(getBufferInt().put(0, value), 0);
+ }
+
+ static long getBufferByte0() {
+ return MemoryUtil.getAddress0(getBufferByte(0));
+ }
+
+ private static class Buffers {
+
+ final IntBuffer ints;
+ final LongBuffer longs;
+ final FloatBuffer floats;
+
+ Buffers() {
+ ints = BufferUtils.createIntBuffer(BUFFERS_SIZE);
+ longs = BufferUtils.createLongBuffer(BUFFERS_SIZE);
+ floats = BufferUtils.createFloatBuffer(BUFFERS_SIZE);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/CallbackUtil.java b/src/java/org/lwjgl/opengles/CallbackUtil.java
new file mode 100644
index 0000000..afca439
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/CallbackUtil.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2002-2010 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class that handles OpenGL API callbacks.
+ *
+ * @author Spasi
+ */
+final class CallbackUtil {
+
+ /** Context -> Long */
+ private static final Map contextUserParamsKHR = new HashMap();
+
+ private CallbackUtil() {}
+
+ /**
+ * Creates a new global reference to the specified Object.
+ *
+ * @param obj the Object
+ *
+ * @return the GlobalRef memory address or 0 if the Object is null.
+ */
+ static long createGlobalRef(final Object obj) {
+ return obj == null ? 0 : ncreateGlobalRef(obj);
+ }
+
+ /**
+ * Creates a new global reference to the specified Object.
+ *
+ * @param obj the Object
+ *
+ * @return the GlobalRef memory address.
+ */
+ private static native long ncreateGlobalRef(Object obj);
+
+ /**
+ * Deletes a global reference.
+ *
+ * @param ref the GlobalRef memory address.
+ */
+ private static native void deleteGlobalRef(long ref);
+
+ // --------- [ XXX_debug_output ] ---------
+
+ /**
+ * Associates the current OpenGL context with the specified global reference. If there
+ * is no context current, the global reference is deleted and an exception is thrown.
+ * Any previous callback registrations will be cleared.
+ *
+ * @param userParam the global reference pointer
+ */
+ private static void registerContextCallback(final long userParam, final Map contextUserData) {
+ ContextCapabilities caps = GLContext.getCapabilities();
+ if ( caps == null ) {
+ deleteGlobalRef(userParam);
+ throw new IllegalStateException("No context is current.");
+ }
+
+ final Long userParam_old = contextUserData.remove(caps);
+ if ( userParam_old != null )
+ deleteGlobalRef(userParam_old);
+
+ if ( userParam != 0 )
+ contextUserData.put(caps, userParam);
+ }
+
+ /**
+ * Releases references to any callbacks associated with the specified GL context.
+ *
+ * @param context the Context to unregister
+ */
+ static void unregisterCallbacks(final Object context) {
+ // TODO: This is never called for custom contexts. Need to fix for LWJGL 3.0
+ final ContextCapabilities caps = GLContext.getCapabilities();
+
+ Long userParam = contextUserParamsKHR.remove(caps);
+ if ( userParam != null )
+ deleteGlobalRef(userParam);
+ }
+
+ // --------- [ KHR_debug ] ---------
+
+ /**
+ * Returns the memory address of the native function we pass to glDebugMessageCallback.
+ *
+ * @return the callback function address
+ */
+ static native long getDebugCallbackKHR();
+
+ /**
+ * Associates the current OpenGL context with the specified global reference. If there
+ * is no context current, the global reference is deleted and an exception is thrown.
+ * Any previous callback registrations will be cleared.
+ *
+ * @param userParam the global reference pointer
+ */
+ static void registerContextCallbackKHR(final long userParam) {
+ registerContextCallback(userParam, contextUserParamsKHR);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/ContextAttribs.java b/src/java/org/lwjgl/opengles/ContextAttribs.java
new file mode 100644
index 0000000..24e23a1
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/ContextAttribs.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.BufferUtils;
+
+import java.nio.IntBuffer;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/**
+ * This class represents the context attributes passed to EGL's eglCreateContext.
+ * The only attribute allowed is EGL_CONTEXT_CLIENT_VERSION and it must be 2 or 3 (LWJGL does not support GLES 1.x).
+ */
+public final class ContextAttribs {
+
+ private int version;
+
+ public ContextAttribs() {
+ this(2);
+ }
+
+ public ContextAttribs(final int version) {
+ if ( 3 < version )
+ throw new IllegalArgumentException("Invalid OpenGL ES version specified: " + version);
+
+ this.version = version;
+ }
+
+ private ContextAttribs(final ContextAttribs attribs) {
+ this.version = attribs.version;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public IntBuffer getAttribList() {
+ int attribCount = 1;
+
+ final IntBuffer attribs = BufferUtils.createIntBuffer((attribCount * 2) + 1);
+
+ attribs.put(EGL_CONTEXT_CLIENT_VERSION).put(version);
+
+ attribs.put(EGL_NONE);
+ attribs.rewind();
+ return attribs;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder(32);
+
+ sb.append("ContextAttribs:");
+ sb.append(" Version=").append(version);
+
+ return sb.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGL.java b/src/java/org/lwjgl/opengles/EGL.java
new file mode 100644
index 0000000..19d97db
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGL.java
@@ -0,0 +1,922 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.BufferChecks;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.MemoryUtil;
+import org.lwjgl.PointerBuffer;
+
+import java.nio.IntBuffer;
+
+/** EGL wrapper class. */
+public final class EGL {
+
+ /** EGL aliases */
+ public static final int
+ EGL_FALSE = 0,
+ EGL_TRUE = 1;
+
+ /** Out-of-band handle values */
+ public static final int
+ EGL_DEFAULT_DISPLAY = 0,
+ EGL_NO_CONTEXT = 0,
+ EGL_NO_DISPLAY = 0,
+ EGL_NO_SURFACE = 0;
+
+ /** Out-of-band attribute value */
+ public static final int EGL_DONT_CARE = -1;
+
+ /** Errors / GetError return values */
+ public static final int
+ EGL_SUCCESS = 0x3000,
+ EGL_NOT_INITIALIZED = 0x3001,
+ EGL_BAD_ACCESS = 0x3002,
+ EGL_BAD_ALLOC = 0x3003,
+ EGL_BAD_ATTRIBUTE = 0x3004,
+ EGL_BAD_CONFIG = 0x3005,
+ EGL_BAD_CONTEXT = 0x3006,
+ EGL_BAD_CURRENT_SURFACE = 0x3007,
+ EGL_BAD_DISPLAY = 0x3008,
+ EGL_BAD_MATCH = 0x3009,
+ EGL_BAD_NATIVE_PIXMAP = 0x300A,
+ EGL_BAD_NATIVE_WINDOW = 0x300B,
+ EGL_BAD_PARAMETER = 0x300C,
+ EGL_BAD_SURFACE = 0x300D,
+ EGL_CONTEXT_LOST = 0x300E; // EGL 1.1 - IMG_power_management
+
+ /** Reserved =0x300F;-=0x301F; for additional errors */
+
+ /** Config attributes */
+ public static final int
+ EGL_BUFFER_SIZE = 0x3020,
+ EGL_ALPHA_SIZE = 0x3021,
+ EGL_BLUE_SIZE = 0x3022,
+ EGL_GREEN_SIZE = 0x3023,
+ EGL_RED_SIZE = 0x3024,
+ EGL_DEPTH_SIZE = 0x3025,
+ EGL_STENCIL_SIZE = 0x3026,
+ EGL_CONFIG_CAVEAT = 0x3027,
+ EGL_CONFIG_ID = 0x3028,
+ EGL_LEVEL = 0x3029,
+ EGL_MAX_PBUFFER_HEIGHT = 0x302A,
+ EGL_MAX_PBUFFER_PIXELS = 0x302B,
+ EGL_MAX_PBUFFER_WIDTH = 0x302C,
+ EGL_NATIVE_RENDERABLE = 0x302D,
+ EGL_NATIVE_VISUAL_ID = 0x302E,
+ EGL_NATIVE_VISUAL_TYPE = 0x302F,
+ EGL_SAMPLES = 0x3031,
+ EGL_SAMPLE_BUFFERS = 0x3032,
+ EGL_SURFACE_TYPE = 0x3033,
+ EGL_TRANSPARENT_TYPE = 0x3034,
+ EGL_TRANSPARENT_BLUE_VALUE = 0x3035,
+ EGL_TRANSPARENT_GREEN_VALUE = 0x3036,
+ EGL_TRANSPARENT_RED_VALUE = 0x3037,
+ EGL_NONE = 0x3038, // Attrib list terminator
+ EGL_BIND_TO_TEXTURE_RGB = 0x3039,
+ EGL_BIND_TO_TEXTURE_RGBA = 0x303A,
+ EGL_MIN_SWAP_INTERVAL = 0x303B,
+ EGL_MAX_SWAP_INTERVAL = 0x303C,
+ EGL_LUMINANCE_SIZE = 0x303D,
+ EGL_ALPHA_MASK_SIZE = 0x303E,
+ EGL_COLOR_BUFFER_TYPE = 0x303F,
+ EGL_RENDERABLE_TYPE = 0x3040,
+ EGL_MATCH_NATIVE_PIXMAP = 0x3041, // Pseudo-attribute (not queryable)
+ EGL_CONFORMANT = 0x3042;
+
+ /** Reserved =0x3041;-=0x304F; for additional config attributes */
+
+ /** Config attribute values */
+ public static final int
+ EGL_SLOW_CONFIG = 0x3050, // EGL_CONFIG_CAVEAT value
+ EGL_NON_CONFORMANT_CONFIG = 0x3051, // EGL_CONFIG_CAVEAT value
+ EGL_TRANSPARENT_RGB = 0x3052, // EGL_TRANSPARENT_TYPE value
+ EGL_RGB_BUFFER = 0x308E, // EGL_COLOR_BUFFER_TYPE value
+ EGL_LUMINANCE_BUFFER = 0x308F; // EGL_COLOR_BUFFER_TYPE value
+
+ /** More config attribute values, for EGL_TEXTURE_FORMAT */
+ public static final int
+ EGL_NO_TEXTURE = 0x305C,
+ EGL_TEXTURE_RGB = 0x305D,
+ EGL_TEXTURE_RGBA = 0x305E,
+ EGL_TEXTURE_2D = 0x305F;
+
+ /** EGL_SURFACE_TYPE mask bits */
+ public static final int
+ EGL_PBUFFER_BIT = 0x0001,
+ EGL_PIXMAP_BIT = 0x0002,
+ EGL_WINDOW_BIT = 0x0004,
+ EGL_VG_COLORSPACE_LINEAR_BIT = 0x0020,
+ EGL_VG_ALPHA_FORMAT_PRE_BIT = 0x0040,
+ EGL_MULTISAMPLE_RESOLVE_BOX_BIT = 0x0200,
+ EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
+
+ /** EGL_RENDERABLE_TYPE mask bits */
+ public static final int
+ EGL_OPENGL_ES_BIT = 0x0001,
+ EGL_OPENVG_BIT = 0x0002,
+ EGL_OPENGL_ES2_BIT = 0x0004,
+ EGL_OPENGL_BIT = 0x0008;
+
+ /** QueryString targets */
+ public static final int
+ EGL_VENDOR = 0x3053,
+ EGL_VERSION = 0x3054,
+ EGL_EXTENSIONS = 0x3055,
+ EGL_CLIENT_APIS = 0x308D;
+
+ /** QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
+ public static final int
+ EGL_HEIGHT = 0x3056,
+ EGL_WIDTH = 0x3057,
+ EGL_LARGEST_PBUFFER = 0x3058,
+ EGL_TEXTURE_FORMAT = 0x3080,
+ EGL_TEXTURE_TARGET = 0x3081,
+ EGL_MIPMAP_TEXTURE = 0x3082,
+ EGL_MIPMAP_LEVEL = 0x3083,
+ EGL_RENDER_BUFFER = 0x3086,
+ EGL_VG_COLORSPACE = 0x3087,
+ EGL_VG_ALPHA_FORMAT = 0x3088,
+ EGL_HORIZONTAL_RESOLUTION = 0x3090,
+ EGL_VERTICAL_RESOLUTION = 0x3091,
+ EGL_PIXEL_ASPECT_RATIO = 0x3092,
+ EGL_SWAP_BEHAVIOR = 0x3093,
+ EGL_MULTISAMPLE_RESOLVE = 0x3099;
+
+ /** EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
+ public static final int
+ EGL_BACK_BUFFER = 0x3084,
+ EGL_SINGLE_BUFFER = 0x3085;
+
+ /** OpenVG color spaces */
+ public static final int
+ EGL_VG_COLORSPACE_sRGB = 0x3089, // EGL_VG_COLORSPACE value
+ EGL_VG_COLORSPACE_LINEAR = 0x308A; // EGL_VG_COLORSPACE value
+
+ /** OpenVG alpha formats */
+ public static final int
+ EGL_VG_ALPHA_FORMAT_NONPRE = 0x308B, // EGL_ALPHA_FORMAT value
+ EGL_VG_ALPHA_FORMAT_PRE = 0x308C; // EGL_ALPHA_FORMAT
+
+ /**
+ * Constant scale factor by which fractional display resolutions &
+ * aspect ratio are scaled when queried as integer values.
+ */
+ public static final int EGL_DISPLAY_SCALING = 10000;
+
+ /** Unknown display resolution/aspect ratio */
+ public static final int EGL_UNKNOWN = -1;
+
+ /** Back buffer swap behaviors */
+ public static final int
+ EGL_BUFFER_PRESERVED = 0x3094, // EGL_SWAP_BEHAVIOR value
+ EGL_BUFFER_DESTROYED = 0x3095; // EGL_SWAP_BEHAVIOR value
+
+ /** CreatePbufferFromClientBuffer buffer types */
+ static final int EGL_OPENVG_IMAGE = 0x3096;
+
+ /** QueryContext targets */
+ public static final int EGL_CONTEXT_CLIENT_TYPE = 0x3097;
+
+ /** CreateContext attributes */
+ public static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+
+ /** Multisample resolution behaviors */
+ public static final int
+ EGL_MULTISAMPLE_RESOLVE_DEFAULT = 0x309A, // EGL_MULTISAMPLE_RESOLVE value
+ EGL_MULTISAMPLE_RESOLVE_BOX = 0x309B; // EGL_MULTISAMPLE_RESOLVE value
+
+ /** BindAPI/QueryAPI targets */
+ public static final int
+ EGL_OPENGL_ES_API = 0x30A0,
+ EGL_OPENVG_API = 0x30A1,
+ EGL_OPENGL_API = 0x30A2;
+
+ /** GetCurrentSurface targets */
+ public static final int
+ EGL_DRAW = 0x3059,
+ EGL_READ = 0x305A;
+
+ /** WaitNative engines */
+ static final int EGL_CORE_NATIVE_ENGINE = 0x305B;
+
+ private EGL() {
+ }
+
+ public static native int eglGetError();
+
+ /**
+ * Obtains an EGL display from the specified native display and initializes it.
+ *
+ * @param display_id the handle to the native display.
+ *
+ * @return the EGL Display
+ *
+ * @throws org.lwjgl.LWJGLException if no display is available or an EGL error occurs
+ */
+ public static EGLDisplay eglGetDisplay(long display_id) throws LWJGLException {
+ //LWJGLUtil.log("eglGetDisplay");
+ final long pointer = neglGetDisplay(display_id);
+
+ if ( pointer == EGL_NO_DISPLAY ) // No error is generated when this happens
+ throw new LWJGLException("Failed to get EGL display from native display handle: " + display_id);
+
+ return new EGLDisplay(pointer);
+ }
+
+ private static native long neglGetDisplay(long display_id);
+
+ /**
+ * Initializes the specified EGL display.
+ *
+ * @param dpy the EGL display to initialize
+ * @param version the EGL major and minor version will be returned in this buffer.
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static void eglInitialize(EGLDisplay dpy, IntBuffer version) throws LWJGLException {
+ //LWJGLUtil.log("eglInitialize");
+ BufferChecks.checkBuffer(version, 2);
+ if ( !neglInitialize(dpy.getPointer(), MemoryUtil.getAddress(version)) )
+ throwEGLError("Failed to initialize EGL display.");
+ }
+
+ private static native boolean neglInitialize(long dpy_ptr, long version);
+
+ /**
+ * Release the resources associated with the specified EGL display.
+ *
+ * @param dpy the EGL display to terminate
+ */
+ static void eglTerminate(EGLDisplay dpy) throws LWJGLException {
+ //LWJGLUtil.log("eglTerminate");
+ if ( !neglTerminate(dpy.getPointer()) )
+ throwEGLError("Failed to terminate EGL display.");
+ }
+
+ private static native boolean neglTerminate(long dpy_ptr);
+
+ /**
+ * Returns a string describing some aspect of the EGL implementation running on the specified display.
+ *
+ * @param dpy the EGL display to query
+ * @param name the value to query
+ *
+ * @return the description
+ */
+ public static String eglQueryString(EGLDisplay dpy, int name) {
+ //LWJGLUtil.log("eglQueryString");
+ return neglQueryString(dpy.getPointer(), name);
+ }
+
+ private static native String neglQueryString(long dpy, int name);
+
+ /**
+ * Returns the number of EGLConfigs that are available on the specified display.
+ *
+ * @param dpy the EGLDisplay
+ *
+ * @return the number of EGLConfigs available
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ * @see #eglGetConfigs(EGLDisplay, EGLConfig[], IntBuffer)
+ */
+ static int eglGetConfigsNum(EGLDisplay dpy) throws LWJGLException {
+ //LWJGLUtil.log("eglGetConfigsNum");
+ IntBuffer num_config = APIUtil.getBufferInt();
+
+ if ( !neglGetConfigs(dpy.getPointer(), 0L, 0, MemoryUtil.getAddress0(num_config)) )
+ throwEGLError("Failed to get EGL configs.");
+
+ return num_config.get(0);
+ }
+
+ /**
+ * Returns the available EGLConfigs on the speficied display. The number of available EGLConfigs
+ * is returned in the num_config parameter. The configs array may be null. If it is null, a new
+ * array will be allocated, with size equal to the result of {@link #eglGetConfigsNum(EGLDisplay)} eglGetConfigsNum}.
+ * If it is not null, no more than {@code configs.length} EGLConfigs will be returned. If the array is bigger
+ * than the number of available EGLConfigs, the remaining array elements will not be affected.
+ *
+ * @param dpy the EGLDisplay
+ * @param configs the EGLConfigs array
+ * @param num_config the number of available EGLConfigs returned
+ *
+ * @return the available EGLConfigs
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static EGLConfig[] eglGetConfigs(EGLDisplay dpy, EGLConfig[] configs, IntBuffer num_config) throws LWJGLException {
+ //LWJGLUtil.log("eglGetConfigs");
+ BufferChecks.checkBuffer(num_config, 1);
+
+ if ( configs == null ) {
+ if ( !neglGetConfigs(dpy.getPointer(), 0L, 0, MemoryUtil.getAddress(num_config)) )
+ throwEGLError("Failed to get number of available EGL configs.");
+
+ configs = new EGLConfig[num_config.get(num_config.position())];
+ }
+
+ final PointerBuffer configs_buffer = APIUtil.getBufferPointer(configs.length);
+ if ( !neglGetConfigs(dpy.getPointer(), MemoryUtil.getAddress0(configs_buffer), configs.length, MemoryUtil.getAddress(num_config)) )
+ throwEGLError("Failed to get EGL configs.");
+
+ final int config_size = num_config.get(num_config.position());
+ for ( int i = 0; i < config_size; i++ )
+ configs[i] = new EGLConfig(dpy, configs_buffer.get(i));
+
+ return configs;
+ }
+
+ private static native boolean neglGetConfigs(long dpy_ptr, long configs, int config_size, long num_config);
+
+ /**
+ * Returns the number of EGLConfigs that are available on the specified display and
+ * match the speficied list of attributes.
+ *
+ * @param dpy the EGLDisplay
+ * @param attrib_list the attribute list (may be null)
+ *
+ * @return the number of EGLConfigs available that satisft the attribute list
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ * @see #eglChooseConfig(EGLDisplay, IntBuffer, EGLConfig[], IntBuffer)
+ */
+ static int eglChooseConfigNum(EGLDisplay dpy, IntBuffer attrib_list) throws LWJGLException {
+ //LWJGLUtil.log("eglChooseConfigNum");
+ checkAttribList(attrib_list);
+ IntBuffer num_config = APIUtil.getBufferInt();
+
+ if ( !neglChooseConfig(dpy.getPointer(), MemoryUtil.getAddressSafe(attrib_list), 0L, 0, MemoryUtil.getAddress0(num_config)) )
+ throwEGLError("Failed to get EGL configs.");
+
+ return num_config.get(0);
+ }
+
+ /**
+ * Returns the available EGLConfigs on the speficied display that satisfy the specified list of attributes.
+ * The number of available EGLConfigs is returned in the num_config parameter. The configs array may be null.
+ * If it is null, a new array will be allocated, with size equal to the result of {@link #eglGetConfigsNum(EGLDisplay)} eglGetConfigsNum}.
+ * If it is not null, no more than {@code configs.length} EGLConfigs will be returned. If the array is bigger
+ * than the number of available EGLConfigs, the remaining array elements will not be affected.
+ *
+ * @param dpy the EGLDisplay
+ * @param attrib_list the attribute list (may be null)
+ * @param configs the EGLConfigs array
+ * @param num_config the number of available EGLConfigs returned
+ *
+ * @return the available EGLConfigs that satisfy the attribute list
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static EGLConfig[] eglChooseConfig(EGLDisplay dpy, IntBuffer attrib_list, EGLConfig[] configs, IntBuffer num_config) throws LWJGLException {
+ //LWJGLUtil.log("eglChooseConfig");
+ checkAttribList(attrib_list);
+ BufferChecks.checkBuffer(num_config, 1);
+
+ int config_size;
+ if ( configs == null ) {
+ if ( !neglChooseConfig(dpy.getPointer(), MemoryUtil.getAddressSafe(attrib_list), 0L, 0, MemoryUtil.getAddress(num_config)) )
+ throwEGLError("Failed to get number of available EGL configs.");
+
+ config_size = num_config.get(num_config.position());
+ } else
+ config_size = configs.length;
+
+ //LWJGLUtil.log("config_size = " + config_size);
+ PointerBuffer configs_buffer = APIUtil.getBufferPointer(config_size);
+ if ( !neglChooseConfig(dpy.getPointer(), MemoryUtil.getAddressSafe(attrib_list), MemoryUtil.getAddress0(configs_buffer), config_size, MemoryUtil.getAddress(num_config)) )
+ throwEGLError("Failed to choose EGL config.");
+
+ // Get the true number of configurations (the first neglChooseConfig call may return more than the second)
+ config_size = num_config.get(num_config.position());
+ if ( configs == null )
+ configs = new EGLConfig[config_size];
+ for ( int i = 0; i < config_size; i++ )
+ configs[i] = new EGLConfig(dpy, configs_buffer.get(i));
+
+ return configs;
+ }
+
+ private static native boolean neglChooseConfig(long dpy_ptr, long attrib_list, long configs, int config_size, long num_config);
+
+ /**
+ * Returns the value of an EGL config attribute.
+ *
+ * @param dpy the EGL display
+ * @param config the EGL config
+ * @param attribute the attribute
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static int eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, int attribute) throws LWJGLException {
+ //LWJGLUtil.log("eglGetConfigAttrib");
+ final IntBuffer value = APIUtil.getBufferInt();
+
+ if ( !neglGetConfigAttrib(dpy.getPointer(), config.getPointer(), attribute, MemoryUtil.getAddress(value)) )
+ throwEGLError("Failed to get EGL config attribute.");
+
+ return value.get(0);
+ }
+
+ private static native boolean neglGetConfigAttrib(long dpy_ptr, long config_ptr, int attribute, long value);
+
+ /**
+ * Creates an on-screen rendering surface on the specified EGL display.
+ *
+ * @param dpy the EGL display
+ * @param config the EGL config
+ * @param win the native window handle
+ * @param attrib_list an attribute list (may be null)
+ *
+ * @return the created EGL surface
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, long win, IntBuffer attrib_list) throws LWJGLException {
+ //LWJGLUtil.log("eglCreateWindowSurface");
+ checkAttribList(attrib_list);
+ final long pointer = neglCreateWindowSurface(dpy.getPointer(), config.getPointer(), win, MemoryUtil.getAddressSafe(attrib_list));
+
+ if ( pointer == EGL_NO_SURFACE )
+ throwEGLError("Failed to create EGL window surface.");
+
+ return new EGLSurface(dpy, config, pointer);
+ }
+
+ private static native long neglCreateWindowSurface(long dpy_ptr, long config_ptr, long win, long attrib_list);
+
+ /**
+ * Creates an off-screen rendering surface on the specified EGL display.
+ *
+ * @param dpy the EGL display
+ * @param config the EGL config
+ * @param attrib_list an attribute list (may be null)
+ *
+ * @return the created EGL surface
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, IntBuffer attrib_list) throws LWJGLException {
+ //LWJGLUtil.log("eglCreatePbufferSurface");
+ checkAttribList(attrib_list);
+ final long pointer = neglCreatePbufferSurface(dpy.getPointer(), config.getPointer(), MemoryUtil.getAddressSafe(attrib_list));
+
+ if ( pointer == EGL_NO_SURFACE )
+ throwEGLError("Failed to create EGL pbuffer surface.");
+
+ return new EGLSurface(dpy, config, pointer);
+ }
+
+ private static native long neglCreatePbufferSurface(long dpy_ptr, long config_ptr, long attrib_list);
+
+ /*
+ EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+ */
+
+ /**
+ * Sets the specified EGL surface attribute to the specified value.
+ *
+ * @param dpy the EGL display
+ * @param surface the EGL surface
+ * @param attribute the attribute
+ * @param value the attribute value
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static void eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, int attribute, int value) throws LWJGLException {
+ //LWJGLUtil.log("eglSurfaceAttrib");
+ if ( !neglSurfaceAttrib(dpy.getPointer(), surface.getPointer(), attribute, value) )
+ throwEGLError("Failed to set surface attribute.");
+ }
+
+ private static native boolean neglSurfaceAttrib(long dpy_ptr, long surface_ptr, int attribute, int value);
+
+ /**
+ * Destroys the specified EGL surface.
+ *
+ * @param dpy the EGL display
+ * @param surface the EGL surface to destroy
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static void eglDestroySurface(EGLDisplay dpy, EGLSurface surface) throws LWJGLException {
+ //LWJGLUtil.log("eglDestroySurface");
+ if ( !neglDestroySurface(dpy.getPointer(), surface.getPointer()) )
+ throwEGLError("Failed to destroy EGL surface.");
+ }
+
+ private static native boolean neglDestroySurface(long dpy_ptr, long surface_ptr);
+
+ /**
+ * Returns the value of the specified EGL surface attribute in the value parameter.
+ *
+ * @param dpy the EGL display
+ * @param surface the EGL surface
+ * @param attribute the surface attribute
+ * @param value the attribute value will be returned here
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ public static void eglQuerySurface(EGLDisplay dpy, EGLSurface surface, int attribute, IntBuffer value) throws LWJGLException {
+ //LWJGLUtil.log("eglQuerySurface");
+ BufferChecks.checkBuffer(value, 1);
+ if ( !neglQuerySurface(dpy.getPointer(), surface.getPointer(), attribute, MemoryUtil.getAddress(value)) )
+ throwEGLError("Failed to query surface attribute.");
+ }
+
+ private static native boolean neglQuerySurface(long dpy_ptr, long surface_ptr, int attribute, long value);
+
+ /**
+ * Binds the specified rendering API to the current thread.
+ *
+ * @param api the API to bind
+ *
+ * @return true if the bind was successful, false if an EGL error occurs
+ */
+ public static native boolean eglBindAPI(int api);
+
+ /**
+ * Returns the current rendering API.
+ *
+ * @return the rendering API bound to the current thread
+ */
+ public static native int eglQueryAPI();
+
+ /**
+ * Returns EGL to its state at thread initialization. This includes the following:
+ *
+ * For each client API supported by EGL, if there is a currently bound context,
+ * that context is released. This is equivalent to calling eglMakeCurrent
+ * with ctx set to EGL_NO_CONTEXT and both draw and read set to EGL_NO_SURFACE
+ *
+ * The current rendering API is reset to its value at thread initialization
+ * Any additional implementation-dependent per-thread state maintained by EGL
+ * is marked for deletion as soon as possible.
+ *
+ * @return true if thread state was released successfully, false is an EGL error occurs
+ */
+ static native boolean eglReleaseThread();
+
+ /*
+ EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+ EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+ EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+ */
+
+ /**
+ * Specifies the minimum number of video frame periods per buffer swap for
+ * the window associated with the current context.
+ *
+ * @param dpy the EGL display
+ * @param interval the frame interval
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static void eglSwapInterval(EGLDisplay dpy, int interval) throws LWJGLException {
+ //LWJGLUtil.log("eglSwapInterval");
+ if ( !neglSwapInterval(dpy.getPointer(), interval) )
+ throwEGLError("Failed to set swap interval.");
+ }
+
+ private static native boolean neglSwapInterval(long dpy_ptr, int interval);
+
+ /**
+ * Creates a new EGL context for the current rendering API.
+ *
+ * @param dpy the EGL display
+ * @param config the EGL config
+ * @param share_context the EGL context to share data with
+ * @param attrib_list the attribute list (may be null)
+ *
+ * @return the created EGL context
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, IntBuffer attrib_list) throws LWJGLException {
+ //LWJGLUtil.log("eglCreateContext");
+ checkAttribList(attrib_list);
+ final long pointer = neglCreateContext(dpy.getPointer(), config.getPointer(),
+ share_context == null ? EGL_NO_CONTEXT : share_context.getPointer(),
+ MemoryUtil.getAddressSafe(attrib_list));
+
+ if ( pointer == EGL_NO_CONTEXT )
+ throwEGLError("Failed to create EGL context.");
+
+ return new EGLContext(dpy, config, pointer);
+ }
+
+ private static native long neglCreateContext(long dpy_ptr, long config_ptr, long share_context_ptr, long attrib_list);
+
+ /**
+ * Destroys a rendering context.
+ *
+ * @param dpy the EGL display
+ * @param ctx the EGL context
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ static void eglDestroyContext(EGLDisplay dpy, EGLContext ctx) throws LWJGLException {
+ //LWJGLUtil.log("eglDestroyContext");
+ if ( !neglDestroyContext(dpy.getPointer(), ctx.getPointer()) )
+ throwEGLError("Failed to destroy context.");
+ }
+
+ private static native boolean neglDestroyContext(long dpy_ptr, long ctx_ptr);
+
+ /**
+ * Binds the specified context to the current thread and to the draw and read surfaces.
+ *
+ * @param dpy the EGL display
+ * @param draw the draw EGL surface
+ * @param read the read EGL surface
+ * @param ctx the EGL context to make current
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ * @throws PowerManagementEventException if an EGL power management event occurs
+ */
+ static void eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) throws LWJGLException, PowerManagementEventException {
+ //LWJGLUtil.log("eglMakeCurrent");
+ if ( !neglMakeCurrent(dpy.getPointer(),
+ draw == null ? EGL_NO_SURFACE : draw.getPointer(),
+ read == null ? EGL_NO_SURFACE : read.getPointer(),
+ ctx == null ? EGL_NO_CONTEXT : ctx.getPointer()) ) {
+ final int error = eglGetError();
+ if ( error == EGL_CONTEXT_LOST )
+ throw new PowerManagementEventException();
+ else
+ throwEGLError("Failed to change the current context.", error);
+ }
+ }
+
+ /**
+ * Releases the current context without assigning a new one.
+ *
+ * @param dpy the EGL display
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ * @throws PowerManagementEventException if an EGL power management event occurs
+ * @see #eglMakeCurrent(EGLDisplay, EGLSurface, EGLSurface, EGLContext)
+ */
+ public static void eglReleaseCurrent(EGLDisplay dpy) throws LWJGLException, PowerManagementEventException {
+ //LWJGLUtil.log("eglReleaseCurrent");
+ eglMakeCurrent(dpy, null, null, null);
+ }
+
+ private static native boolean neglMakeCurrent(long dpy_ptr, long draw_ptr, long read_ptr, long ctx_ptr);
+
+ /**
+ * Returns the current EGL context for the current rendering API.
+ * If there is no context current, null is returned.
+ *
+ * @return the current context
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ public static EGLContext eglGetCurrentContext() throws LWJGLException {
+ //LWJGLUtil.log("eglGetCurrentContext");
+ // Get current context
+ final long ctx = neglGetCurrentContext();
+ if ( ctx == EGL_NO_CONTEXT )
+ return null;
+
+ // Get current display
+ final EGLDisplay display = eglGetCurrentDisplay();
+
+ // Query context's CONFIG_ID
+ final IntBuffer attrib_list = APIUtil.getBufferInt();
+ neglQueryContext(display.getPointer(), ctx, EGL_CONFIG_ID, MemoryUtil.getAddress0(attrib_list));
+
+ final EGLConfig config = getEGLConfig(display, attrib_list);
+
+ // Create the context handle
+ return new EGLContext(display, config, ctx);
+ }
+
+ /**
+ * Returns true if the specified EGL context is the current context.
+ * This method is faster than using {@code #eglGetCurrentContext}
+ * and comparing the two EGLContext objects.
+ *
+ * @param context the EGL context
+ *
+ * @return true if the EGL context is current
+ *
+ * @see #eglGetCurrentContext()
+ */
+ public static boolean eglIsCurrentContext(EGLContext context) {
+ //LWJGLUtil.log("eglIsCurrentContext");
+ return neglGetCurrentContext() == context.getPointer();
+ }
+
+ private static native long neglGetCurrentContext();
+
+ /**
+ * Returns the EGL surfaces used for rendering by the current context.
+ * If there is no context current, null is returned.
+ *
+ * @param readdraw the read or draw surface
+ *
+ * @return the current surface
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ public static EGLSurface eglGetCurrentSurface(int readdraw) throws LWJGLException {
+ //LWJGLUtil.log("eglGetCurrentSurface");
+ final long surface = neglGetCurrentSurface(readdraw);
+ if ( surface == EGL_NO_SURFACE )
+ return null;
+
+ // Get current display
+ EGLDisplay display = eglGetCurrentDisplay();
+
+ // Query context's CONFIG_ID
+ final IntBuffer attrib_list = APIUtil.getBufferInt();
+ if ( !neglQuerySurface(display.getPointer(), surface, EGL_CONFIG_ID, MemoryUtil.getAddress0(attrib_list)) )
+ throwEGLError("Failed to query surface EGL config ID.");
+
+ final EGLConfig config = getEGLConfig(display, attrib_list);
+
+ // Create the surface handle
+ return new EGLSurface(display, config, surface);
+ }
+
+ private static native long neglGetCurrentSurface(int readdraw);
+
+ /**
+ * Returns the EGL display associated with the current context.
+ *
+ * @return the current display
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ public static EGLDisplay eglGetCurrentDisplay() throws LWJGLException {
+ //LWJGLUtil.log("eglGetCurrentDisplay");
+ return new EGLDisplay(neglGetCurrentDisplay());
+ }
+
+ private static native long neglGetCurrentDisplay();
+
+ /**
+ * Returns the value of the specified EGL context attribute in the value parameter.
+ *
+ * @param dpy the EGL display
+ * @param ctx the EGL context
+ * @param attribute the context attribute
+ * @param value the attribute value will be returned here
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs
+ */
+ public static void eglQueryContext(EGLDisplay dpy, EGLContext ctx, int attribute, IntBuffer value) throws LWJGLException {
+ //LWJGLUtil.log("eglQueryContext");
+ BufferChecks.checkBuffer(value, 1);
+ if ( !neglQueryContext(dpy.getPointer(), ctx.getPointer(), attribute, MemoryUtil.getAddress(value)) )
+ throwEGLError("Failed to query context attribute.");
+ }
+
+ private static native boolean neglQueryContext(long dpy_ptr, long ctx_ptr, int attribute, long value);
+
+ /**
+ * Prevents native rendering API functions from executing until any
+ * outstanding client API rendering affecting the same surface is complete.
+ *
+ * @return true if the wait was successful, false is an EGL error occurs
+ */
+ public static native boolean eglWaitClient();
+
+ /**
+ * This method does the equivalent of:
+ *
+ * EGLenum api = eglQueryAPI();
+ * eglBindAPI(EGL_OPENGL_ES_API);
+ * eglWaitClient();
+ * eglBindAPI(api);
+ *
+ *
+ * @return true if the wait was successful, false if an EGL error occurs
+ */
+ public static native boolean eglWaitGL();
+
+ /**
+ * Prevents a client API command sequence from executing until any outstanding
+ * native rendering affecting the same surface is complete.
+ *
+ * @param engine the native rendering engine
+ *
+ * @return true if the wait was successful, false if an EGL error occurs
+ */
+ public static native boolean eglWaitNative(int engine);
+
+ /**
+ * Posts the color buffer to the window.
+ *
+ * @param dpy the EGL display
+ * @param surface the EGL back-buffered window surface
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL occurs
+ * @throws PowerManagementEventException if an EGL power management event occurs
+ */
+ static void eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) throws LWJGLException, PowerManagementEventException {
+ //LWJGLUtil.log("eglSwapBuffers");
+ if ( !neglSwapBuffers(dpy.getPointer(), surface.getPointer()) ) {
+ final int error = eglGetError();
+ if ( error == EGL_CONTEXT_LOST )
+ throw new PowerManagementEventException();
+ else
+ throwEGLError("Failed to swap buffers.", error);
+ }
+ }
+
+ private static native boolean neglSwapBuffers(long dpy_ptr, long surface_ptr);
+
+ //EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+
+ /* --------------------------------
+ HELPER METHODS
+ -------------------------------- */
+
+ static void checkAttribList(IntBuffer attrib_list) {
+ if ( attrib_list == null )
+ return;
+
+ //BufferChecks.checkDirect(attrib_list);
+ if ( attrib_list.remaining() % 2 != 1 )
+ throw new IllegalArgumentException("Invalid number of values in attribute list.");
+ if ( attrib_list.get(attrib_list.limit() - 1) != EGL_NONE )
+ throw new IllegalArgumentException("The attribute list is not terminated with EGL_NONE.");
+ }
+
+ private static EGLConfig getEGLConfig(final EGLDisplay dpy, final IntBuffer attrib_list) throws LWJGLException {
+ final int configID = attrib_list.get(0);
+
+ // -- This fails on the emulator
+ // Get EGL config used by the context
+ attrib_list.put(0, EGL_CONFIG_ID).put(1, configID).put(2, EGL_NONE);
+
+ final PointerBuffer configs_buffer = APIUtil.getBufferPointer(1);
+ if ( !neglChooseConfig(dpy.getPointer(), MemoryUtil.getAddress(attrib_list), MemoryUtil.getAddress0(configs_buffer), 1, MemoryUtil.getAddress(attrib_list, 3)) )
+ throwEGLError("Failed to choose EGL config.");
+
+ return new EGLConfig(dpy, configs_buffer.get(0));
+
+ // -- Emulator workaround
+ /*
+ EGLConfig config = null;
+
+ final EGLConfig[] configs = eglGetConfigs(dpy, null, attrib_list);
+ final int config_size = attrib_list.get(0);
+ for ( int i = 0; i < config_size; i++ ) {
+ if ( configs[i].getConfigID() == configID ) {
+ config = configs[i];
+ break;
+ }
+ }
+
+ if ( config == null )
+ throwEGLError("Failed to retrieve EGL config for current context.");
+
+ return config;
+ //*/
+ }
+
+ static void throwEGLError(final String msg) throws LWJGLException {
+ throwEGLError(msg, eglGetError());
+ }
+
+ static void throwEGLError(String msg, final int error) throws LWJGLException {
+ if ( error != EGL_SUCCESS )
+ msg += " EGL error: " + Util.translateEGLErrorString(error);
+
+ throw new LWJGLException(msg);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLConfig.java b/src/java/org/lwjgl/opengles/EGLConfig.java
new file mode 100644
index 0000000..4e1988f
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLConfig.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.PointerWrapperAbstract;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/** EGLConfig wrapper class. */
+public final class EGLConfig extends PointerWrapperAbstract {
+
+ private final EGLDisplay display;
+
+ private final int configID;
+
+ EGLConfig(final EGLDisplay display, final long pointer) throws LWJGLException {
+ super(pointer);
+
+ this.display = display;
+ this.configID = getAttribute(EGL_CONFIG_ID);
+ }
+
+ /**
+ * Returns the EGL display from which this EGL config was retrieved.
+ *
+ * @return the EGL display
+ */
+ public EGLDisplay getDisplay() {
+ return display;
+ }
+
+ /**
+ * Returns the EGL_CONFIG_ID attribute of this EGLConfig.
+ *
+ * @return the EGL_CONFIG_ID
+ */
+ public int getConfigID() {
+ return configID;
+ }
+
+ /**
+ * Returns the value of the specified EGL config attribute.
+ *
+ * @param attribute the attribute
+ *
+ * @return the attribute value
+ */
+ public int getAttribute(final int attribute) throws LWJGLException {
+ return eglGetConfigAttrib(display, this, attribute);
+ }
+
+ public boolean equals(final Object obj) {
+ if ( obj == null || !(obj instanceof EGLConfig) )
+ return false;
+
+ return getPointer() == ((EGLConfig)obj).getPointer();
+ }
+
+ public String toString() {
+ final StringBuilder sb = new StringBuilder(512);
+
+ sb.append("EGLConfig (").append(configID).append(")");
+ sb.append("\n------------");
+
+ try {
+ sb.append("\nEGL_LEVEL").append(": ").append(getAttribute(EGL_LEVEL));
+ sb.append("\nEGL_RENDERABLE_TYPE").append(": ").append(Integer.toBinaryString(getAttribute(EGL_RENDERABLE_TYPE)));
+ sb.append("\nEGL_NATIVE_RENDERABLE").append(": ").append(getAttribute(EGL_NATIVE_RENDERABLE) == EGL_TRUE);
+ sb.append("\nEGL_SURFACE_TYPE").append(": ").append(Integer.toBinaryString(getAttribute(EGL_SURFACE_TYPE)));
+ } catch (LWJGLException e) {
+ }
+
+ final PixelFormat.Attrib[] attribEnums = PixelFormat.Attrib.values();
+ for ( PixelFormat.Attrib attribEnum : attribEnums ) {
+ if ( attribEnum.isSurfaceAttrib() )
+ continue;
+
+ try {
+ final int attrib = getAttribute(attribEnum.getEGLAttrib());
+ sb.append("\nEGL_").append(attribEnum.name()).append(": ").append(attrib);
+ } catch (LWJGLException e) {
+ //System.out.println("Failed to retrieve: " + attribEnum.name());
+ // Ignore, can happen when querying unsupported attributes (e.g. extension ones)
+ }
+ }
+
+ return sb.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLContext.java b/src/java/org/lwjgl/opengles/EGLContext.java
new file mode 100644
index 0000000..39ac7a4
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLContext.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.PointerWrapperAbstract;
+
+import java.nio.IntBuffer;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/** EGLContext wrapper class. */
+public final class EGLContext extends PointerWrapperAbstract {
+
+ private EGLDisplay display;
+ private final EGLConfig config;
+
+ private boolean destroyed;
+
+ EGLContext(final EGLDisplay display, final EGLConfig config, final long pointer) {
+ super(pointer);
+
+ if ( !display.isInitialized() )
+ throw new IllegalStateException("Invalid EGL display specified.");
+
+ if ( config.getDisplay() != display )
+ throw new IllegalStateException("Invalid EGL config specified.");
+
+ this.display = display;
+ this.config = config;
+ }
+
+ public void setDisplay(EGLDisplay display) {
+ this.display = display;
+ }
+
+ EGLDisplay getDisplay() {
+ return display;
+ }
+
+ EGLConfig getConfig() {
+ return config;
+ }
+
+ private void checkDestroyed() {
+ if ( destroyed )
+ throw new IllegalStateException("The EGL surface has been destroyed.");
+ }
+
+ public void destroy() throws LWJGLException {
+ eglDestroyContext(display, this);
+ destroyed = true;
+ }
+
+ /**
+ * Returns the value of the specified EGL context attribute.
+ *
+ * @param attribute the context attribute
+ *
+ * @return the attribute value
+ */
+ int getAttribute(final int attribute) throws LWJGLException {
+ checkDestroyed();
+
+ IntBuffer value = APIUtil.getBufferInt();
+ eglQueryContext(display, this, attribute, value);
+ return value.get(0);
+ }
+
+ public void makeCurrent(final EGLSurface surface) throws LWJGLException, PowerManagementEventException {
+ makeCurrent(surface, surface);
+ }
+
+ public void makeCurrent(final EGLSurface draw, final EGLSurface read) throws LWJGLException, PowerManagementEventException {
+ eglMakeCurrent(display, draw, read, this);
+ }
+
+ public boolean equals(final Object obj) {
+ if ( obj == null || !(obj instanceof EGLContext) )
+ return false;
+
+ return getPointer() == ((EGLContext)obj).getPointer();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLDisplay.java b/src/java/org/lwjgl/opengles/EGLDisplay.java
new file mode 100644
index 0000000..5e6016f
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLDisplay.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.PointerWrapperAbstract;
+
+import java.nio.IntBuffer;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/** EGLDisplay wrapper class. */
+public final class EGLDisplay extends PointerWrapperAbstract {
+
+ private int majorVersion;
+ private int minorVersion;
+
+ private Set extensions;
+
+ private boolean initialized;
+
+ EGLDisplay(final long pointer) throws LWJGLException {
+ super(pointer);
+
+ initialize();
+
+ /*final EGLConfig[] configs = eglGetConfigs(this, null, APIUtil.getBufferInt());
+ for ( EGLConfig config : configs ) {
+ System.out.println(config);
+ System.out.println("");
+ }*/
+ }
+
+ /**
+ * Returns the major EGL version of this EGL display.
+ *
+ * @return the major EGL version
+ */
+ public int getMajorVersion() {
+ return majorVersion;
+ }
+
+ /**
+ * Returns the minor EGL version of this EGL display.
+ *
+ * @return the minor EGL version
+ */
+ public int getMinorVersion() {
+ return minorVersion;
+ }
+
+ /**
+ * Returns true if the specified EGL extension is supported by this EGL display.
+ *
+ * @param eglExtension the EGL extension
+ *
+ * @return true if the extension is supported
+ */
+ public boolean isExtensionSupported(final String eglExtension) {
+ checkInitialized();
+ if ( extensions == null ) {
+ extensions = new HashSet(16);
+
+ final StringTokenizer tokenizer = new StringTokenizer(eglQueryString(this, EGL_EXTENSIONS));
+ while ( tokenizer.hasMoreTokens() )
+ extensions.add(tokenizer.nextToken());
+ }
+
+ return extensions.contains(eglExtension);
+ }
+
+ boolean isInitialized() {
+ return initialized;
+ }
+
+ private void initialize() throws LWJGLException {
+ IntBuffer version = APIUtil.getBufferInt();
+ eglInitialize(this, version);
+
+ majorVersion = version.get(0);
+ minorVersion = version.get(1);
+
+ initialized = true;
+ }
+
+ private void checkInitialized() {
+ if ( !initialized )
+ throw new IllegalStateException("The EGL display needs to be initialized first.");
+ }
+
+ /** Release the resources associated with this EGL display. */
+ public void terminate() throws LWJGLException {
+ eglTerminate(this);
+
+ majorVersion = 0;
+ minorVersion = 0;
+
+ initialized = false;
+ }
+
+ /**
+ * Returns a string describing some aspect of the EGL implementation running on the specified display.
+ *
+ * @param name the value to query
+ *
+ * @return the description
+ */
+ public String query(int name) {
+ checkInitialized();
+ return eglQueryString(this, name);
+ }
+
+ int getConfigsNum() throws LWJGLException {
+ checkInitialized();
+ return eglGetConfigsNum(this);
+ }
+
+ EGLConfig[] getConfigs(EGLConfig[] configs, IntBuffer num_config) throws LWJGLException {
+ checkInitialized();
+ return eglGetConfigs(this, configs, num_config);
+ }
+
+ int getConfigNum(IntBuffer attrib_list) throws LWJGLException {
+ checkInitialized();
+ return eglChooseConfigNum(this, attrib_list);
+ }
+
+ /** Returns the available EGL configs on this display that satisfy the specified list of attributes. */
+ public EGLConfig[] chooseConfig(IntBuffer attrib_list, EGLConfig[] configs, IntBuffer num_config) throws LWJGLException {
+ checkInitialized();
+ return eglChooseConfig(this, attrib_list, configs, num_config);
+ }
+
+ /**
+ * Creates an on-screen rendering surface on this EGL display.
+ *
+ * @param config the EGL config
+ * @param window the native window handle
+ * @param attrib_list an attribute list (may be null)
+ *
+ * @return the EGL surface
+ */
+ public EGLSurface createWindowSurface(EGLConfig config, long window, IntBuffer attrib_list) throws LWJGLException {
+ checkInitialized();
+
+ if ( config.getDisplay() != this )
+ throw new IllegalArgumentException("Invalid EGL config specified.");
+
+ return eglCreateWindowSurface(this, config, window, attrib_list);
+ }
+
+ EGLSurface createPbufferSurface(EGLConfig config, IntBuffer attrib_list) throws LWJGLException {
+ checkInitialized();
+
+ if ( config.getDisplay() != this )
+ throw new IllegalArgumentException("Invalid EGL config specified.");
+
+ return eglCreatePbufferSurface(this, config, attrib_list);
+ }
+
+ public EGLContext createContext(EGLConfig config, EGLContext shareContext, IntBuffer attrib_list) throws LWJGLException {
+ checkInitialized();
+
+ if ( config.getDisplay() != this )
+ throw new IllegalStateException("Invalid EGL config specified.");
+
+ if ( shareContext != null && shareContext.getDisplay() != this )
+ throw new IllegalStateException("Invalid shared EGL context specified.");
+
+ return eglCreateContext(this, config, shareContext, attrib_list);
+ }
+
+ public void setSwapInterval(final int interval) throws LWJGLException {
+ eglSwapInterval(this, interval);
+ }
+
+ public boolean equals(final Object obj) {
+ if ( obj == null || !(obj instanceof EGLDisplay) )
+ return false;
+
+ return getPointer() == ((EGLDisplay)obj).getPointer();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLImageOES.java b/src/java/org/lwjgl/opengles/EGLImageOES.java
new file mode 100644
index 0000000..6dabe9c
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLImageOES.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.PointerWrapperAbstract;
+
+/** EGLImageOES wrapper class. */
+public final class EGLImageOES extends PointerWrapperAbstract {
+
+ public EGLImageOES(final long pointer) {
+ super(pointer);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLKHRFenceSync.java b/src/java/org/lwjgl/opengles/EGLKHRFenceSync.java
new file mode 100644
index 0000000..4063d60
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLKHRFenceSync.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.MemoryUtil;
+
+import java.nio.IntBuffer;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/** EGL_KHR_fence_sync wrapper class. */
+public final class EGLKHRFenceSync {
+
+ /**
+ * Accepted by the <type> parameter of eglCreateSyncKHR, and returned
+ * in <value> when eglGetSyncAttribKHR is called with <attribute>
+ * EGL_SYNC_TYPE_KHR:
+ */
+ public static final int EGL_SYNC_FENCE_KHR = 0x30F9;
+
+ /** Accepted by the <attribute> parameter of eglGetSyncAttribKHR: */
+ public static final int EGL_SYNC_TYPE_KHR = 0x30F7,
+ EGL_SYNC_STATUS_KHR = 0x30F1,
+ EGL_SYNC_CONDITION_KHR = 0x30F8;
+
+ /**
+ * Returned in <value> when eglGetSyncAttribKHR is called with
+ * <attribute> EGL_SYNC_STATUS_KHR:
+ */
+ public static final int EGL_SIGNALED_KHR = 0x30F2,
+ EGL_UNSIGNALED_KHR = 0x30F3;
+
+ /**
+ * Returned in <value> when eglGetSyncAttribKHR is called with
+ * <attribute> EGL_SYNC_CONDITION_KHR:
+ */
+ public static final int EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR = 0x30F0;
+
+ /** Accepted in the <flags> parameter of eglClientWaitSyncKHR: */
+ public static final int EGL_SYNC_FLUSH_COMMANDS_BIT_KHR = 0x0001;
+
+ /** Accepted in the <timeout> parameter of eglClientWaitSyncKHR: */
+ public static final long EGL_FOREVER_KHR = 0xFFFFFFFFFFFFFFFFl;
+
+ /** Returned by eglClientWaitSyncKHR: */
+ public static final int EGL_TIMEOUT_EXPIRED_KHR = 0x30F5,
+ EGL_CONDITION_SATISFIED_KHR = 0x30F6;
+
+ /** Returned by eglCreateSyncKHR in the event of an error: */
+ public static final long EGL_NO_SYNC_KHR = 0;
+
+ static {
+ initNativeStubs();
+ }
+
+ private EGLKHRFenceSync() {
+ }
+
+ private static native void initNativeStubs();
+
+ /**
+ * Creates a fence sync object for the specified EGL display and returns
+ * a handle to the new object.
+ *
+ * @param dpy the EGL display
+ * @param type the sync type
+ * @param attrib_list an attribute list (may be null)
+ *
+ * @return the created fence sync object
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, int type, IntBuffer attrib_list) throws LWJGLException {
+ checkAttribList(attrib_list);
+
+ final long pointer = neglCreateSyncKHR(dpy.getPointer(), type, MemoryUtil.getAddressSafe(attrib_list));
+
+ if ( pointer == EGL_NO_SYNC_KHR )
+ throwEGLError("Failed to create KHR fence sync object.");
+
+ return new EGLSyncKHR(pointer);
+ }
+
+ private static native long neglCreateSyncKHR(long dpy_ptr, int type, long attrib_list);
+
+ /**
+ * Destroys an existing sync object.
+ *
+ * @param sync the sync object
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static void eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) throws LWJGLException {
+ if ( !neglDestroySyncKHR(dpy.getPointer(), sync.getPointer()) )
+ throwEGLError("Failed to destroy KHR fence sync object.");
+ }
+
+ private static native boolean neglDestroySyncKHR(long dpy_ptr, long sync_ptr);
+
+ /**
+ * Blocks the calling thread until the specified sync object is
+ * signaled, or until a specified timeout value expires.
+ *
+ * @param sync the sync object
+ * @param flags the block flags
+ * @param timeout the block timeout
+ *
+ * @return the sync object status
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static int eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, int flags, long timeout) throws LWJGLException {
+ final int status = neglClientWaitSyncKHR(dpy.getPointer(), sync.getPointer(), flags, timeout);
+
+ if ( status == EGL_FALSE )
+ throwEGLError("Failed to block on KHR fence sync object.");
+
+ return status;
+ }
+
+ private static native int neglClientWaitSyncKHR(long dpy_ptr, long sync_ptr, int flags, long timeout);
+
+ /**
+ * Returns the value of the sync object attribute.
+ *
+ * @param sync the sync object
+ * @param attribute the attribute to query
+ *
+ * @return the attribute value
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static int eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, int attribute) throws LWJGLException {
+ final IntBuffer value = APIUtil.getBufferInt();
+
+ if ( !neglGetSyncAttribKHR(dpy.getPointer(), sync.getPointer(), attribute, MemoryUtil.getAddress(value)) )
+ throwEGLError("Failed to get KHR fence sync object attribute.");
+
+ return value.get(0);
+ }
+
+ private static native boolean neglGetSyncAttribKHR(long dpy_ptr, long sync_ptr, int attribute, long value);
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLKHRReusableSync.java b/src/java/org/lwjgl/opengles/EGLKHRReusableSync.java
new file mode 100644
index 0000000..40297b0
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLKHRReusableSync.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.LWJGLException;
+
+import java.nio.IntBuffer;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/** EGL_KHR_reusable_sync wrapper class. */
+public final class EGLKHRReusableSync {
+
+ /**
+ * Accepted by the <type> parameter of eglCreateSyncKHR, and returned
+ * in <value> when eglGetSyncAttribKHR is called with <attribute>
+ * EGL_SYNC_TYPE_KHR:
+ */
+ public static final int EGL_SYNC_REUSABLE_KHR = 0x30FA;
+
+ /** Accepted by the <attribute> parameter of eglGetSyncAttribKHR: */
+ public static final int EGL_SYNC_TYPE_KHR = 0x30F7,
+ EGL_SYNC_STATUS_KHR = 0x30F1;
+
+ /**
+ * Returned in <value> when eglGetSyncAttribKHR is called with
+ * <attribute> EGL_SYNC_STATUS_KHR:
+ */
+ public static final int EGL_SIGNALED_KHR = 0x30F2,
+ EGL_UNSIGNALED_KHR = 0x30F3;
+
+ /** Accepted in the <flags> parameter of eglClientWaitSyncKHR: */
+ public static final int EGL_SYNC_FLUSH_COMMANDS_BIT_KHR = 0x0001;
+
+ /** Accepted in the <timeout> parameter of eglClientWaitSyncKHR: */
+ public static final long EGL_FOREVER_KHR = 0xFFFFFFFFFFFFFFFFl;
+
+ /** Returned by eglClientWaitSyncKHR: */
+ public static final int EGL_TIMEOUT_EXPIRED_KHR = 0x30F5,
+ EGL_CONDITION_SATISFIED_KHR = 0x30F6;
+
+ /** Returned by eglCreateSyncKHR in the event of an error: */
+ public static final long EGL_NO_SYNC_KHR = 0;
+
+ static {
+ initNativeStubs();
+ }
+
+ private EGLKHRReusableSync() {
+ }
+
+ private static native void initNativeStubs();
+
+ /**
+ * Creates a fence sync object for the specified EGL display and returns
+ * a handle to the new object.
+ *
+ * @param dpy the EGL display
+ * @param type the sync type
+ * @param attrib_list an attribute list (may be null)
+ *
+ * @return the created fence sync object
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, int type, IntBuffer attrib_list) throws LWJGLException {
+ return EGLKHRFenceSync.eglCreateSyncKHR(dpy, type, attrib_list);
+ }
+
+ /**
+ * Destroys an existing sync object.
+ *
+ * @param sync the sync object
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static void eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) throws LWJGLException {
+ EGLKHRFenceSync.eglDestroySyncKHR(dpy, sync);
+ }
+
+ /**
+ * Blocks the calling thread until the specified sync object is
+ * signaled, or until a specified timeout value expires.
+ *
+ * @param sync the sync object
+ * @param flags the block flags
+ * @param timeout the block timeout
+ *
+ * @return the sync object status
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static int eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, int flags, long timeout) throws LWJGLException {
+ return EGLKHRFenceSync.eglClientWaitSyncKHR(dpy, sync, flags, timeout);
+ }
+
+ /**
+ * Signals or unsignals the sync object by changing its status to
+ * the specified mode.
+ *
+ * @param sync the sync object
+ * @param mode the mode
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static void eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, int mode) throws LWJGLException {
+ if ( !neglSignalSyncKHR(dpy.getPointer(), sync.getPointer(), mode) )
+ throwEGLError("Failed to signal the KHR fence sync object.");
+ }
+
+ private static native boolean neglSignalSyncKHR(long dpy_ptr, long sync_ptr, int mode);
+
+ /**
+ * Returns the value of the sync object attribute.
+ *
+ * @param sync the sync object
+ * @param attribute the attribute to query
+ *
+ * @return the attribute value
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static int eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, int attribute) throws LWJGLException {
+ return EGLKHRFenceSync.eglGetSyncAttribKHR(dpy, sync, attribute);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLNVSync.java b/src/java/org/lwjgl/opengles/EGLNVSync.java
new file mode 100644
index 0000000..88fe2b1
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLNVSync.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.MemoryUtil;
+
+import java.nio.IntBuffer;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/** EGL_NV_sync wrapper class. */
+public final class EGLNVSync {
+
+ /**
+ * Accepted in the <condition> parameter of eglCreateFenceSyncNV, and
+ * returned in <value> when eglGetSyncAttribNV is called with <attribute>
+ * EGL_SYNC_CONDITION_NV:
+ */
+ public static final int EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV = 0x30E6;
+
+ /**
+ * Accepted as an attribute name in the <attrib_list> parameter of
+ * eglCreateFenceSyncNV, and by the <attribute> parameter of
+ * eglGetSyncAttribNV:
+ */
+ public static final int EGL_SYNC_STATUS_NV = 0x30E7;
+
+ /**
+ * Accepted as an attribute value in the <attrib_list> parameter of
+ * eglCreateFenceSyncNV for the EGL_SYNC_STATUS_NV attribute, by
+ * the <mode> parameter of eglSignalSyncNV and returned in <value>
+ * when eglGetSyncAttribNV is called with <attribute>
+ * EGL_SYNC_STATUS_NV:
+ */
+ public static final int EGL_SIGNALED_NV = 0x30E8,
+ EGL_UNSIGNALED_NV = 0x30E9;
+
+ /** Accepted in the <flags> parameter of eglClientWaitSyncNV: */
+ public static final int EGL_SYNC_FLUSH_COMMANDS_BIT_NV = 0x0001;
+
+ /** Accepted in the <timeout> parameter of eglClientWaitSyncNV: */
+ public static final long EGL_FOREVER_NV = 0xFFFFFFFFFFFFFFFFL;
+
+ /** Returned by eglClientWaitSyncNV: */
+ public static final int EGL_ALREADY_SIGNALED_NV = 0x30EA,
+ EGL_TIMEOUT_EXPIRED_NV = 0x30EB,
+ EGL_CONDITION_SATISFIED_NV = 0x30EC;
+
+ /** Accepted in the <attribute> parameter of eglGetSyncAttribNV: */
+ public static final int EGL_SYNC_TYPE_NV = 0x30ED,
+ EGL_SYNC_CONDITION_NV = 0x30EE;
+
+ /**
+ * Returned in <value> when eglGetSyncAttribNV is called with
+ * <attribute> EGL_SYNC_TYPE_NV:
+ */
+ public static final int EGL_SYNC_FENCE_NV = 0x30EF;
+
+ /** Returned by eglCreateFenceSyncNV in the event of an error: */
+ public static final long EGL_NO_SYNC_NV = 0;
+
+ static {
+ initNativeStubs();
+ }
+
+ private EGLNVSync() {
+ }
+
+ private static native void initNativeStubs();
+
+ /**
+ * Creates a fence sync object for the specified EGL display and returns
+ * a handle to the new object.
+ *
+ * @param dpy the EGL display
+ * @param condition the sync condition
+ * @param attrib_list an attribute list (may be null)
+ *
+ * @return the created fence sync object
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static EGLSyncNV eglCreateFenceSyncNV(EGLDisplay dpy, int condition, IntBuffer attrib_list) throws LWJGLException {
+ checkAttribList(attrib_list);
+
+ final long pointer = neglCreateFenceSyncNV(dpy.getPointer(), condition, MemoryUtil.getAddressSafe(attrib_list));
+
+ if ( pointer == EGL_NO_SYNC_NV )
+ throwEGLError("Failed to create NV fence sync object.");
+
+ return new EGLSyncNV(pointer);
+ }
+
+ private static native long neglCreateFenceSyncNV(long dpy_ptr, int condition, long attrib_list);
+
+ /**
+ * Destroys an existing sync object.
+ *
+ * @param sync the sync object
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static void eglDestroySyncNV(EGLSyncNV sync) throws LWJGLException {
+ if ( !neglDestroySyncNV(sync.getPointer()) )
+ throwEGLError("Failed to destroy NV fence sync object.");
+ }
+
+ private static native boolean neglDestroySyncNV(long sync_ptr);
+
+ /**
+ * Inserts a fence command into the command stream of the bound API's current
+ * context and associates it with sync object.
+ *
+ * @param sync the sync object
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static void eglFenceNV(EGLSyncNV sync) throws LWJGLException {
+ if ( !neglFenceNV(sync.getPointer()) )
+ throwEGLError("Failed to insert NV fence command.");
+ }
+
+ private static native boolean neglFenceNV(long sync_ptr);
+
+ /**
+ * Blocks the calling thread until the specified sync object is
+ * signaled, or until a specified timeout value expires.
+ *
+ * @param sync the sync object
+ * @param flags the block flags
+ * @param timeout the block timeout
+ *
+ * @return the sync object status
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static int eglClientWaitSyncNV(EGLSyncNV sync, int flags, long timeout) throws LWJGLException {
+ final int status = neglClientWaitSyncNV(sync.getPointer(), flags, timeout);
+
+ if ( status == EGL_FALSE )
+ throwEGLError("Failed to block on NV fence sync object.");
+
+ return status;
+ }
+
+ private static native int neglClientWaitSyncNV(long sync_ptr, int flags, long timeout);
+
+ /**
+ * Signals or unsignals the sync object by changing its status to
+ * the specified mode.
+ *
+ * @param sync the sync object
+ * @param mode the mode
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static void eglSignalSyncNV(EGLSyncNV sync, int mode) throws LWJGLException {
+ if ( !neglSignalSyncNV(sync.getPointer(), mode) )
+ throwEGLError("Failed to signal the NV fence sync object.");
+ }
+
+ private static native boolean neglSignalSyncNV(long sync_ptr, int mode);
+
+ /**
+ * Returns the value of the sync object attribute.
+ *
+ * @param sync the sync object
+ * @param attribute the attribute to query
+ *
+ * @return the attribute value
+ *
+ * @throws org.lwjgl.LWJGLException if an EGL error occurs.
+ */
+ public static int eglGetSyncAttribNV(EGLSyncNV sync, int attribute) throws LWJGLException {
+ final IntBuffer value = APIUtil.getBufferInt();
+
+ if ( !neglGetSyncAttribNV(sync.getPointer(), attribute, MemoryUtil.getAddress0(value)) )
+ throwEGLError("Failed to get NV fence sync object attribute.");
+
+ return value.get(0);
+ }
+
+ private static native boolean neglGetSyncAttribNV(long sync_ptr, int attribute, long value);
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLSurface.java b/src/java/org/lwjgl/opengles/EGLSurface.java
new file mode 100644
index 0000000..a68be83
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLSurface.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.PointerWrapperAbstract;
+
+import java.nio.IntBuffer;
+
+import static org.lwjgl.opengles.EGL.*;
+
+/** EGLSurface wrapper class. */
+public final class EGLSurface extends PointerWrapperAbstract {
+
+ private final EGLDisplay display;
+ private final EGLConfig config;
+
+ private boolean destroyed;
+
+ EGLSurface(final EGLDisplay display, final EGLConfig config, final long pointer) {
+ super(pointer);
+
+ if ( !display.isInitialized() )
+ throw new IllegalStateException("Invalid EGL display specified.");
+
+ this.display = display;
+ this.config = config;
+ }
+
+ /**
+ * Returns the EGL display from which this EGL surface was created.
+ *
+ * @return the EGL display
+ */
+ public EGLDisplay getDisplay() {
+ return display;
+ }
+
+ /**
+ * Returns the EGL config associated with this EGL surface.
+ *
+ * @return the EGL config
+ */
+ public EGLConfig getConfig() {
+ return config;
+ }
+
+ private void checkDestroyed() {
+ if ( destroyed )
+ throw new IllegalStateException("The EGL surface has been destroyed.");
+ }
+
+ /** Destroys this EGL surface. */
+ public void destroy() throws LWJGLException {
+ eglDestroySurface(display, this);
+ destroyed = true;
+ }
+
+ void setAttribute(int attribute, int value) throws LWJGLException {
+ checkDestroyed();
+ eglSurfaceAttrib(display, this, attribute, value);
+ }
+
+ /**
+ * Returns the value of the specified EGL surface attribute.
+ *
+ * @param attribute the surface attribute
+ *
+ * @return the attribute value
+ */
+ public int getAttribute(int attribute) throws LWJGLException {
+ checkDestroyed();
+
+ IntBuffer value = APIUtil.getBufferInt();
+ eglQuerySurface(display, this, attribute, value);
+ return value.get(0);
+ }
+
+ public void swapBuffers() throws LWJGLException, PowerManagementEventException {
+ checkDestroyed();
+ eglSwapBuffers(display, this);
+ }
+
+ public boolean equals(final Object obj) {
+ if ( obj == null || !(obj instanceof EGLSurface) )
+ return false;
+
+ return getPointer() == ((EGLSurface)obj).getPointer();
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLSyncKHR.java b/src/java/org/lwjgl/opengles/EGLSyncKHR.java
new file mode 100644
index 0000000..eb2f5be
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLSyncKHR.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.PointerWrapperAbstract;
+
+/** EGLSyncKHR wrapper class. */
+public class EGLSyncKHR extends PointerWrapperAbstract {
+
+ public EGLSyncKHR(final long pointer) {
+ super(pointer);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/EGLSyncNV.java b/src/java/org/lwjgl/opengles/EGLSyncNV.java
new file mode 100644
index 0000000..84fb233
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/EGLSyncNV.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.PointerWrapperAbstract;
+
+/** EGLSyncNV wrapper class. */
+public class EGLSyncNV extends PointerWrapperAbstract {
+
+ public EGLSyncNV(final long pointer) {
+ super(pointer);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/FastIntMap.java b/src/java/org/lwjgl/opengles/FastIntMap.java
new file mode 100644
index 0000000..d452b39
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/FastIntMap.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.lwjgl.opengles;
+
+import java.util.Iterator;
+
+/**
+ * A hash map using primitive ints as keys rather than objects.
+ *
+ * @author Justin Couch
+ * @author Alex Chaffee (alex@apache.org)
+ * @author Stephen Colebourne
+ * @author Nathan Sweet
+ */
+final class FastIntMap implements Iterable> {
+
+ private Entry[] table;
+ private int size, mask, capacity, threshold;
+
+ /** Same as: FastIntMap(16, 0.75f); */
+ FastIntMap() {
+ this(16, 0.75f);
+ }
+
+ /** Same as: FastIntMap(initialCapacity, 0.75f); */
+ FastIntMap(int initialCapacity) {
+ this(initialCapacity, 0.75f);
+ }
+
+ FastIntMap(int initialCapacity, float loadFactor) {
+ if ( initialCapacity > 1 << 30 ) throw new IllegalArgumentException("initialCapacity is too large.");
+ if ( initialCapacity < 0 ) throw new IllegalArgumentException("initialCapacity must be greater than zero.");
+ if ( loadFactor <= 0 ) throw new IllegalArgumentException("initialCapacity must be greater than zero.");
+ capacity = 1;
+ while ( capacity < initialCapacity )
+ capacity <<= 1;
+ this.threshold = (int)(capacity * loadFactor);
+ this.table = new Entry[capacity];
+ this.mask = capacity - 1;
+ }
+
+ private int index(final int key) {
+ return index(key, mask);
+ }
+
+ private static int index(final int key, final int mask) {
+ return key & mask;
+ }
+
+ public V put(int key, V value) {
+ final Entry[] table = this.table;
+ int index = index(key);
+
+ // Check if key already exists.
+ for ( Entry e = table[index]; e != null; e = e.next ) {
+ if ( e.key != key ) continue;
+ V oldValue = e.value;
+ e.value = value;
+ return oldValue;
+ }
+
+ table[index] = new Entry(key, value, table[index]);
+
+ if ( size++ >= threshold )
+ rehash(table);
+
+ return null;
+ }
+
+ private void rehash(final Entry[] table) {
+ final int newCapacity = 2 * capacity;
+ final int newMask = newCapacity - 1;
+
+ final Entry[] newTable = new Entry[newCapacity];
+
+ for ( int i = 0, index; i < table.length; i++ ) {
+ Entry e = table[i];
+ if ( e == null ) continue;
+ do {
+ final Entry next = e.next;
+ index = index(e.key, newMask);
+ e.next = newTable[index];
+ newTable[index] = e;
+ e = next;
+ } while ( e != null );
+ }
+
+ this.table = newTable;
+ capacity = newCapacity;
+ mask = newMask;
+ threshold *= 2;
+ }
+
+ public V get(int key) {
+ final int index = index(key);
+ for ( Entry e = table[index]; e != null; e = e.next )
+ if ( e.key == key ) return e.value;
+ return null;
+ }
+
+ public boolean containsValue(Object value) {
+ final Entry[] table = this.table;
+ for ( int i = table.length - 1; i >= 0; i-- )
+ for ( Entry e = table[i]; e != null; e = e.next )
+ if ( e.value.equals(value) ) return true;
+ return false;
+ }
+
+ public boolean containsKey(int key) {
+ final int index = index(key);
+ for ( Entry e = table[index]; e != null; e = e.next )
+ if ( e.key == key ) return true;
+ return false;
+ }
+
+ public V remove(int key) {
+ final int index = index(key);
+
+ Entry prev = table[index];
+ Entry e = prev;
+ while ( e != null ) {
+ Entry next = e.next;
+ if ( e.key == key ) {
+ size--;
+ if ( prev == e )
+ table[index] = next;
+ else
+ prev.next = next;
+ return e.value;
+ }
+ prev = e;
+ e = next;
+ }
+ return null;
+ }
+
+ public int size() {
+ return size;
+ }
+
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ public void clear() {
+ final Entry[] table = this.table;
+ for ( int index = table.length - 1; index >= 0; index-- )
+ table[index] = null;
+ size = 0;
+ }
+
+ public EntryIterator iterator() {
+ return new EntryIterator();
+ }
+
+ public class EntryIterator implements Iterator> {
+
+ private int nextIndex;
+ private Entry current;
+
+ EntryIterator() {
+ reset();
+ }
+
+ public void reset() {
+ current = null;
+ // Find first bucket.
+ final Entry[] table = FastIntMap.this.table;
+ int i;
+ for ( i = table.length - 1; i >= 0; i-- )
+ if ( table[i] != null ) break;
+ nextIndex = i;
+ }
+
+ public boolean hasNext() {
+ if ( nextIndex >= 0 ) return true;
+ Entry e = current;
+ return e != null && e.next != null;
+ }
+
+ public Entry next() {
+ // Next entry in current bucket.
+ Entry e = current;
+ if ( e != null ) {
+ e = e.next;
+ if ( e != null ) {
+ current = e;
+ return e;
+ }
+ }
+ // Use the bucket at nextIndex and find the next nextIndex.
+ final Entry[] table = FastIntMap.this.table;
+ int i = nextIndex;
+ e = current = table[i];
+ while ( --i >= 0 )
+ if ( table[i] != null ) break;
+ nextIndex = i;
+ return e;
+ }
+
+ public void remove() {
+ FastIntMap.this.remove(current.key);
+ }
+ }
+
+ static final class Entry {
+
+ final int key;
+ T value;
+ Entry next;
+
+ Entry(int key, T value, Entry next) {
+ this.key = key;
+ this.value = value;
+ this.next = next;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/GLChecks.java b/src/java/org/lwjgl/opengles/GLChecks.java
new file mode 100644
index 0000000..3971615
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/GLChecks.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.opengl.OpenGLException;
+
+import java.nio.Buffer;
+
+import static org.lwjgl.opengles.GLES20.*;
+
+/**
+ * A class to check buffer boundaries in GL methods. Many GL
+ * methods read data from the GL into a native Buffer at its current position. If there is unsufficient space in the buffer when
+ * the call is made then a buffer overflow would otherwise occur and cause unexpected behaviour, a crash, or worse, a security
+ * risk. Therefore in those methods where GL reads data back into a buffer, we will call a bounds check method from this class
+ * to ensure that there is sufficient space in the buffer.
+ *
+ * Thrown by the debug build library of the LWJGL if any OpenGL operation causes an error.
+ *
+ * @author cix_foo
+ * @version $Revision: 3459 $
+ * $Id: GLChecks.java 3459 2010-11-29 17:21:05Z spasi $
+ */
+class GLChecks {
+
+ /** Static methods only! */
+ private GLChecks() {
+ }
+
+ /** Helper method to ensure that array buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensureArrayVBOdisabled() {
+ if ( LWJGLUtil.CHECKS && StateTracker.getTracker().arrayBuffer != 0 )
+ throw new OpenGLException("Cannot use Buffers when Array Buffer Object is enabled");
+ }
+
+ /** Helper method to ensure that array buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensureArrayVBOenabled() {
+ if ( LWJGLUtil.CHECKS && StateTracker.getTracker().arrayBuffer == 0 )
+ throw new OpenGLException("Cannot use offsets when Array Buffer Object is disabled");
+ }
+
+ /** Helper method to ensure that element array buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensureElementVBOdisabled() {
+ if ( LWJGLUtil.CHECKS && StateTracker.getTracker().elementArrayBuffer != 0 )
+ throw new OpenGLException("Cannot use Buffers when Element Array Buffer Object is enabled");
+ }
+
+ /** Helper method to ensure that element array buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensureElementVBOenabled() {
+ if ( LWJGLUtil.CHECKS && StateTracker.getTracker().elementArrayBuffer == 0 )
+ throw new OpenGLException("Cannot use offsets when Element Array Buffer Object is disabled");
+ }
+
+ /** Helper method to ensure that pixel pack buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensurePackPBOdisabled() {
+ if ( LWJGLUtil.CHECKS && StateTracker.getTracker().pixelPackBuffer != 0 )
+ throw new OpenGLException("Cannot use Buffers when Pixel Pack Buffer Object is enabled");
+ }
+
+ /** Helper method to ensure that pixel pack buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensurePackPBOenabled() {
+ if ( LWJGLUtil.CHECKS && StateTracker.getTracker().pixelPackBuffer == 0 )
+ throw new OpenGLException("Cannot use offsets when Pixel Pack Buffer Object is disabled");
+ }
+
+ /** Helper method to ensure that pixel unpack buffer objects are disabled. If they are enabled, we'll throw an OpenGLException */
+ static void ensureUnpackPBOdisabled() {
+ if ( LWJGLUtil.CHECKS && StateTracker.getTracker().pixelUnpackBuffer != 0 )
+ throw new OpenGLException("Cannot use Buffers when Pixel Unpack Buffer Object is enabled");
+ }
+
+ /** Helper method to ensure that pixel unpack buffer objects are enabled. If they are disabled, we'll throw an OpenGLException */
+ static void ensureUnpackPBOenabled() {
+ if ( LWJGLUtil.CHECKS && StateTracker.getTracker().pixelUnpackBuffer == 0 )
+ throw new OpenGLException("Cannot use offsets when Pixel Unpack Buffer Object is disabled");
+ }
+
+ /**
+ * Calculate the storage required for an image in elements
+ *
+ * @param format The format of the image (example: GL_RGBA)
+ * @param type The type of the image elements (example: GL_UNSIGNED_BYTE)
+ * @param width The width of the image
+ * @param height The height of the image (1 for 1D images)
+ * @param depth The depth of the image (1 for 2D images)
+ *
+ * @return the size, in elements, of the image
+ */
+ static int calculateImageStorage(Buffer buffer, int format, int type, int width, int height, int depth) {
+ return LWJGLUtil.CHECKS ? calculateImageStorage(format, type, width, height, depth) >> BufferUtils.getElementSizeExponent(buffer) : 0;
+ }
+
+ static int calculateTexImage1DStorage(Buffer buffer, int format, int type, int width) {
+ return LWJGLUtil.CHECKS ? calculateTexImage1DStorage(format, type, width) >> BufferUtils.getElementSizeExponent(buffer) : 0;
+ }
+
+ static int calculateTexImage2DStorage(Buffer buffer, int format, int type, int width, int height) {
+ return LWJGLUtil.CHECKS ? calculateTexImage2DStorage(format, type, width, height) >> BufferUtils.getElementSizeExponent(buffer) : 0;
+ }
+
+ static int calculateTexImage3DStorage(Buffer buffer, int format, int type, int width, int height, int depth) {
+ return LWJGLUtil.CHECKS ? calculateTexImage3DStorage(format, type, width, height, depth) >> BufferUtils.getElementSizeExponent(buffer) : 0;
+ }
+
+ /**
+ * Calculate the storage required for an image in bytes.
+ *
+ * @param format The format of the image (example: GL_RGBA)
+ * @param type The type of the image elements (example: GL_UNSIGNED_BYTE)
+ * @param width The width of the image
+ * @param height The height of the image (1 for 1D images)
+ * @param depth The depth of the image (1 for 2D images)
+ *
+ * @return the size, in bytes, of the image
+ */
+ private static int calculateImageStorage(int format, int type, int width, int height, int depth) {
+ return calculateBytesPerPixel(format, type) * width * height * depth;
+ }
+
+ private static int calculateTexImage1DStorage(int format, int type, int width) {
+ return calculateBytesPerPixel(format, type) * width;
+ }
+
+ private static int calculateTexImage2DStorage(int format, int type, int width, int height) {
+ return calculateTexImage1DStorage(format, type, width) * height;
+ }
+
+ private static int calculateTexImage3DStorage(int format, int type, int width, int height, int depth) {
+ return calculateTexImage2DStorage(format, type, width, height) * depth;
+ }
+
+ private static int calculateBytesPerPixel(int format, int type) {
+ int bpe;
+ switch ( type ) {
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ bpe = 1;
+ break;
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ bpe = 2;
+ break;
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ case GL_FLOAT:
+ bpe = 4;
+ break;
+ default:
+ // TODO: Add more types (like the GL12 types GL_UNSIGNED_INT_8_8_8_8
+ return 0;
+ // throw new IllegalArgumentException("Unknown type " + type);
+ }
+ int epp;
+ switch ( format ) {
+ case GL_LUMINANCE:
+ case GL_ALPHA:
+ epp = 1;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ epp = 2;
+ break;
+ case GL_RGB:
+ epp = 3;
+ break;
+ case GL_RGBA:
+ epp = 4;
+ break;
+ default:
+ // TODO: Add more formats. Assuming 4 is too wasteful on buffer sizes where e.g. 1 is enough (like GL_DEPTH_COMPONENT)
+ return 0;
+ }
+
+ return bpe * epp;
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/org/lwjgl/opengles/GLContext.java b/src/java/org/lwjgl/opengles/GLContext.java
new file mode 100644
index 0000000..e8fd543
--- /dev/null
+++ b/src/java/org/lwjgl/opengles/GLContext.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2002-2011 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.opengles;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.LWJGLUtil;
+import org.lwjgl.Sys;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.WeakHashMap;
+
+import static org.lwjgl.opengles.GLES20.*;
+
+/**
+ *
+ * Manages GL contexts. Before any rendering is done by a LWJGL system, a call should be made to GLContext.useContext() with a
+ * context. This will ensure that GLContext has an accurate reflection of the current context's capabilities and function
+ * pointers.
+ *
+ * This class is thread-safe in the sense that multiple threads can safely call all public methods. The class is also
+ * thread-aware in the sense that it tracks a per-thread current context (including capabilities and function pointers).
+ * That way, multiple threads can have multiple contexts current and render to them concurrently.
+ *
+ * @author elias_naur
+ * @version $Revision: 3279 $
+ * $Id: GLContext.java 3279 2010-03-11 21:06:49Z spasi $
+ */
+public final class GLContext {
+
+ /** Maps threads to their current context's ContextCapabilities, if any */
+ private static final ThreadLocal current_capabilities = new ThreadLocal