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.
This commit is contained in:
Ioannis Tsakpinis 2010-01-04 18:47:49 +00:00
parent f970b8ba42
commit d97fc05a7b
13 changed files with 195 additions and 60 deletions

View File

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

View File

@ -43,4 +43,5 @@ import java.lang.annotation.ElementType;
@Target(ElementType.METHOD)
public @interface CachedResult {
boolean isRange() default false;
}

View File

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

View File

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

View File

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

View File

@ -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))

View File

@ -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) {

View File

@ -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:
* <p/>
* 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);
* <p/>
* Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused.
* <p/>
* 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.
* <p/>
* 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.<br>
* 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.

View File

@ -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:
* <p/>
* ByteBuffer mapped_buffer; mapped_buffer = glMapBufferRange(..., ..., ..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapBufferRange(..., ..., ..., ..., mapped_buffer);
* <p/>
* 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);

View File

@ -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:
* <p/>
* ByteBuffer mapped_buffer; mapped_buffer = glMapObjectBufferATI(..., null); ... // Another map on the same buffer mapped_buffer = glMapObjectBufferATI(..., mapped_buffer);
* <p/>
* Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused.
* <p/>
* 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.
* <p/>
* 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.<br>
* 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);

View File

@ -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:
* <p/>
* ByteBuffer mapped_buffer; mapped_buffer = glMapNamedBufferEXT(..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapNamedBufferEXT(..., ..., mapped_buffer);
* <p/>
* Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused.
* <p/>
* 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.
* <p/>
* 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.<br>
* 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:
* <p/>
* ByteBuffer mapped_buffer; mapped_buffer = glMapNamedBufferRangeEXT(..., ..., ..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapNamedBufferRangeEXT(..., ..., ..., ..., mapped_buffer);
* <p/>
* 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);

View File

@ -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:
* <p/>
* 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);
* <p/>
* Only ByteBuffers returned from this method are to be passed as the old_buffer argument. User-created ByteBuffers cannot be reused.
* <p/>
* 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.
* <p/>
* 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.<br>
* 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.
*/

View File

@ -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:
* <p/>
* ByteBuffer mapped_buffer; mapped_buffer = glMapBufferRange(..., ..., ..., ..., null); ... // Another map on the same buffer mapped_buffer = glMapBufferRange(..., ..., ..., ..., mapped_buffer);
* <p/>
* 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);