diff --git a/src/java/org/lwjgl/BufferChecks.java b/src/java/org/lwjgl/BufferChecks.java
index 392ac862..ed909e35 100644
--- a/src/java/org/lwjgl/BufferChecks.java
+++ b/src/java/org/lwjgl/BufferChecks.java
@@ -43,6 +43,8 @@ import java.nio.LongBuffer;
*
A class to check buffer boundaries in general. 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.
+ *
+ * Internal class, don't use.
*
* @author cix_foo
* @author elias_naur
@@ -177,7 +179,7 @@ public class BufferChecks {
* The minimum buffer size
* @throws IllegalArgumentException
*/
- private static void checkBufferSize(Buffer buf, int size) {
+ public static void checkBufferSize(Buffer buf, int size) {
if (buf.remaining() < size) {
throwBufferSizeException(buf, size);
}
diff --git a/src/java/org/lwjgl/NondirectBufferWrapper.java b/src/java/org/lwjgl/NondirectBufferWrapper.java
new file mode 100644
index 00000000..b7ddce55
--- /dev/null
+++ b/src/java/org/lwjgl/NondirectBufferWrapper.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2002-2004 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl;
+
+import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
+import java.nio.IntBuffer;
+import java.nio.FloatBuffer;
+import java.nio.LongBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Utility class to cache thread local direct buffers so when we are passed a non-direct buffer,
+ * we can put its contents into a cached direct buffer and use that at the native side instead.
+ *
+ * Internal class, don't use.
+ * @author elias_naur
+ * @version $Revision: 2762 $
+ * $Id: BufferChecks.java 2762 2007-04-11 16:13:05Z elias_naur $
+ */
+public final class NondirectBufferWrapper {
+ private final static int INITIAL_BUFFER_SIZE = 1;
+
+ private final static ThreadLocal thread_buffer = new ThreadLocal() {
+ protected final Object initialValue() {
+ return new CachedBuffers(INITIAL_BUFFER_SIZE);
+ }
+ };
+
+ private static CachedBuffers getCachedBuffers(int minimum_byte_size) {
+ CachedBuffers buffers = (CachedBuffers)thread_buffer.get();
+ int current_byte_size = buffers.byte_buffer.capacity();
+ if (minimum_byte_size > current_byte_size) {
+ buffers = new CachedBuffers(minimum_byte_size);
+ thread_buffer.set(buffers);
+ }
+ return buffers;
+ }
+
+ public static ByteBuffer wrapBufferOrNull(ByteBuffer buf, int size) {
+ if (buf != null)
+ return wrapBuffer(buf, size);
+ return buf;
+ }
+
+ public static ShortBuffer wrapBufferOrNull(ShortBuffer buf, int size) {
+ if (buf != null)
+ return wrapBuffer(buf, size);
+ return buf;
+ }
+
+ public static IntBuffer wrapBufferOrNull(IntBuffer buf, int size) {
+ if (buf != null)
+ return wrapBuffer(buf, size);
+ return buf;
+ }
+
+ public static LongBuffer wrapBufferOrNull(LongBuffer buf, int size) {
+ if (buf != null)
+ return wrapBuffer(buf, size);
+ return buf;
+ }
+
+ public static FloatBuffer wrapBufferOrNull(FloatBuffer buf, int size) {
+ if (buf != null)
+ return wrapBuffer(buf, size);
+ return buf;
+ }
+
+ public static DoubleBuffer wrapBufferOrNull(DoubleBuffer buf, int size) {
+ if (buf != null)
+ return wrapBuffer(buf, size);
+ return buf;
+ }
+
+ public static ByteBuffer wrapBuffer(ByteBuffer buf, int size) {
+ BufferChecks.checkBufferSize(buf, size);
+ return wrapDirect(buf);
+ }
+
+ public static ShortBuffer wrapBuffer(ShortBuffer buf, int size) {
+ BufferChecks.checkBufferSize(buf, size);
+ return wrapDirect(buf);
+ }
+
+ public static IntBuffer wrapBuffer(IntBuffer buf, int size) {
+ BufferChecks.checkBufferSize(buf, size);
+ return wrapDirect(buf);
+ }
+
+ public static LongBuffer wrapBuffer(LongBuffer buf, int size) {
+ BufferChecks.checkBufferSize(buf, size);
+ return wrapDirect(buf);
+ }
+
+ public static FloatBuffer wrapBuffer(FloatBuffer buf, int size) {
+ BufferChecks.checkBufferSize(buf, size);
+ return wrapDirect(buf);
+ }
+
+ public static DoubleBuffer wrapBuffer(DoubleBuffer buf, int size) {
+ BufferChecks.checkBufferSize(buf, size);
+ return wrapDirect(buf);
+ }
+
+ public static ByteBuffer wrapDirectOrNull(ByteBuffer buffer) {
+ if (buffer != null)
+ return wrapDirect(buffer);
+ return buffer;
+ }
+
+ public static ShortBuffer wrapDirectOrNull(ShortBuffer buffer) {
+ if (buffer != null)
+ return wrapDirect(buffer);
+ return buffer;
+ }
+
+ public static FloatBuffer wrapDirectOrNull(FloatBuffer buffer) {
+ if (buffer != null)
+ return wrapDirect(buffer);
+ return buffer;
+ }
+
+ public static IntBuffer wrapDirectOrNull(IntBuffer buffer) {
+ if (buffer != null)
+ return wrapDirect(buffer);
+ return buffer;
+ }
+
+ public static LongBuffer wrapDirectOrNull(LongBuffer buffer) {
+ if (buffer != null)
+ return wrapDirect(buffer);
+ return buffer;
+ }
+
+ public static DoubleBuffer wrapDirectOrNull(DoubleBuffer buffer) {
+ if (buffer != null)
+ return wrapDirect(buffer);
+ return buffer;
+ }
+
+ public static ByteBuffer wrapDirect(ByteBuffer buffer) {
+ if (!buffer.isDirect())
+ return doWrap(buffer);
+ return buffer;
+ }
+
+ public static ShortBuffer wrapDirect(ShortBuffer buffer) {
+ if (!buffer.isDirect())
+ return doWrap(buffer);
+ return buffer;
+ }
+
+ public static FloatBuffer wrapDirect(FloatBuffer buffer) {
+ if (!buffer.isDirect())
+ return doWrap(buffer);
+ return buffer;
+ }
+
+ public static IntBuffer wrapDirect(IntBuffer buffer) {
+ if (!buffer.isDirect())
+ return doWrap(buffer);
+ return buffer;
+ }
+
+ public static LongBuffer wrapDirect(LongBuffer buffer) {
+ if (!buffer.isDirect())
+ return doWrap(buffer);
+ return buffer;
+ }
+
+ public static DoubleBuffer wrapDirect(DoubleBuffer buffer) {
+ if (!buffer.isDirect())
+ return doWrap(buffer);
+ return buffer;
+ }
+
+ private static ByteBuffer doWrap(ByteBuffer buffer) {
+ ByteBuffer direct_buffer = getCachedBuffers(buffer.remaining()).byte_buffer;
+ direct_buffer.clear();
+ int saved_position = buffer.position();
+ direct_buffer.put(buffer);
+ buffer.position(saved_position);
+ direct_buffer.flip();
+ return direct_buffer;
+ }
+
+ private static ShortBuffer doWrap(ShortBuffer buffer) {
+ CachedBuffers buffers = getCachedBuffers(buffer.remaining()*2);
+ ShortBuffer direct_buffer = buffer.order() == ByteOrder.LITTLE_ENDIAN ? buffers.short_buffer_little : buffers.short_buffer_big;
+ direct_buffer.clear();
+ int saved_position = buffer.position();
+ direct_buffer.put(buffer);
+ buffer.position(saved_position);
+ direct_buffer.flip();
+ return direct_buffer;
+ }
+
+ private static FloatBuffer doWrap(FloatBuffer buffer) {
+ CachedBuffers buffers = getCachedBuffers(buffer.remaining()*4);
+ FloatBuffer direct_buffer = buffer.order() == ByteOrder.LITTLE_ENDIAN ? buffers.float_buffer_little : buffers.float_buffer_big;
+ direct_buffer.clear();
+ int saved_position = buffer.position();
+ direct_buffer.put(buffer);
+ buffer.position(saved_position);
+ direct_buffer.flip();
+ return direct_buffer;
+ }
+
+ private static IntBuffer doWrap(IntBuffer buffer) {
+ CachedBuffers buffers = getCachedBuffers(buffer.remaining()*4);
+ IntBuffer direct_buffer = buffer.order() == ByteOrder.LITTLE_ENDIAN ? buffers.int_buffer_little : buffers.int_buffer_big;
+ direct_buffer.clear();
+ int saved_position = buffer.position();
+ direct_buffer.put(buffer);
+ buffer.position(saved_position);
+ direct_buffer.flip();
+ return direct_buffer;
+ }
+
+ private static LongBuffer doWrap(LongBuffer buffer) {
+ CachedBuffers buffers = getCachedBuffers(buffer.remaining()*8);
+ LongBuffer direct_buffer = buffer.order() == ByteOrder.LITTLE_ENDIAN ? buffers.long_buffer_little : buffers.long_buffer_big;
+ direct_buffer.clear();
+ int saved_position = buffer.position();
+ direct_buffer.put(buffer);
+ buffer.position(saved_position);
+ direct_buffer.flip();
+ return direct_buffer;
+ }
+
+ private static DoubleBuffer doWrap(DoubleBuffer buffer) {
+ CachedBuffers buffers = getCachedBuffers(buffer.remaining()*8);
+ DoubleBuffer direct_buffer = buffer.order() == ByteOrder.LITTLE_ENDIAN ? buffers.double_buffer_little : buffers.double_buffer_big;
+ direct_buffer.clear();
+ int saved_position = buffer.position();
+ direct_buffer.put(buffer);
+ buffer.position(saved_position);
+ direct_buffer.flip();
+ return direct_buffer;
+ }
+
+ private final static class CachedBuffers {
+ private final ByteBuffer byte_buffer;
+ private final ShortBuffer short_buffer_big;
+ private final IntBuffer int_buffer_big;
+ private final FloatBuffer float_buffer_big;
+ private final LongBuffer long_buffer_big;
+ private final DoubleBuffer double_buffer_big;
+ private final ShortBuffer short_buffer_little;
+ private final IntBuffer int_buffer_little;
+ private final FloatBuffer float_buffer_little;
+ private final LongBuffer long_buffer_little;
+ private final DoubleBuffer double_buffer_little;
+
+ private CachedBuffers(int size) {
+ this.byte_buffer = ByteBuffer.allocateDirect(size);
+ this.short_buffer_big = byte_buffer.asShortBuffer();
+ this.int_buffer_big = byte_buffer.asIntBuffer();
+ this.float_buffer_big = byte_buffer.asFloatBuffer();
+ this.long_buffer_big = byte_buffer.asLongBuffer();
+ this.double_buffer_big = byte_buffer.asDoubleBuffer();
+ this.byte_buffer.order(ByteOrder.LITTLE_ENDIAN);
+ this.short_buffer_little = byte_buffer.asShortBuffer();
+ this.int_buffer_little = byte_buffer.asIntBuffer();
+ this.float_buffer_little = byte_buffer.asFloatBuffer();
+ this.long_buffer_little = byte_buffer.asLongBuffer();
+ this.double_buffer_little = byte_buffer.asDoubleBuffer();
+ }
+ }
+}
diff --git a/src/java/org/lwjgl/test/opengl/Gears.java b/src/java/org/lwjgl/test/opengl/Gears.java
index b937e280..44a21f86 100644
--- a/src/java/org/lwjgl/test/opengl/Gears.java
+++ b/src/java/org/lwjgl/test/opengl/Gears.java
@@ -156,18 +156,14 @@ public class Gears {
Display.setLocation((Display.getDisplayMode().getWidth() - 300) / 2,
(Display.getDisplayMode().getHeight() - 300) / 2);
Display.setDisplayMode(new DisplayMode(300, 300));
- Display.setTitle("Gears");
+ Display.setTitle("Gears");
Display.create();
// setup ogl
- FloatBuffer pos = BufferUtils.createFloatBuffer(4).put(new float[] { 5.0f, 5.0f, 10.0f, 0.0f});
- FloatBuffer red = BufferUtils.createFloatBuffer(4).put(new float[] { 0.8f, 0.1f, 0.0f, 1.0f});
- FloatBuffer green = BufferUtils.createFloatBuffer(4).put(new float[] { 0.0f, 0.8f, 0.2f, 1.0f});
- FloatBuffer blue = BufferUtils.createFloatBuffer(4).put(new float[] { 0.2f, 0.2f, 1.0f, 1.0f});
- pos.flip();
- red.flip();
- green.flip();
- blue.flip();
+ FloatBuffer pos = FloatBuffer.wrap(new float[] { 5.0f, 5.0f, 10.0f, 0.0f});
+ FloatBuffer red = FloatBuffer.wrap(new float[] { 0.8f, 0.1f, 0.0f, 1.0f});
+ FloatBuffer green = FloatBuffer.wrap(new float[] { 0.0f, 0.8f, 0.2f, 1.0f});
+ FloatBuffer blue = FloatBuffer.wrap(new float[] { 0.2f, 0.2f, 1.0f, 1.0f});
GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, pos);
GL11.glEnable(GL11.GL_CULL_FACE);
diff --git a/src/java/org/lwjgl/util/generator/GeneratorVisitor.java b/src/java/org/lwjgl/util/generator/GeneratorVisitor.java
index c1ee236e..b6d78248 100644
--- a/src/java/org/lwjgl/util/generator/GeneratorVisitor.java
+++ b/src/java/org/lwjgl/util/generator/GeneratorVisitor.java
@@ -171,6 +171,7 @@ public class GeneratorVisitor extends SimpleDeclarationVisitor {
java_writer.println();
java_writer.println("import org.lwjgl.LWJGLException;");
java_writer.println("import org.lwjgl.BufferChecks;");
+ java_writer.println("import org.lwjgl.NondirectBufferWrapper;");
java_writer.println("import java.nio.*;");
java_writer.println();
java_writer.print("public ");
diff --git a/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java b/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java
index d8ad946c..6ea699a7 100644
--- a/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java
+++ b/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java
@@ -425,7 +425,8 @@ public class JavaMethodsGenerator {
}
boolean null_terminated = param.getAnnotation(NullTerminated.class) != null;
if (Buffer.class.isAssignableFrom(java_type)) {
- printParameterCheck(writer, param.getSimpleName(), check_value, can_be_null, null_terminated);
+ boolean indirect_buffer_allowed = param.getAnnotation(CachedReference.class) == null;
+ printParameterCheck(writer, param.getSimpleName(), check_value, can_be_null, null_terminated, indirect_buffer_allowed);
} else if (String.class.equals(java_type)) {
if (!can_be_null)
writer.println("\t\tBufferChecks.checkNotNull(" + param.getSimpleName() + ");");
@@ -433,11 +434,14 @@ public class JavaMethodsGenerator {
}
}
if (method.getAnnotation(CachedResult.class) != null)
- printParameterCheck(writer, Utils.CACHED_BUFFER_NAME, null, true, false);
+ printParameterCheck(writer, Utils.CACHED_BUFFER_NAME, null, true, false, false);
}
- private static void printParameterCheck(PrintWriter writer, String name, String check_value, boolean can_be_null, boolean null_terminated) {
- writer.print("\t\tBufferChecks.check");
+ private static void printParameterCheck(PrintWriter writer, String name, String check_value, boolean can_be_null, boolean null_terminated, boolean indirect_buffer_allowed) {
+ if (indirect_buffer_allowed)
+ writer.print("\t\t" + name + " = NondirectBufferWrapper.wrap");
+ else
+ writer.print("\t\tBufferChecks.check");
if (check_value != null && !"".equals(check_value) ) {
writer.print("Buffer");
if (can_be_null)