diff options
author | Kenneth Russel <[email protected]> | 2006-02-05 18:09:23 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2006-02-05 18:09:23 +0000 |
commit | 875652cab75b68ac30b9b1cc81ee62f7ff1e165d (patch) | |
tree | 7e6d85cee9453f6864d9067ac1c90213244ab4e0 | |
parent | 98da87017cb72785ca13f5b0657ce2c5d8a067c3 (diff) |
Intermediate checkin for FBO support in Java2D/JOGL bridge. Needed to
keep track of server-side OpenGL objects, like textures and display
lists, created by the end user to preserve the illusion of independent
contexts even though they will all share textures and display lists
with the Java2D OpenGL context in order to access its FBO. Added
GLObjectTracker class to track creation and destruction of these
objects and to support cleanup when the last referring context has
been destroyed. Modified GLContextShareSet to create and install
GLObjectTrackers when necessary and GLContext to ref and unref tracker
appropriately. Changed GlueGen's JavaPrologue and JavaEpilogue
directives (and their documentation) to perform argument name
substitution. Wrote documentation section on argument name
substitution and specified behavior for primitive arrays (converts to
string "array_name, array_name_offset" in substitution). Rephrased
GlueGen's RangeCheck directives in terms of JavaPrologue directives
and deleted old specialized code. Fixed bug in handling of VBO support
in GLConfiguration when JavaPrologue was present for affected
functions. Added JavaPrologue and JavaEpilogue directives to all
existing OpenGL routines creating server-side objects (though it's
possible some were missed) to call GLObjectTracker when necessary.
Added RangeCheck directives for these routines as well. Worked around
bug in JOGL demos where shutdownDemo() was being called more than once.
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/gluegen/trunk@13 a78bb65f-1512-4460-ba86-f6dc96a7bf27
-rwxr-xr-x | doc/manual/index.html | 102 | ||||
-rw-r--r-- | src/java/com/sun/gluegen/CMethodBindingEmitter.java | 25 | ||||
-rw-r--r-- | src/java/com/sun/gluegen/FunctionEmitter.java | 17 | ||||
-rw-r--r-- | src/java/com/sun/gluegen/JavaConfiguration.java | 57 | ||||
-rw-r--r-- | src/java/com/sun/gluegen/JavaEmitter.java | 6 | ||||
-rw-r--r-- | src/java/com/sun/gluegen/JavaMethodBindingEmitter.java | 60 | ||||
-rwxr-xr-x | src/java/com/sun/gluegen/opengl/GLConfiguration.java | 20 | ||||
-rw-r--r-- | src/java/com/sun/gluegen/runtime/BufferFactory.java | 39 |
8 files changed, 195 insertions, 131 deletions
diff --git a/doc/manual/index.html b/doc/manual/index.html index 2e4ed84..cbeea8e 100755 --- a/doc/manual/index.html +++ b/doc/manual/index.html @@ -1,3 +1,9 @@ +<HTML> +<HEAD> +<TITLE>GlueGen Manual</TITLE> +</HEAD> +<BODY> + <H1>GlueGen Manual</H1> <H2> Table of Contents </H2> @@ -23,6 +29,7 @@ Chapter 2 - Using GlueGen <LI> <a href = "#SecStub">Stub Headers</a> <LI> <a href = "#Sec32">32- and 64-bit Considerations</a> <LI> <a href = "#SecOpaque">Opaque Directives</a> +<LI> <a href = "#SecSubstitution">Argument Name Substitution</a> <LI> <a href = "#SecConfiguration">Configuration File Directives</a> <UL> <LI> <a href = "#SecJavaEmitter">JavaEmitter Configuration</a> @@ -755,6 +762,63 @@ type to a Java long: Now HANDLEs are exposed to Java as longs as desired. A similar technique is used to expose XIDs on the X11 platform as Java longs. +</P> + + +<H3><a name="SecSubstitution">Argument Name Substitution</a></H3> + +<P> + +Certain configuration file directives allow the insertion of Java or C +code at various places in the generated glue code, to both eliminate +the need to hand-edit the generated glue code as well as to minimize +the hand-writing of glue code, which sidesteps the GlueGen process. In +some situations the inserted code may reference incoming arguments to +compute some value or perform some operation. Examples of directives +supporting this substitution include <a +href="#ReturnValueCapacity">ReturnValueCapacity</a> and <a +href="#ReturnedArrayLength">ReturnedArrayLength</a>. + +</P> +<P> + +The expressions in these directives may contain Java MessageFormat +expressions like <code>{0}</code> which refer to the incoming argument +names to the function. <code>{0}</code> refers to the first incoming +argument. + +</P> +<P> + +Strongly-typed C primitive pointers such as <code>int*</code>, which +ordinarily expand to overloaded Java methods taking +e.g. <code>int[]</code> as well as <code>IntBuffer</code>, present a +problem. The expansion to <code>int[] arr</code> also generates an +<code>int arr_offset</code> argument to be able to pass a pointer into +the middle of the array down to C. To allow the same MessageFormat +expression to be used for both cases, the subsitution that occurs when +such a primitive array is referenced is the string <code>arr, +arr_offset</code>; in other words, the subtituted string contains a +comma. This construct may be used in the following way: the code being +manually inserted may itself contain a method call taking +e.g. <code>{3}</code> (the incoming argument index of the primitive +array or buffer). The user should supply two overloaded versions of +this method, one taking a strongly-typed Buffer and one taking e.g. an +<code>int[] arr</code> and <code>int arr_offset</code> argument. The +implementation of <code>RangeCheck</code>s for primitive arrays and +strongly-typed buffers uses this construct. + +</P> +<P> + +It should be noted that in the autogenerated C code the offset +argument is expressed in bytes while at the Java level it is expressed +in elements. Most uses of GlueGen will probably not have to refer to +the primitive array arguments in C code so this slight confusion +should be minor. + +</P> + <H3><a name="SecConfiguration">Configuration File Directives</a></H3> @@ -1047,10 +1111,11 @@ href="#ImplJavaClass">ImplJavaClass</a>. (optional) Adds the specified code as an epilogue in the Java method for the specified C function; this code is run after the underlying C function has been called via the native method but before any result -is returned. No transformations are currently performed on this code, -unlike in the <a href="#ReturnedArrayLength">ReturnedArrayLength</a> -and other directives. See also <a -href="#JavaPrologue">JavaPrologue</a>. +is returned. As in the <a +href="#ReturnedArrayLength">ReturnedArrayLength</a> and other +directives, <a href="#SecSubstitution">argument name +substitution</a> is performed on MessageFormat expressions in the +specified code. See also <a href="#JavaPrologue">JavaPrologue</a>. <dt><strong><a name="JavaOutputDir">JavaOutputDir</a></strong> @@ -1068,10 +1133,11 @@ defaults to the current working directory. (optional) Adds the specified code as a prologue in the Java method for the specified C function; this code is run before the underlying C -function is called via the native method. No transformations are -currently performed on this code, unlike in the <a +function is called via the native method. As in the <a href="#ReturnedArrayLength">ReturnedArrayLength</a> and other -directives. See also <a href="#JavaEpilogue">JavaEpilogue</a>. +directives, <a href="#SecSubstitution">argument name +substitution</a> is performed on MessageFormat expressions in the +specified code. See also <a href="#JavaEpilogue">JavaEpilogue</a>. <dt><strong><a name="ManuallyImplement">ManuallyImplement</a></strong> @@ -1160,9 +1226,8 @@ that should be expressed in terms of a number of bytes rather than a number of elements, see the <a href="#RangeCheckBytes">RangeCheckBytes</a> directive. As in the <a href="#ReturnedArrayLength">ReturnedArrayLength</a> and other -directives, MessageFormat expressions such as "{0}" are replaced with -the corresponding incoming argument name, where the first incoming -argument is index 0. +directives, <a href="#SecSubstitution">argument name substitution</a> +is performed on MessageFormat expressions. <dt><strong><a name="RangeCheckBytes">RangeCheckBytes</a></strong> @@ -1171,7 +1236,8 @@ argument is index 0. (optional) Same as the <a href="#RangeCheck">RangeCheck</a> directive, but the specified expression is treated as a minimum number of bytes -remaining rather than a minimum number of elements remaining. +remaining rather than a minimum number of elements remaining. This +directive may not be used with primitive arrays. <dt><strong><a name="RenameJavaMethod">RenameJavaMethod</a></strong> @@ -1203,7 +1269,8 @@ href="#ImplJavaClass">ImplJavaClass</a> directives. expression with MessageFormat specifiers such as "{0}". These specifiers will be replaced in the generated glue code with the incoming argument names where the first argument to the method is -numbered 0. <br> +numbered 0. See the section on <a href="#SecSubstitution"> argument +name substitution</a>.<br> (optional) For a function returning a compound C pointer type such as an <code>XVisualInfo*</code>, indicates that the returned pointer is @@ -1235,8 +1302,8 @@ subclass wrapping a C primitive pointer such as <code>char*</code> or <code>float*</code> being returned from a C function. Typically necessary in order to properly use such pointer return results from Java. As in the <a href="#ReturnedArrayLength">ReturnedArrayLength</a> -directive, argument name substitution is performed on MessageFormat -expressions such as "{0}" where the first argument is index 0. +directive, <a href="#SecSubstitution">argument name substitution</a> +is performed on MessageFormat expressions. <dt><strong><a name="ReturnValueLength">ReturnValueLength</a></strong> @@ -1253,8 +1320,8 @@ directive handles boxing of individual elements of the array (which are pointers) in to the Java class which wraps that C struct type. See the (FIXME) examples for a concrete example of usage. As in the <a href="#ReturnedArrayLength">ReturnedArrayLength</a> directive, -argument name substitution is performed on MessageFormat expressions -such as "{0}" where the first argument is index 0. +<a href="#SecSubstitution">argument name substitution</a> is performed +on MessageFormat expressions. <dt><strong><a name="RuntimeExceptionType">RuntimeExceptionType</a></strong> @@ -1538,3 +1605,6 @@ despite the fact that it has an associated function pointer typedef in the header. </dl> + +</BODY> +</HTML> diff --git a/src/java/com/sun/gluegen/CMethodBindingEmitter.java b/src/java/com/sun/gluegen/CMethodBindingEmitter.java index 9222588..1ffd362 100644 --- a/src/java/com/sun/gluegen/CMethodBindingEmitter.java +++ b/src/java/com/sun/gluegen/CMethodBindingEmitter.java @@ -988,13 +988,8 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.print(" return (*env)->NewDirectByteBuffer(env, _res, "); // See whether capacity has been specified if (returnValueCapacityExpression != null) { - String[] argumentNames = new String[binding.getNumArguments()]; - for (int i = 0; i < binding.getNumArguments(); i++) - { - argumentNames[i] = binding.getArgumentName(i); - } writer.print( - returnValueCapacityExpression.format(argumentNames)); + returnValueCapacityExpression.format(argumentNameArray())); } else { if (cReturnType.isPointer() && cReturnType.asPointer().getTargetType().isCompound()) { @@ -1025,11 +1020,7 @@ public class CMethodBindingEmitter extends FunctionEmitter throw new RuntimeException("Error while generating C code: no length specified for array returned from function " + binding); } - String[] argumentNames = new String[binding.getNumArguments()]; - for (int i = 0; i < binding.getNumArguments(); i++) { - argumentNames[i] = binding.getArgumentName(i); - } - writer.println(" " + arrayResLength + " = " + returnValueLengthExpression.format(argumentNames) + ";"); + writer.println(" " + arrayResLength + " = " + returnValueLengthExpression.format(argumentNameArray()) + ";"); writer.println(" " + arrayRes + " = (*env)->NewObjectArray(env, " + arrayResLength + ", (*env)->FindClass(env, \"java/nio/ByteBuffer\"), NULL);"); writer.println(" for (" + arrayIdx + " = 0; " + arrayIdx + " < " + arrayResLength + "; " + arrayIdx + "++) {"); Type retType = binding.getCSymbol().getReturnType(); @@ -1408,6 +1399,18 @@ public class CMethodBindingEmitter extends FunctionEmitter return binding.getArgumentName(i) + "_byte_offset_array"; } + protected String[] argumentNameArray() { + String[] argumentNames = new String[binding.getNumArguments()]; + for (int i = 0; i < binding.getNumArguments(); i++) { + argumentNames[i] = binding.getArgumentName(i); + if (binding.getJavaArgumentType(i).isPrimitiveArray()) { + // Add on _offset argument in comma-separated expression + argumentNames[i] = argumentNames[i] + ", " + byteOffsetArgName(i); + } + } + return argumentNames; + } + protected String pointerConversionArgumentName(int i) { return "_ptr" + i; } diff --git a/src/java/com/sun/gluegen/FunctionEmitter.java b/src/java/com/sun/gluegen/FunctionEmitter.java index 3fa6f03..0d0f225 100644 --- a/src/java/com/sun/gluegen/FunctionEmitter.java +++ b/src/java/com/sun/gluegen/FunctionEmitter.java @@ -47,7 +47,7 @@ public abstract class FunctionEmitter { public static final EmissionModifier STATIC = new EmissionModifier("static"); - private HashSet modifiers = new HashSet(4); + private ArrayList modifiers = new ArrayList(); private CommentEmitter commentEmitter = null; private PrintWriter defaultOutput; @@ -64,7 +64,7 @@ public abstract class FunctionEmitter * Makes this FunctionEmitter a copy of the passed one. */ public FunctionEmitter(FunctionEmitter arg) { - modifiers = (HashSet) arg.modifiers.clone(); + modifiers = (ArrayList) arg.modifiers.clone(); commentEmitter = arg.commentEmitter; defaultOutput = arg.defaultOutput; } @@ -203,6 +203,19 @@ public abstract class FunctionEmitter public final String toString() { return emittedForm; } private String emittedForm; + + public int hashCode() { + return emittedForm.hashCode(); + } + + public boolean equals(Object arg) { + if (arg == null || (!(arg instanceof EmissionModifier))) { + return false; + } + + return emittedForm.equals(((EmissionModifier) arg).emittedForm); + } + protected EmissionModifier(String emittedForm) { this.emittedForm = emittedForm; } } } diff --git a/src/java/com/sun/gluegen/JavaConfiguration.java b/src/java/com/sun/gluegen/JavaConfiguration.java index ae8c46e..b5f43d6 100644 --- a/src/java/com/sun/gluegen/JavaConfiguration.java +++ b/src/java/com/sun/gluegen/JavaConfiguration.java @@ -116,8 +116,6 @@ public class JavaConfiguration { private Map/*<String,String>*/ javaMethodRenames = new HashMap(); private Map/*<String,List<String>>*/ javaPrologues = new HashMap(); private Map/*<String,List<String>>*/ javaEpilogues = new HashMap(); - private Map/*<String,Map<Integer,String>>*/ rangeChecks = new HashMap(); - private Map/*<String,Map<Integer,String>>*/ byteRangeChecks = new HashMap(); /** Reads the configuration file. @param filename path to file that should be read @@ -571,22 +569,6 @@ public class JavaConfiguration { return res; } - /** Returns a map of Integer argument numbers to expressions to be - used to range check the given arguments to the given function. - Returns null if there were no range check expressions supplied - for this function. */ - public Map/*<Integer, String>*/ rangeCheckExpressions(String functionName) { - return (Map/*<Integer, String>*/) rangeChecks.get(functionName); - } - - /** Returns a map of Integer argument numbers to expressions to be - used to range check (in size of bytes) the given arguments to - the given function. Returns null if there were no range check - expressions supplied for this function. */ - public Map/*<Integer, String>*/ byteRangeCheckExpressions(String functionName) { - return (Map/*<Integer, String>*/) byteRangeChecks.get(functionName); - } - //---------------------------------------------------------------------- // Internals only below this point // @@ -1142,13 +1124,7 @@ public class JavaConfiguration { methodName = methodName + descriptor; } } - Map code = (prologue ? javaPrologues : javaEpilogues); - List/*<String>*/ data = (List/*<String>*/) code.get(methodName); - if (data == null) { - data = new ArrayList/*<String>*/(); - code.put(methodName, data); - } - data.add(restOfLine); + addJavaPrologueOrEpilogue(methodName, restOfLine, prologue); } catch (NoSuchElementException e) { throw new RuntimeException("Error parsing \"" + (prologue ? "JavaPrologue" : "JavaEpilogue") + @@ -1157,27 +1133,28 @@ public class JavaConfiguration { } } + protected void addJavaPrologueOrEpilogue(String methodName, String code, boolean prologue) { + Map codes = (prologue ? javaPrologues : javaEpilogues); + List/*<String>*/ data = (List/*<String>*/) codes.get(methodName); + if (data == null) { + data = new ArrayList/*<String>*/(); + codes.put(methodName, data); + } + data.add(code); + } + protected void readRangeCheck(StringTokenizer tok, String filename, int lineNo, boolean inBytes) { try { String functionName = tok.nextToken(); int argNum = Integer.parseInt(tok.nextToken()); String restOfLine = tok.nextToken("\n\r\f"); restOfLine = restOfLine.trim(); - Map/*<Integer, String>*/ checksForFunction = null; - if (inBytes) { - checksForFunction = (Map/*<Integer, String>*/) byteRangeChecks.get(functionName); - } else { - checksForFunction = (Map/*<Integer, String>*/) rangeChecks.get(functionName); - } - if (checksForFunction == null) { - checksForFunction = new HashMap/*<Integer, String>*/(); - if (inBytes) { - byteRangeChecks.put(functionName, checksForFunction); - } else { - rangeChecks.put(functionName, checksForFunction); - } - } - checksForFunction.put(new Integer(argNum), restOfLine); + // Construct a JavaPrologue for this + addJavaPrologueOrEpilogue(functionName, + "BufferFactory.rangeCheck" + + (inBytes ? "Bytes" : "") + + "({" + argNum + "}, " + restOfLine + ");", + true); } catch (Exception e) { throw new RuntimeException("Error parsing \"RangeCheck" + (inBytes ? "Bytes" : "") + "\" command at line " + lineNo + " in file \"" + filename + "\"", e); diff --git a/src/java/com/sun/gluegen/JavaEmitter.java b/src/java/com/sun/gluegen/JavaEmitter.java index f079906..d4bafb7 100644 --- a/src/java/com/sun/gluegen/JavaEmitter.java +++ b/src/java/com/sun/gluegen/JavaEmitter.java @@ -377,8 +377,6 @@ public class JavaEmitter implements GlueEmitter { emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName())); emitter.setPrologue(prologue); emitter.setEpilogue(epilogue); - emitter.setRangeCheckExpressions(cfg.rangeCheckExpressions(binding.getName())); - emitter.setByteRangeCheckExpressions(cfg.byteRangeCheckExpressions(binding.getName())); allEmitters.add(emitter); } @@ -432,8 +430,6 @@ public class JavaEmitter implements GlueEmitter { } emitter.addModifier(JavaMethodBindingEmitter.NATIVE); emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName())); - emitter.setRangeCheckExpressions(cfg.rangeCheckExpressions(binding.getName())); - emitter.setByteRangeCheckExpressions(cfg.byteRangeCheckExpressions(binding.getName())); allEmitters.add(emitter); // Optionally emit the entry point taking arrays which handles @@ -459,8 +455,6 @@ public class JavaEmitter implements GlueEmitter { } emitter.addModifier(JavaMethodBindingEmitter.NATIVE); emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName())); - emitter.setRangeCheckExpressions(cfg.rangeCheckExpressions(binding.getName())); - emitter.setByteRangeCheckExpressions(cfg.byteRangeCheckExpressions(binding.getName())); allEmitters.add(emitter); } } diff --git a/src/java/com/sun/gluegen/JavaMethodBindingEmitter.java b/src/java/com/sun/gluegen/JavaMethodBindingEmitter.java index 7e08977..0032b61 100644 --- a/src/java/com/sun/gluegen/JavaMethodBindingEmitter.java +++ b/src/java/com/sun/gluegen/JavaMethodBindingEmitter.java @@ -87,10 +87,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter // number of elements of the returned array. private String returnedArrayLengthExpression; - // Range-check expressions for various Buffer arguments - private Map/*<Integer, String>*/ rangeCheckExpressions; - private Map/*<Integer, String>*/ byteRangeCheckExpressions; - public JavaMethodBindingEmitter(MethodBinding binding, PrintWriter output, String runtimeExceptionType, @@ -133,8 +129,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter prologue = arg.prologue; epilogue = arg.epilogue; returnedArrayLengthExpression = arg.returnedArrayLengthExpression; - rangeCheckExpressions = arg.rangeCheckExpressions; - byteRangeCheckExpressions = arg.byteRangeCheckExpressions; } public final MethodBinding getBinding() { return binding; } @@ -199,14 +193,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter this.forImplementingMethodCall = impl; } - public void setRangeCheckExpressions(Map/*<Integer, String>*/ rangeChecks) { - this.rangeCheckExpressions = rangeChecks; - } - - public void setByteRangeCheckExpressions(Map/*<Integer, String>*/ rangeChecks) { - this.byteRangeCheckExpressions = rangeChecks; - } - protected void emitReturnType(PrintWriter writer) { writer.print(getReturnTypeString(false)); @@ -369,8 +355,10 @@ public class JavaMethodBindingEmitter extends FunctionEmitter protected void emitPrologueOrEpilogue(List/*<String>*/ code, PrintWriter writer) { if (code != null) { + String[] argumentNames = argumentNameArray(); for (Iterator iter = code.iterator(); iter.hasNext(); ) { - writer.println(" " + (String) iter.next()); + MessageFormat fmt = new MessageFormat((String) iter.next()); + writer.println(" " + fmt.format(argumentNames)); } } } @@ -438,44 +426,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter } } } - - emitManuallySpecifiedRangeChecks(rangeCheckExpressions, false, writer); - emitManuallySpecifiedRangeChecks(byteRangeCheckExpressions, true, writer); - } - - protected void emitManuallySpecifiedRangeChecks(Map/*<Integer, String>*/ rangeChecks, - boolean inBytes, - PrintWriter writer) { - if (rangeChecks == null) { - return; - } - - // Check lengths of arrays and buffers with user-specified checks - for (Iterator iter = rangeChecks.keySet().iterator(); iter.hasNext(); ) { - Integer argNumBox = (Integer) iter.next(); - int argNum = argNumBox.intValue(); - JavaType type = binding.getJavaArgumentType(argNum); - String argName = getArgumentName(argNum); - if (type.isPrimitiveArray()) { - String offsetArg = offsetArgName(argNum); - if (inBytes) { - throw new RuntimeException("Can not specify RangeCheckBytes for primitive array arguments (failed on function " + - binding.getName() + ", argument " + argName + ")"); - } - writer.println(" BufferFactory.rangeCheck(" + argName + ", " + offsetArg + ", " + - new MessageFormat((String) rangeChecks.get(argNumBox)).format(argumentNameArray()) + - ");"); - } else if (!type.isPrimitive()) { - // Assume it's a Buffer - writer.print(" BufferFactory.rangeCheck"); - if (inBytes) { - writer.print("Bytes"); - } - writer.println("(" + argName + ", " + - new MessageFormat((String) rangeChecks.get(argNumBox)).format(argumentNameArray()) + - ");"); - } - } } protected void emitCall(MethodBinding binding, PrintWriter writer, boolean direct) { @@ -700,6 +650,10 @@ public class JavaMethodBindingEmitter extends FunctionEmitter String[] argumentNames = new String[binding.getNumArguments()]; for (int i = 0; i < binding.getNumArguments(); i++) { argumentNames[i] = getArgumentName(i); + if (binding.getJavaArgumentType(i).isPrimitiveArray()) { + // Add on _offset argument in comma-separated expression + argumentNames[i] = argumentNames[i] + ", " + offsetArgName(i); + } } return argumentNames; } diff --git a/src/java/com/sun/gluegen/opengl/GLConfiguration.java b/src/java/com/sun/gluegen/opengl/GLConfiguration.java index a44f3fe..e331d16 100755 --- a/src/java/com/sun/gluegen/opengl/GLConfiguration.java +++ b/src/java/com/sun/gluegen/opengl/GLConfiguration.java @@ -125,9 +125,14 @@ public class GLConfiguration extends ProcAddressConfiguration { // Need to generate appropriate prologue based on both buffer // object kind and whether this variant of the MethodBinding // is the one accepting a "long" as argument - if (res == null) { - res = new ArrayList(); + // + // NOTE we MUST NOT mutate the array returned from the super + // call! + ArrayList res2 = new ArrayList(); + if (res != null) { + res2.addAll(res); } + res = res2; String prologue = "check"; @@ -152,6 +157,17 @@ public class GLConfiguration extends ProcAddressConfiguration { prologue = prologue + "();"; res.add(0, prologue); + + // Must also filter out bogus rangeCheck directives for VBO/PBO + // variants + if (emitter.isBufferObjectMethodBinding(binding)) { + for (Iterator iter = res.iterator(); iter.hasNext(); ) { + String line = (String) iter.next(); + if (line.indexOf("BufferFactory.rangeCheck") >= 0) { + iter.remove(); + } + } + } } return res; diff --git a/src/java/com/sun/gluegen/runtime/BufferFactory.java b/src/java/com/sun/gluegen/runtime/BufferFactory.java index ce46d14..4f095f4 100644 --- a/src/java/com/sun/gluegen/runtime/BufferFactory.java +++ b/src/java/com/sun/gluegen/runtime/BufferFactory.java @@ -44,6 +44,7 @@ import java.nio.*; public class BufferFactory { public static final int SIZEOF_BYTE = 1; public static final int SIZEOF_SHORT = 2; + public static final int SIZEOF_CHAR = 2; public static final int SIZEOF_INT = 4; public static final int SIZEOF_FLOAT = 4; public static final int SIZEOF_LONG = 8; @@ -77,7 +78,7 @@ public class BufferFactory { } else if (buf instanceof LongBuffer) { return ((LongBuffer) buf).isDirect(); } - throw new RuntimeException("Unknown buffer type " + buf.getClass().getName()); + throw new RuntimeException("Unexpected buffer type " + buf.getClass().getName()); } @@ -101,6 +102,8 @@ public class BufferFactory { return (buf.position() * SIZEOF_DOUBLE); } else if (buf instanceof LongBuffer) { return (buf.position() * SIZEOF_LONG); + } else if (buf instanceof CharBuffer) { + return (buf.position() * SIZEOF_CHAR); } throw new RuntimeException("Disallowed array backing store type in buffer " @@ -127,6 +130,8 @@ public class BufferFactory { return ((DoubleBuffer) buf).array(); } else if (buf instanceof LongBuffer) { return ((LongBuffer) buf).array(); + } else if (buf instanceof CharBuffer) { + return ((CharBuffer) buf).array(); } throw new RuntimeException("Disallowed array backing store type in buffer " @@ -156,48 +161,78 @@ public class BufferFactory { return (SIZEOF_DOUBLE*(((DoubleBuffer)buf).arrayOffset() + pos)); } else if(buf instanceof LongBuffer) { return (SIZEOF_LONG*(((LongBuffer)buf).arrayOffset() + pos)); + } else if(buf instanceof CharBuffer) { + return (SIZEOF_CHAR*(((CharBuffer)buf).arrayOffset() + pos)); } throw new RuntimeException("Unknown buffer type " + buf.getClass().getName()); } public static void rangeCheck(byte[] array, int offset, int minElementsRemaining) { + if (array == null) { + return; + } + if (array.length < offset + minElementsRemaining) { throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset)); } } public static void rangeCheck(char[] array, int offset, int minElementsRemaining) { + if (array == null) { + return; + } + if (array.length < offset + minElementsRemaining) { throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset)); } } public static void rangeCheck(short[] array, int offset, int minElementsRemaining) { + if (array == null) { + return; + } + if (array.length < offset + minElementsRemaining) { throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset)); } } public static void rangeCheck(int[] array, int offset, int minElementsRemaining) { + if (array == null) { + return; + } + if (array.length < offset + minElementsRemaining) { throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset)); } } public static void rangeCheck(long[] array, int offset, int minElementsRemaining) { + if (array == null) { + return; + } + if (array.length < offset + minElementsRemaining) { throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset)); } } public static void rangeCheck(float[] array, int offset, int minElementsRemaining) { + if (array == null) { + return; + } + if (array.length < offset + minElementsRemaining) { throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset)); } } public static void rangeCheck(double[] array, int offset, int minElementsRemaining) { + if (array == null) { + return; + } + if (array.length < offset + minElementsRemaining) { throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset)); } @@ -232,6 +267,8 @@ public class BufferFactory { bytesRemaining = elementsRemaining * SIZEOF_DOUBLE; } else if (buffer instanceof LongBuffer) { bytesRemaining = elementsRemaining * SIZEOF_LONG; + } else if (buffer instanceof CharBuffer) { + bytesRemaining = elementsRemaining * SIZEOF_CHAR; } if (bytesRemaining < minBytesRemaining) { throw new IndexOutOfBoundsException("Required " + minBytesRemaining + " remaining bytes in buffer, only had " + bytesRemaining); |