From d97fc05a7b7c63852dd5518bfa8c7506882da967 Mon Sep 17 00:00:00 2001 From: Ioannis Tsakpinis Date: Mon, 4 Jan 2010 18:47:49 +0000 Subject: [PATCH] Added support for explicit length arguments in functions that map buffer objects. Simplified CachedResult handling of functions that map buffer object ranges. Improved documentation of CachedResult functions. --- src/java/org/lwjgl/opengl/GLChecks.java | 6 +++ .../lwjgl/util/generator/CachedResult.java | 1 + .../util/generator/GeneratorVisitor.java | 8 ++- .../util/generator/JavaMethodsGenerator.java | 50 +++++++++++++------ src/java/org/lwjgl/util/generator/Mode.java | 27 +++++----- .../generator/NativeMethodStubsGenerator.java | 11 ++-- src/java/org/lwjgl/util/generator/Utils.java | 5 +- .../org/lwjgl/opengl/ARB_buffer_object.java | 21 ++++++-- .../lwjgl/opengl/ARB_map_buffer_range.java | 16 +++++- .../lwjgl/opengl/ATI_map_object_buffer.java | 28 ++++++++--- .../lwjgl/opengl/EXT_direct_state_access.java | 39 ++++++++++++++- src/templates/org/lwjgl/opengl/GL15.java | 27 ++++++---- src/templates/org/lwjgl/opengl/GL30.java | 16 +++++- 13 files changed, 195 insertions(+), 60 deletions(-) diff --git a/src/java/org/lwjgl/opengl/GLChecks.java b/src/java/org/lwjgl/opengl/GLChecks.java index 3e1f7817..3a912700 100644 --- a/src/java/org/lwjgl/opengl/GLChecks.java +++ b/src/java/org/lwjgl/opengl/GLChecks.java @@ -71,6 +71,12 @@ class GLChecks { return scratch_buffer.get(0); } + static int getBufferObjectSizeATI(ContextCapabilities caps, int buffer) { + IntBuffer scratch_buffer = caps.scratch_int_buffer; + ATIVertexArrayObject.glGetObjectBufferATI(buffer, ATIVertexArrayObject.GL_OBJECT_BUFFER_SIZE_ATI, scratch_buffer); + return scratch_buffer.get(0); + } + static int getNamedBufferObjectSize(ContextCapabilities caps, int buffer) { IntBuffer scratch_buffer = caps.scratch_int_buffer; EXTDirectStateAccess.glGetNamedBufferParameterEXT(buffer, GL15.GL_BUFFER_SIZE, scratch_buffer); diff --git a/src/java/org/lwjgl/util/generator/CachedResult.java b/src/java/org/lwjgl/util/generator/CachedResult.java index e62487b3..fc0f1958 100644 --- a/src/java/org/lwjgl/util/generator/CachedResult.java +++ b/src/java/org/lwjgl/util/generator/CachedResult.java @@ -43,4 +43,5 @@ import java.lang.annotation.ElementType; @Target(ElementType.METHOD) public @interface CachedResult { + boolean isRange() default false; } diff --git a/src/java/org/lwjgl/util/generator/GeneratorVisitor.java b/src/java/org/lwjgl/util/generator/GeneratorVisitor.java index 8f4c0ab8..7372b370 100644 --- a/src/java/org/lwjgl/util/generator/GeneratorVisitor.java +++ b/src/java/org/lwjgl/util/generator/GeneratorVisitor.java @@ -91,8 +91,12 @@ public class GeneratorVisitor extends SimpleDeclarationVisitor { } if (Utils.getResultParameter(method) != null && !method.getReturnType().equals(env.getTypeUtils().getVoidType())) throw new RuntimeException(method + " return type is not void but a parameter is annotated with Result"); - if (method.getAnnotation(CachedResult.class) != null && Utils.getNIOBufferType(Utils.getMethodReturnType(method)) == null) - throw new RuntimeException(method + " return type is not a Buffer, but is annotated with CachedResult"); + if (method.getAnnotation(CachedResult.class) != null) { + if (Utils.getNIOBufferType(Utils.getMethodReturnType(method)) == null) + throw new RuntimeException(method + " return type is not a Buffer, but is annotated with CachedResult"); + if (method.getAnnotation(AutoResultSize.class) == null) + throw new RuntimeException(method + " is annotated with CachedResult but misses an AutoResultSize annotation"); + } validateTypes(method, method.getAnnotationMirrors(), method.getReturnType()); } diff --git a/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java b/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java index 649a1c0d..afc15e54 100644 --- a/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java +++ b/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java @@ -68,6 +68,9 @@ public class JavaMethodsGenerator { printMethodWithMultiType(env, type_map, writer, interface_decl, method, typeinfos_instance, Mode.NORMAL, generate_error_checks, context_specific); } } + if ( method.getAnnotation(CachedResult.class) != null && !method.getAnnotation(CachedResult.class).isRange() ) { + printMethodWithMultiType(env, type_map, writer, interface_decl, method, TypeInfo.getDefaultTypeInfoMap(method), Mode.CACHEDRESULT, generate_error_checks, context_specific); + } printJavaNativeStub(writer, method, Mode.NORMAL, generate_error_checks, context_specific); if (Utils.hasMethodBufferObjectParameter(method)) { printMethodWithMultiType(env, type_map, writer, interface_decl, method, TypeInfo.getDefaultTypeInfoMap(method), Mode.BUFFEROBJECT, generate_error_checks, context_specific); @@ -120,16 +123,23 @@ public class JavaMethodsGenerator { first_parameter = generateParameterJava(writer, param, type_info, native_stub, first_parameter, mode); } } + CachedResult cached_result_annotation = method.getAnnotation(CachedResult.class); TypeMirror result_type = Utils.getMethodReturnType(method); if ((native_stub && Utils.getNIOBufferType(result_type) != null) || Utils.needResultSize(method)) { - if (!first_parameter) - writer.print(", "); - first_parameter = false; - writer.print("long " + Utils.RESULT_SIZE_NAME); + if (cached_result_annotation == null || !cached_result_annotation.isRange()) { + if (!first_parameter) + writer.print(", "); + first_parameter = false; + writer.print("long " + Utils.RESULT_SIZE_NAME); + } } - if (method.getAnnotation(CachedResult.class) != null) { + if (cached_result_annotation != null) { if (!first_parameter) writer.print(", "); + + if ( mode == Mode.CACHEDRESULT ) + writer.print("long " + Utils.CACHED_BUFFER_LENGTH_NAME + ", "); + first_parameter = false; printResultType(writer, method, native_stub); writer.print(" " + Utils.CACHED_BUFFER_NAME); @@ -403,16 +413,26 @@ public class JavaMethodsGenerator { first_parameter = printMethodCallArgument(writer, method, param, typeinfos_instance, mode, first_parameter); } if (Utils.getNIOBufferType(Utils.getMethodReturnType(method)) != null) { - if (!first_parameter) - writer.print(", "); - first_parameter = false; - AutoResultSize auto_result_size_annotation = method.getAnnotation(AutoResultSize.class); - String result_size_expression; - if (auto_result_size_annotation == null) - result_size_expression = Utils.RESULT_SIZE_NAME; - else - result_size_expression = auto_result_size_annotation.value(); - Utils.printExtraCallArguments(writer, method, result_size_expression); + if (method.getAnnotation(CachedResult.class) != null && method.getAnnotation(CachedResult.class).isRange()) { + first_parameter = false; + Utils.printExtraCallArguments(writer, method, ""); + } else { + if (!first_parameter) + writer.print(", "); + first_parameter = false; + + String result_size_expression; + if ( mode == Mode.CACHEDRESULT ) + result_size_expression = Utils.CACHED_BUFFER_LENGTH_NAME; + else { + AutoResultSize auto_result_size_annotation = method.getAnnotation(AutoResultSize.class); + if (auto_result_size_annotation == null) + result_size_expression = Utils.RESULT_SIZE_NAME; + else + result_size_expression = auto_result_size_annotation.value(); + } + Utils.printExtraCallArguments(writer, method, result_size_expression); + } } return first_parameter; } diff --git a/src/java/org/lwjgl/util/generator/Mode.java b/src/java/org/lwjgl/util/generator/Mode.java index fbf5c4af..bffb07cb 100644 --- a/src/java/org/lwjgl/util/generator/Mode.java +++ b/src/java/org/lwjgl/util/generator/Mode.java @@ -1,31 +1,31 @@ -/* +/* * 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 + * modification, are permitted provided that the following conditions are * met: - * - * * Redistributions of source code must retain the above copyright + * + * * 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 + * * 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 + * 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 + * 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. */ @@ -34,5 +34,6 @@ package org.lwjgl.util.generator; public enum Mode { BUFFEROBJECT, AUTOS, + CACHEDRESULT, // Used for generating a CachedResult method with an explicit length argument. NORMAL } diff --git a/src/java/org/lwjgl/util/generator/NativeMethodStubsGenerator.java b/src/java/org/lwjgl/util/generator/NativeMethodStubsGenerator.java index 06948555..19104a45 100644 --- a/src/java/org/lwjgl/util/generator/NativeMethodStubsGenerator.java +++ b/src/java/org/lwjgl/util/generator/NativeMethodStubsGenerator.java @@ -106,8 +106,10 @@ public class NativeMethodStubsGenerator { writer.print("(JNIEnv *env, jclass clazz"); generateParameters(writer, method.getParameters(), mode); if (Utils.getNIOBufferType(result_type) != null) { - writer.print(", jlong " + Utils.RESULT_SIZE_NAME); - if (method.getAnnotation(CachedResult.class) != null) + CachedResult cached_result_annotation = method.getAnnotation(CachedResult.class); + if (cached_result_annotation == null || !cached_result_annotation.isRange()) + writer.print(", jlong " + Utils.RESULT_SIZE_NAME); + if (cached_result_annotation != null) writer.print(", jobject " + Utils.CACHED_BUFFER_NAME); } if (context_specific) { @@ -160,7 +162,10 @@ public class NativeMethodStubsGenerator { writer.print(Utils.RESULT_VAR_NAME); if (Buffer.class.isAssignableFrom(java_result_type)) { writer.print(", "); - Utils.printExtraCallArguments(writer, method, Utils.RESULT_SIZE_NAME); + if (method.getAnnotation(CachedResult.class) != null && method.getAnnotation(CachedResult.class).isRange()) + Utils.printExtraCallArguments(writer, method, method.getAnnotation(AutoResultSize.class).value()); + else + Utils.printExtraCallArguments(writer, method, Utils.RESULT_SIZE_NAME); } if (Buffer.class.isAssignableFrom(java_result_type) || String.class.equals(java_result_type)) diff --git a/src/java/org/lwjgl/util/generator/Utils.java b/src/java/org/lwjgl/util/generator/Utils.java index d3887754..268d1eaa 100644 --- a/src/java/org/lwjgl/util/generator/Utils.java +++ b/src/java/org/lwjgl/util/generator/Utils.java @@ -58,13 +58,14 @@ public class Utils { public static final String BUFFER_OBJECT_PARAMETER_POSTFIX = "_buffer_offset"; public static final String RESULT_SIZE_NAME = "result_size"; public static final String RESULT_VAR_NAME = "__result"; + public static final String CACHED_BUFFER_LENGTH_NAME = "length"; public static final String CACHED_BUFFER_NAME = "old_buffer"; private static final String OVERLOADED_METHOD_PREFIX = "n"; public static String getTypedefName(MethodDeclaration method) { return method.getSimpleName() + TYPEDEF_POSTFIX; } - + public static String getFunctionAddressName(InterfaceDeclaration interface_decl, MethodDeclaration method) { return interface_decl.getSimpleName() + "_" + method.getSimpleName() + FUNCTION_POINTER_POSTFIX; } @@ -201,7 +202,7 @@ public class Utils { public static boolean needResultSize(MethodDeclaration method) { return getNIOBufferType(getMethodReturnType(method)) != null && method.getAnnotation(AutoResultSize.class) == null; } - + public static void printExtraCallArguments(PrintWriter writer, MethodDeclaration method, String size_parameter_name) { writer.print(size_parameter_name); if (method.getAnnotation(CachedResult.class) != null) { diff --git a/src/templates/org/lwjgl/opengl/ARB_buffer_object.java b/src/templates/org/lwjgl/opengl/ARB_buffer_object.java index ff0625e8..2602c8b2 100644 --- a/src/templates/org/lwjgl/opengl/ARB_buffer_object.java +++ b/src/templates/org/lwjgl/opengl/ARB_buffer_object.java @@ -104,13 +104,24 @@ public interface ARB_buffer_object { @GLdouble Buffer data); /** - * glMapBufferARB maps a gl vertex buffer buffer to a ByteBuffer. The oldBuffer argument can be null, - * in which case a new ByteBuffer will be created, pointing to the returned memory. If oldBuffer is non-null, - * it will be returned if it points to the same mapped memory, otherwise a new ByteBuffer is created. That - * way, an application will normally use glMapBufferARB like this: + * glMapBufferARB maps a GL buffer object to a ByteBuffer. The old_buffer argument can be null, + * in which case a new ByteBuffer will be created, pointing to the returned memory. If old_buffer is non-null, + * it will be returned if it points to the same mapped memory and has the same capacity as the buffer object, + * otherwise a new ByteBuffer is created. That way, an application will normally use glMapBufferARB like this: *

- * ByteBuffer mapped_buffer; mapped_buffer = glMapBufferARB(..., ..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapBufferARB(..., ..., ..., mapped_buffer); + * ByteBuffer mapped_buffer; mapped_buffer = glMapBufferARB(..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapBufferARB(..., ..., mapped_buffer); + *

+ * Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused. + *

+ * The version of this method without an explicit length argument calls glGetBufferParameterARB internally to + * retrieve the current buffer object size, which may cause a pipeline flush and reduce application performance. + *

+ * The version of this method with an explicit length argument is a fast alternative to the one without. No GL call + * is made to retrieve the buffer object size, so the user is responsible for tracking and using the appropriate length.
+ * Security warning: The length argument should match the buffer object size. Reading from or writing to outside + * the memory region that corresponds to the mapped buffer object will cause native crashes. * + * @param length the length of the mapped memory in bytes. * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, it will be returned and no new buffer will be created. * * @return A ByteBuffer representing the mapped buffer memory. diff --git a/src/templates/org/lwjgl/opengl/ARB_map_buffer_range.java b/src/templates/org/lwjgl/opengl/ARB_map_buffer_range.java index eba5bd3b..f99b4bee 100644 --- a/src/templates/org/lwjgl/opengl/ARB_map_buffer_range.java +++ b/src/templates/org/lwjgl/opengl/ARB_map_buffer_range.java @@ -45,7 +45,21 @@ public interface ARB_map_buffer_range { int GL_MAP_FLUSH_EXPLICIT_BIT = 0x0010; int GL_MAP_UNSYNCHRONIZED_BIT = 0x0020; - @CachedResult + /** + * glMapBufferRange maps a GL buffer object range to a ByteBuffer. The old_buffer argument can be null, + * in which case a new ByteBuffer will be created, pointing to the returned memory. If old_buffer is non-null, + * it will be returned if it points to the same mapped memory and has the same capacity as the buffer object, + * otherwise a new ByteBuffer is created. That way, an application will normally use glMapBufferRange like this: + *

+ * ByteBuffer mapped_buffer; mapped_buffer = glMapBufferRange(..., ..., ..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapBufferRange(..., ..., ..., ..., mapped_buffer); + *

+ * Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused. + * + * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, it will be returned and no new buffer will be created. + * + * @return A ByteBuffer representing the mapped buffer memory. + */ + @CachedResult(isRange = true) @GLvoid @AutoResultSize("length") ByteBuffer glMapBufferRange(@GLenum int target, @GLintptr long offset, @GLsizeiptr long length, @GLbitfield int access); diff --git a/src/templates/org/lwjgl/opengl/ATI_map_object_buffer.java b/src/templates/org/lwjgl/opengl/ATI_map_object_buffer.java index 959a2229..c762c9d6 100644 --- a/src/templates/org/lwjgl/opengl/ATI_map_object_buffer.java +++ b/src/templates/org/lwjgl/opengl/ATI_map_object_buffer.java @@ -38,19 +38,31 @@ import java.nio.*; public interface ATI_map_object_buffer { /** - * glMapObjectBufferATI maps a gl object buffer to a ByteBuffer. The oldBuffer argument can be - * null, in which case a new ByteBuffer will be created, pointing to the returned memory. If - * oldBuffer is non-null, it will be returned if it points to the same mapped memory, otherwise a - * new ByteBuffer is created. + * glMapObjectBufferATI maps an ATI vertex array object to a ByteBuffer. The old_buffer argument can be null, + * in which case a new ByteBuffer will be created, pointing to the returned memory. If old_buffer is non-null, + * it will be returned if it points to the same mapped memory and has the same capacity as the vertex array object, + * otherwise a new ByteBuffer is created. That way, an application will normally use glMapObjectBufferATI like this: + *

+ * ByteBuffer mapped_buffer; mapped_buffer = glMapObjectBufferATI(..., null); ... // Another map on the same buffer mapped_buffer = glMapObjectBufferATI(..., mapped_buffer); + *

+ * Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused. + *

+ * The version of this method without an explicit length argument calls glGetObjectBufferATI internally to + * retrieve the current vertex array object size, which may cause a pipeline flush and reduce application performance. + *

+ * The version of this method with an explicit length argument is a fast alternative to the one without. No GL call + * is made to retrieve the vertex array object size, so the user is responsible for tracking and using the appropriate length.
+ * Security warning: The length argument should match the vertex array object size. Reading from or writing to outside + * the memory region that corresponds to the mapped vertex array object will cause native crashes. * - * @param result_size The size of the buffer area. - * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, - * it will be returned and no new buffer will be created. + * @param length the length of the mapped memory in bytes. + * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, it will be returned and no new buffer will be created. * - * @return A ByteBuffer representing the mapped object buffer memory. + * @return A ByteBuffer representing the mapped buffer memory. */ @CachedResult @GLvoid + @AutoResultSize("GLChecks.getBufferObjectSizeATI(caps, buffer)") ByteBuffer glMapObjectBufferATI(@GLuint int buffer); void glUnmapObjectBufferATI(@GLuint int buffer); diff --git a/src/templates/org/lwjgl/opengl/EXT_direct_state_access.java b/src/templates/org/lwjgl/opengl/EXT_direct_state_access.java index 2d8d5d01..8edd6a48 100644 --- a/src/templates/org/lwjgl/opengl/EXT_direct_state_access.java +++ b/src/templates/org/lwjgl/opengl/EXT_direct_state_access.java @@ -778,6 +778,29 @@ public interface EXT_direct_state_access { @GLfloat @GLdouble Buffer data); + /** + * glMapNamedBufferEXT maps a GL buffer object to a ByteBuffer. The old_buffer argument can be null, + * in which case a new ByteBuffer will be created, pointing to the returned memory. If old_buffer is non-null, + * it will be returned if it points to the same mapped memory and has the same capacity as the buffer object, + * otherwise a new ByteBuffer is created. That way, an application will normally use glMapNamedBufferEXT like this: + *

+ * ByteBuffer mapped_buffer; mapped_buffer = glMapNamedBufferEXT(..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapNamedBufferEXT(..., ..., mapped_buffer); + *

+ * Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused. + *

+ * The version of this method without an explicit length argument calls glGetNamedBufferParameterEXT internally to + * retrieve the current buffer object size, which may cause a pipeline flush and reduce application performance. + *

+ * The version of this method with an explicit length argument is a fast alternative to the one without. No GL call + * is made to retrieve the buffer object size, so the user is responsible for tracking and using the appropriate length.
+ * Security warning: The length argument should match the buffer object size. Reading from or writing to outside + * the memory region that corresponds to the mapped buffer object will cause native crashes. + * + * @param length the length of the mapped memory in bytes. + * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, it will be returned and no new buffer will be created. + * + * @return A ByteBuffer representing the mapped buffer memory. + */ @Dependent("OpenGL15") @CachedResult @GLvoid @@ -1283,8 +1306,22 @@ public interface EXT_direct_state_access { in name and replace "enum target" parameter with "uint buffer" */ + /** + * glMapNamedBufferRangeEXT maps a GL buffer object range to a ByteBuffer. The old_buffer argument can be null, + * in which case a new ByteBuffer will be created, pointing to the returned memory. If old_buffer is non-null, + * it will be returned if it points to the same mapped memory and has the same capacity as the buffer object, + * otherwise a new ByteBuffer is created. That way, an application will normally use glMapNamedBufferRangeEXT like this: + *

+ * ByteBuffer mapped_buffer; mapped_buffer = glMapNamedBufferRangeEXT(..., ..., ..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapNamedBufferRangeEXT(..., ..., ..., ..., mapped_buffer); + *

+ * Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused. + * + * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, it will be returned and no new buffer will be created. + * + * @return A ByteBuffer representing the mapped buffer memory. + */ @Dependent("OpenGL30") - @CachedResult + @CachedResult(isRange = true) @GLvoid @AutoResultSize("length") ByteBuffer glMapNamedBufferRangeEXT(@GLuint int buffer, @GLintptr long offset, @GLsizeiptr long length, @GLbitfield int access); diff --git a/src/templates/org/lwjgl/opengl/GL15.java b/src/templates/org/lwjgl/opengl/GL15.java index b01863be..6224c947 100644 --- a/src/templates/org/lwjgl/opengl/GL15.java +++ b/src/templates/org/lwjgl/opengl/GL15.java @@ -124,16 +124,25 @@ public interface GL15 { @GLdouble Buffer data); /** - * glMapBuffer maps a gl vertex buffer buffer to a ByteBuffer. The oldBuffer argument can be null, in which case a new - * ByteBuffer will be created, pointing to the returned memory. If oldBuffer is non-null, it will be returned if it points to - * the same mapped memory, otherwise a new ByteBuffer is created. That way, an application will normally use glMapBuffer like - * this: + * glMapBuffer maps a GL buffer object to a ByteBuffer. The old_buffer argument can be null, + * in which case a new ByteBuffer will be created, pointing to the returned memory. If old_buffer is non-null, + * it will be returned if it points to the same mapped memory and has the same capacity as the buffer object, + * otherwise a new ByteBuffer is created. That way, an application will normally use glMapBuffer like this: *

- * ByteBuffer mapped_buffer; mapped_buffer = glMapBuffer(..., ..., ..., null); ... // Another map on the same buffer - * mapped_buffer = glMapBuffer(..., ..., ..., mapped_buffer); - * - * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, it will be returned and no - * new buffer will be created. + * ByteBuffer mapped_buffer; mapped_buffer = glMapBuffer(..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapBuffer(..., ..., mapped_buffer); + *

+ * Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused. + *

+ * The version of this method without an explicit length argument calls glGetBufferParameter internally to + * retrieve the current buffer object size, which may cause a pipeline flush and reduce application performance. + *

+ * The version of this method with an explicit length argument is a fast alternative to the one without. No GL call + * is made to retrieve the buffer object size, so the user is responsible for tracking and using the appropriate length.
+ * Security warning: The length argument should match the buffer object size. Reading from or writing to outside + * the memory region that corresponds to the mapped buffer object will cause native crashes. + * + * @param length the length of the mapped memory in bytes. + * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, it will be returned and no new buffer will be created. * * @return A ByteBuffer representing the mapped buffer memory. */ diff --git a/src/templates/org/lwjgl/opengl/GL30.java b/src/templates/org/lwjgl/opengl/GL30.java index d148d97c..a3820cc8 100644 --- a/src/templates/org/lwjgl/opengl/GL30.java +++ b/src/templates/org/lwjgl/opengl/GL30.java @@ -240,7 +240,21 @@ public interface GL30 { int GL_MAP_FLUSH_EXPLICIT_BIT = 0x0010; int GL_MAP_UNSYNCHRONIZED_BIT = 0x0020; - @CachedResult + /** + * glMapBufferRange maps a GL buffer object range to a ByteBuffer. The old_buffer argument can be null, + * in which case a new ByteBuffer will be created, pointing to the returned memory. If old_buffer is non-null, + * it will be returned if it points to the same mapped memory and has the same capacity as the buffer object, + * otherwise a new ByteBuffer is created. That way, an application will normally use glMapBufferRange like this: + *

+ * ByteBuffer mapped_buffer; mapped_buffer = glMapBufferRange(..., ..., ..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapBufferRange(..., ..., ..., ..., mapped_buffer); + *

+ * Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused. + * + * @param old_buffer A ByteBuffer. If this argument points to the same address and has the same capacity as the new mapping, it will be returned and no new buffer will be created. + * + * @return A ByteBuffer representing the mapped buffer memory. + */ + @CachedResult(isRange = true) @GLvoid @AutoResultSize("length") ByteBuffer glMapBufferRange(@GLenum int target, @GLintptr long offset, @GLsizeiptr long length, @GLbitfield int access);