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)