summaryrefslogtreecommitdiffstats
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/java/games/gluegen/CMethodBindingEmitter.java841
-rw-r--r--src/net/java/games/gluegen/CMethodBindingImplEmitter.java127
-rw-r--r--src/net/java/games/gluegen/JavaConfiguration.java331
-rw-r--r--src/net/java/games/gluegen/JavaEmitter.java809
-rw-r--r--src/net/java/games/gluegen/JavaMethodBindingEmitter.java511
-rw-r--r--src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java482
-rw-r--r--src/net/java/games/gluegen/JavaType.java65
-rw-r--r--src/net/java/games/gluegen/MethodBinding.java204
-rw-r--r--src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java139
-rw-r--r--src/net/java/games/gluegen/opengl/GLEmitter.java55
-rw-r--r--src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java130
-rw-r--r--src/net/java/games/gluegen/runtime/BufferFactory.java77
-rw-r--r--src/net/java/games/jogl/Animator.java19
-rw-r--r--src/net/java/games/jogl/GLJPanel.java20
-rwxr-xr-xsrc/net/java/games/jogl/impl/Project.java31
-rw-r--r--src/net/java/games/jogl/impl/mipmap/Mipmap.java8
16 files changed, 1584 insertions, 2265 deletions
diff --git a/src/net/java/games/gluegen/CMethodBindingEmitter.java b/src/net/java/games/gluegen/CMethodBindingEmitter.java
index 2616f151b..4a7ad1c98 100644
--- a/src/net/java/games/gluegen/CMethodBindingEmitter.java
+++ b/src/net/java/games/gluegen/CMethodBindingEmitter.java
@@ -57,8 +57,6 @@ public class CMethodBindingEmitter extends FunctionEmitter
protected MethodBinding binding;
- protected boolean indirectBufferInterface = false;
-
/** Name of the package in which the corresponding Java method resides.*/
private String packageName;
@@ -77,6 +75,10 @@ public class CMethodBindingEmitter extends FunctionEmitter
*/
private boolean isJavaMethodStatic;
+ // Flags which change various aspects of glue code generation
+ protected boolean forImplementingMethodCall;
+ protected boolean forIndirectBufferAndArrayImplementation;
+
/**
* Optional List of Strings containing temporary C variables to declare.
*/
@@ -117,11 +119,13 @@ public class CMethodBindingEmitter extends FunctionEmitter
* being bound.
*/
public CMethodBindingEmitter(MethodBinding binding,
- boolean isOverloadedBinding,
+ PrintWriter output,
String javaPackageName,
String javaClassName,
+ boolean isOverloadedBinding,
boolean isJavaMethodStatic,
- PrintWriter output)
+ boolean forImplementingMethodCall,
+ boolean forIndirectBufferAndArrayImplementation)
{
super(output);
@@ -134,21 +138,14 @@ public class CMethodBindingEmitter extends FunctionEmitter
this.className = javaClassName;
this.isOverloadedBinding = isOverloadedBinding;
this.isJavaMethodStatic = isJavaMethodStatic;
- setCommentEmitter(defaultCommentEmitter);
- }
-
- public final MethodBinding getBinding() { return binding; }
+ this.forImplementingMethodCall = forImplementingMethodCall;
+ this.forIndirectBufferAndArrayImplementation = forIndirectBufferAndArrayImplementation;
- public boolean isIndirectBufferInterface() {
- return indirectBufferInterface;
- }
-
-
- public void setIndirectBufferInterface(boolean indirect) {
- indirectBufferInterface = indirect;
+ setCommentEmitter(defaultCommentEmitter);
}
+ public final MethodBinding getBinding() { return binding; }
public String getName() {
return binding.getName();
@@ -164,8 +161,8 @@ public class CMethodBindingEmitter extends FunctionEmitter
/**
* If this function returns a void* encapsulated in a
- * java.nio.Buffer, sets the expression for the capacity of the
- * returned Buffer.
+ * java.nio.Buffer (or compound type wrapper), sets the expression
+ * for the capacity of the returned Buffer.
*
* @param expression a MessageFormat which, when applied to an array
* of type String[] that contains each of the arguments names of the
@@ -175,18 +172,20 @@ public class CMethodBindingEmitter extends FunctionEmitter
* returned from this method.
*
* @throws IllegalArgumentException if the <code>
- * binding.getJavaReturnType().isNIOBuffer() == false
+ * binding.getJavaReturnType().isNIOBuffer() == false and
+ * binding.getJavaReturnType().isCompoundTypeWrapper() == false
* </code>
*/
public final void setReturnValueCapacityExpression(MessageFormat expression)
{
returnValueCapacityExpression = expression;
- if (!binding.getJavaReturnType().isNIOBuffer())
+ if (!binding.getJavaReturnType().isNIOBuffer() &&
+ !binding.getJavaReturnType().isCompoundTypeWrapper())
{
throw new IllegalArgumentException(
"Cannot specify return value capacity for a method that does not " +
- "return java.nio.Buffer: \"" + binding + "\"");
+ "return java.nio.Buffer or a compound type wrapper: \"" + binding + "\"");
}
}
@@ -217,7 +216,8 @@ public class CMethodBindingEmitter extends FunctionEmitter
{
returnValueLengthExpression = expression;
- if (!binding.getJavaReturnType().isArray())
+ if (!binding.getJavaReturnType().isArray() &&
+ !binding.getJavaReturnType().isArrayOfCompoundTypeWrappers())
{
throw new IllegalArgumentException(
"Cannot specify return value length for a method that does not " +
@@ -285,6 +285,12 @@ public class CMethodBindingEmitter extends FunctionEmitter
*/
public final boolean getIsJavaMethodStatic() { return isJavaMethodStatic; }
+ /**
+ * Is this CMethodBindingEmitter implementing the case of an
+ * indirect buffer or array being passed down to C code?
+ */
+ public final boolean forIndirectBufferAndArrayImplementation() { return forIndirectBufferAndArrayImplementation; }
+
protected void emitReturnType(PrintWriter writer)
{
writer.print("JNIEXPORT ");
@@ -314,10 +320,19 @@ public class CMethodBindingEmitter extends FunctionEmitter
}
}
+ protected String getImplSuffix() {
+ if (forImplementingMethodCall) {
+ if (forIndirectBufferAndArrayImplementation) {
+ return "1";
+ } else {
+ return "0";
+ }
+ }
+ return "";
+ }
+
protected int emitArguments(PrintWriter writer)
{
- int numBufferOffsetArgs = 0, numBufferOffsetArrayArgs = 0;
-
writer.print("JNIEnv *env, ");
int numEmitted = 1; // initially just the JNIEnv
if (isJavaMethodStatic && !binding.hasContainingType())
@@ -335,9 +350,6 @@ public class CMethodBindingEmitter extends FunctionEmitter
{
// "this" argument always comes down in argument 0 as direct buffer
writer.print(", jobject " + JavaMethodBindingEmitter.javaThisArgumentName());
- numBufferOffsetArgs++;
- // add Buffer offset argument for Buffer types
- writer.print(", jint " + byteOffsetConversionArgName(numBufferOffsetArgs));
}
for (int i = 0; i < binding.getNumArguments(); i++) {
JavaType javaArgType = binding.getJavaArgumentType(i);
@@ -357,28 +369,13 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer.print(binding.getArgumentName(i));
++numEmitted;
- // Replace following for indirect buffer case
- // if(javaArgType.isNIOBuffer() || javaArgType.isNIOBufferArray()) {
- if((javaArgType.isNIOBuffer() && !isIndirectBufferInterface()) || javaArgType.isNIOBufferArray()) {
- if(!javaArgType.isArray()) {
- numBufferOffsetArgs++;
- writer.print(", jint " + byteOffsetConversionArgName(numBufferOffsetArgs));
- } else {
- numBufferOffsetArrayArgs++;
- writer.print(", jintArray " +
- byteOffsetArrayConversionArgName(numBufferOffsetArrayArgs));
- }
- }
-
- // indirect buffer case needs same offset syntax as arrays
- if(javaArgType.isNIOBuffer() && isIndirectBufferInterface())
- writer.print(", jint " + binding.getArgumentName(i) + "_offset");
-
- // Add array primitive index/offset parameter
- if(javaArgType.isArray() && !javaArgType.isNIOBufferArray() && !javaArgType.isStringArray()) {
- writer.print(", jint " + binding.getArgumentName(i) + "_offset");
- }
-
+ if (javaArgType.isPrimitiveArray() ||
+ javaArgType.isNIOBuffer()) {
+ writer.print(", jint " + byteOffsetArgName(i));
+ } else if (javaArgType.isNIOBufferArray()) {
+ writer.print(", jintArray " +
+ byteOffsetArrayArgName(i));
+ }
}
return numEmitted;
}
@@ -418,7 +415,7 @@ public class CMethodBindingEmitter extends FunctionEmitter
continue;
}
- if (type.isArray() || type.isNIOBuffer()) {
+ if (type.isArray() || type.isNIOBuffer() || type.isCompoundTypeWrapper()) {
String convName = pointerConversionArgumentName(i);
// handle array/buffer argument types
boolean needsDataCopy =
@@ -435,7 +432,7 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer.println(" jsize _tmpArrayLen;");
// Pointer to the data in the Buffer, taking the offset into account
- writer.println(" GLint * _offsetHandle = NULL;");
+ writer.println(" int * _offsetHandle = NULL;");
emittedDataCopyTemps = true;
}
@@ -457,37 +454,36 @@ public class CMethodBindingEmitter extends FunctionEmitter
// Note we must respect const/volatile for return argument
writer.print(binding.getCSymbol().getReturnType().getName(true));
writer.println(" _res;");
- if (javaReturnType.isArray()) {
- if (javaReturnType.isNIOByteBufferArray()) {
- writer.print(" int ");
- writer.print(arrayResLength);
- writer.println(";");
- writer.print(" int ");
- writer.print(arrayIdx);
- writer.println(";");
- writer.print(" jobjectArray ");
- writer.print(arrayRes);
- writer.println(";");
- } else {
- writer.print(" int ");
- writer.print(arrayResLength);
- writer.println(";");
-
- Class componentType = javaReturnType.getJavaClass().getComponentType();
- if (componentType.isArray()) {
- throw new RuntimeException("Multi-dimensional arrays not supported yet");
- }
+ if (javaReturnType.isNIOByteBufferArray() ||
+ javaReturnType.isArrayOfCompoundTypeWrappers()) {
+ writer.print(" int ");
+ writer.print(arrayResLength);
+ writer.println(";");
+ writer.print(" int ");
+ writer.print(arrayIdx);
+ writer.println(";");
+ writer.print(" jobjectArray ");
+ writer.print(arrayRes);
+ writer.println(";");
+ } else if (javaReturnType.isArray()) {
+ writer.print(" int ");
+ writer.print(arrayResLength);
+ writer.println(";");
- String javaTypeName = componentType.getName();
- capitalizedComponentType =
- "" + Character.toUpperCase(javaTypeName.charAt(0)) + javaTypeName.substring(1);
- String javaArrayTypeName = "j" + javaTypeName + "Array";
- writer.print(" ");
- writer.print(javaArrayTypeName);
- writer.print(" ");
- writer.print(arrayRes);
- writer.println(";");
+ Class componentType = javaReturnType.getJavaClass().getComponentType();
+ if (componentType.isArray()) {
+ throw new RuntimeException("Multi-dimensional arrays not supported yet");
}
+
+ String javaTypeName = componentType.getName();
+ capitalizedComponentType =
+ "" + Character.toUpperCase(javaTypeName.charAt(0)) + javaTypeName.substring(1);
+ String javaArrayTypeName = "j" + javaTypeName + "Array";
+ writer.print(" ");
+ writer.print(javaArrayTypeName);
+ writer.print(" ");
+ writer.print(arrayRes);
+ writer.println(";");
}
}
}
@@ -504,6 +500,17 @@ public class CMethodBindingEmitter extends FunctionEmitter
}
}
+ /** Checks a type (expected to be pointer-to-pointer) for const-ness */
+ protected boolean isConstPtrPtr(Type type) {
+ if (type.pointerDepth() != 2) {
+ return false;
+ }
+ if (type.asPointer().getTargetType().asPointer().getTargetType().isConst()) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Code to init the variables that were declared in
* emitBodyVariableDeclarations(), PRIOR TO calling the actual C
@@ -512,21 +519,17 @@ public class CMethodBindingEmitter extends FunctionEmitter
protected void emitBodyVariablePreCallSetup(PrintWriter writer,
boolean emittingPrimitiveArrayCritical)
{
- int byteOffsetCounter=0, byteOffsetArrayCounter=0;
-
if (!emittingPrimitiveArrayCritical) {
// Convert all Buffers to pointers first so we don't have to
// call ReleasePrimitiveArrayCritical for any arrays if any
// incoming buffers aren't direct
- // we don't want to fall in here for indirectBuffer case, since its an array
- if (binding.hasContainingType() && !isIndirectBufferInterface()) {
- byteOffsetCounter++;
+ if (binding.hasContainingType()) {
emitPointerConversion(writer, binding,
binding.getContainingType(),
binding.getContainingCType(),
JavaMethodBindingEmitter.javaThisArgumentName(),
CMethodBindingEmitter.cThisArgumentName(),
- byteOffsetConversionArgName(byteOffsetCounter));
+ null);
}
for (int i = 0; i < binding.getNumArguments(); i++) {
@@ -535,13 +538,13 @@ public class CMethodBindingEmitter extends FunctionEmitter
continue;
}
- if (type.isNIOBuffer() && !isIndirectBufferInterface()) {
- byteOffsetCounter++;
+ if (type.isCompoundTypeWrapper() ||
+ (type.isNIOBuffer() && !forIndirectBufferAndArrayImplementation)) {
emitPointerConversion(writer, binding, type,
binding.getCArgumentType(i),
binding.getArgumentName(i),
pointerConversionArgumentName(i),
- byteOffsetConversionArgName(byteOffsetCounter));
+ byteOffsetArgName(i));
}
}
}
@@ -554,16 +557,9 @@ public class CMethodBindingEmitter extends FunctionEmitter
continue;
}
- // create array replacement type for Buffer for indirect Buffer case
- if(isIndirectBufferInterface() && javaArgType.isNIOBuffer()) {
- float[] c = new float[1];
- javaArgType = JavaType.createForClass(c.getClass());
- }
-
- if (javaArgType.isArray()) {
+ if (javaArgType.isArray() ||
+ (javaArgType.isNIOBuffer() && forIndirectBufferAndArrayImplementation)) {
boolean needsDataCopy = javaArgTypeNeedsDataCopy(javaArgType);
- Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType();
-
// We only defer the emission of GetPrimitiveArrayCritical
// calls that won't be matched up until after the function
@@ -588,15 +584,14 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer.print(" ");
writer.print(convName);
writer.print(" = (");
- if (javaArgType.isArray() &&
- javaArgType.getJavaClass().getComponentType() == java.lang.String.class) {
+ if (javaArgType.isStringArray()) {
// java-side type is String[]
cArgTypeName = "jstring *";
}
writer.print(cArgTypeName);
- writer.print(") (*env)->GetPrimitiveArrayCritical(env, ");
+ writer.print(") (((char*) (*env)->GetPrimitiveArrayCritical(env, ");
writer.print(binding.getArgumentName(i));
- writer.println(", NULL);");
+ writer.println(", NULL)) + " + byteOffsetArgName(i) + ");");
//if(cargtypename is void*)
// _ptrX = ((char*)convName + index1*sizeof(thisArgsJavaType));
@@ -607,7 +602,7 @@ public class CMethodBindingEmitter extends FunctionEmitter
//
// FIXME: should factor out this whole block of code into a separate
// method for clarity and maintenance purposes
- if (cArgType.toString().indexOf("const") == -1) {
+ if (!isConstPtrPtr(cArgType)) {
// FIXME: if the arg type is non-const, the sematics might be that
// the function modifies the argument -- we don't yet support
// this.
@@ -654,49 +649,43 @@ public class CMethodBindingEmitter extends FunctionEmitter
arrayLenName,
"Could not allocate buffer for copying data in argument \\\""+binding.getArgumentName(i)+"\\\"");
- // Get the handle for the byte offset array sent down for Buffers
- // But avoid doing this if the Array is a string array, the one exception since
- // that type is never converted to a Buffer according to JOGL semantics (for instance,
- // glShaderSourceARB Java signature is String[], not Buffer)
- byteOffsetArrayCounter++;
- if(subArrayElementJavaType != java.lang.String.class)
+ // Get the handle for the byte offset array sent down for Buffers
+ // FIXME: not 100% sure this is correct with respect to the
+ // JNI spec because it may be illegal to call
+ // GetObjectArrayElement while in a critical section. May
+ // need to do another loop and add in the offsets.
+ if (javaArgType.isNIOBufferArray()) {
writer.println
- (" _offsetHandle = (GLint *) (*env)->GetPrimitiveArrayCritical(env, " +
- byteOffsetArrayConversionArgName(byteOffsetArrayCounter) +
- ", NULL);");
-
+ (" _offsetHandle = (int *) (*env)->GetPrimitiveArrayCritical(env, " +
+ byteOffsetArrayArgName(i) +
+ ", NULL);");
+ }
// process each element in the array
writer.println(" for (_copyIndex = 0; _copyIndex < "+arrayLenName+"; ++_copyIndex) {");
// get each array element
writer.println(" /* get each element of the array argument \"" + binding.getArgumentName(i) + "\" */");
- String subArrayElementJNITypeString = jniType(subArrayElementJavaType);
- writer.print(" _tmpObj = (");
- writer.print(subArrayElementJNITypeString);
- writer.print(") (*env)->GetObjectArrayElement(env, ");
+ writer.print(" _tmpObj = (*env)->GetObjectArrayElement(env, ");
writer.print(binding.getArgumentName(i));
writer.println(", _copyIndex);");
- if (subArrayElementJNITypeString == "jstring")
- {
+ if (javaArgType.isStringArray()) {
writer.print(" ");
emitGetStringUTFChars(writer,
"(jstring) _tmpObj",
- convName+"_copy[_copyIndex]");
- }
- else if (isNIOBufferClass(subArrayElementJavaType))
- {
+ convName+"_copy[_copyIndex]",
+ true);
+ } else if (javaArgType.isNIOBufferArray()) {
/* We always assume an integer "byte offset" argument follows any Buffer
in the method binding. */
emitGetDirectBufferAddress(writer,
"_tmpObj",
cArgElementType.getName(),
convName + "_copy[_copyIndex]",
- "_offsetHandle[_copyIndex]");
- }
- else
- {
+ "_offsetHandle[_copyIndex]",
+ true);
+ } else {
// Question: do we always need to copy the sub-arrays, or just
// GetPrimitiveArrayCritical on each jobjectarray element and
// assign it to the appropriate elements at pointer depth 1?
@@ -704,46 +693,35 @@ public class CMethodBindingEmitter extends FunctionEmitter
// Malloc enough space to hold a copy of each sub-array
writer.print(" ");
emitMalloc(
- writer,
- convName+"_copy[_copyIndex]",
- cArgElementType.getTargetType().getName(), // assumes cArgPtrType is ptr-to-ptr-to-primitive !!
- "(*env)->GetArrayLength(env, _tmpObj)",
- "Could not allocate buffer during copying of data in argument \\\""+binding.getArgumentName(i)+"\\\"");
+ writer,
+ convName+"_copy[_copyIndex]",
+ cArgElementType.getTargetType().getName(), // assumes cArgPtrType is ptr-to-ptr-to-primitive !!
+ "(*env)->GetArrayLength(env, _tmpObj)",
+ "Could not allocate buffer during copying of data in argument \\\""+binding.getArgumentName(i)+"\\\"");
// FIXME: copy the data (use matched Get/ReleasePrimitiveArrayCritical() calls)
if (true) throw new RuntimeException(
- "Cannot yet handle type \"" + cArgType.getName() +
- "\"; need to add support for copying ptr-to-ptr-to-primitiveType subarrays");
+ "Cannot yet handle type \"" + cArgType.getName() +
+ "\"; need to add support for copying ptr-to-ptr-to-primitiveType subarrays");
}
writer.println(" }");
- if(subArrayElementJavaType != java.lang.String.class) {
- writer.println
- (" (*env)->ReleasePrimitiveArrayCritical(env, " +
- byteOffsetArrayConversionArgName(byteOffsetArrayCounter) +
- ", _offsetHandle, JNI_ABORT);");
+ if (javaArgType.isNIOBufferArray()) {
+ writer.println
+ (" (*env)->ReleasePrimitiveArrayCritical(env, " +
+ byteOffsetArrayArgName(i) +
+ ", _offsetHandle, JNI_ABORT);");
}
writer.println();
} // end of data copy
if (EMIT_NULL_CHECKS) {
- writer.print(" }");
-
- if (needsDataCopy) {
- writer.println();
- } else {
- // Zero out array offset in the case of a null pointer
- // being passed down to prevent construction of arbitrary
- // pointers
- writer.println(" else {");
- writer.println(" " + binding.getArgumentName(i) + "_offset = 0;");
- writer.println(" }");
- }
+ writer.println(" }");
}
} else if (javaArgType.isString()) {
- if (emittingPrimitiveArrayCritical) {
+ if (!emittingPrimitiveArrayCritical) {
continue;
}
@@ -755,7 +733,8 @@ public class CMethodBindingEmitter extends FunctionEmitter
emitGetStringUTFChars(writer,
binding.getArgumentName(i),
- "_UTF8" + binding.getArgumentName(i));
+ "_UTF8" + binding.getArgumentName(i),
+ false);
if (EMIT_NULL_CHECKS) {
writer.println(" }");
@@ -783,16 +762,9 @@ public class CMethodBindingEmitter extends FunctionEmitter
continue;
}
-
- // create array type for Indirect Buffer case
- if(isIndirectBufferInterface() && javaArgType.isNIOBuffer()) {
- float[] c = new float[1];
- javaArgType = JavaType.createForClass(c.getClass());
- }
-
- if (javaArgType.isArray()) {
+ if (javaArgType.isArray() ||
+ (javaArgType.isNIOBuffer() && forIndirectBufferAndArrayImplementation)) {
boolean needsDataCopy = javaArgTypeNeedsDataCopy(javaArgType);
- Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType();
if ((!needsDataCopy && !emittingPrimitiveArrayCritical) ||
(needsDataCopy && emittingPrimitiveArrayCritical)) {
@@ -838,7 +810,7 @@ public class CMethodBindingEmitter extends FunctionEmitter
// Only need to perform cleanup for individual array
// elements if they are not direct buffers
- if (!isNIOBufferClass(subArrayElementJavaType)) {
+ if (!javaArgType.isNIOBufferArray()) {
// Re-fetch length of array that was copied
String arrayLenName = "_tmpArrayLen";
writer.print(" ");
@@ -861,14 +833,11 @@ public class CMethodBindingEmitter extends FunctionEmitter
// get each array element
writer.println(" /* free each element of " +convName +"_copy */");
- String subArrayElementJNITypeString = jniType(subArrayElementJavaType);
- writer.print(" _tmpObj = (");
- writer.print(subArrayElementJNITypeString);
- writer.print(") (*env)->GetObjectArrayElement(env, ");
+ writer.print(" _tmpObj = (*env)->GetObjectArrayElement(env, ");
writer.print(binding.getArgumentName(i));
writer.println(", _copyIndex);");
- if (subArrayElementJNITypeString == "jstring") {
+ if (javaArgType.isStringArray()) {
writer.print(" (*env)->ReleaseStringUTFChars(env, ");
writer.print("(jstring) _tmpObj");
writer.print(", ");
@@ -920,25 +889,9 @@ public class CMethodBindingEmitter extends FunctionEmitter
}
}
- protected void emitBodyCallCFunction(PrintWriter writer)
- {
-
- // Make the call to the actual C function
- writer.print(" ");
-
- // WARNING: this code assumes that the return type has already been
- // typedef-resolved.
- Type cReturnType = binding.getCReturnType();
-
- if (!cReturnType.isVoid()) {
- writer.print("_res = ");
- }
- if (binding.hasContainingType()) {
- // Call through function pointer
- writer.print(CMethodBindingEmitter.cThisArgumentName() + "->");
- }
- writer.print(binding.getCSymbol().getName());
- writer.print("(");
+ /** Returns the number of arguments passed so calling code knows
+ whether to print a comma */
+ protected int emitBodyPassCArguments(PrintWriter writer) {
for (int i = 0; i < binding.getNumArguments(); i++) {
if (i != 0) {
writer.print(", ");
@@ -964,40 +917,39 @@ public class CMethodBindingEmitter extends FunctionEmitter
if (binding.getCArgumentType(i).isPointer() && binding.getJavaArgumentType(i).isPrimitive()) {
writer.print("(intptr_t) ");
}
- if (javaArgType.isArray() || javaArgType.isNIOBuffer()) {
-
- // Add special code for accounting for array offsets
- //
- // For mapping from byte primitive array type to type* case produces code:
- // (GLtype*)((char*)_ptr0 + varName_offset)
- // where varName_offset is the number of bytes offset as calculated in Java code
- // also, output same for indirect buffer as for array
- if(javaArgType.isNIOBuffer() && isIndirectBufferInterface())
- writer.print("( (char*)");
- else if(javaArgType.isArray() && !javaArgType.isNIOBufferArray() && !javaArgType.isStringArray()) {
- writer.print("( (char*)");
- }
- /* End of this section of new code for array offsets */
-
- writer.print(pointerConversionArgumentName(i));
- if (javaArgTypeNeedsDataCopy(javaArgType)) {
- writer.print("_copy");
- }
-
- /* Continuation of special code for accounting for array offsets */
- if(javaArgType.isNIOBuffer() && isIndirectBufferInterface())
- writer.print(" + " + binding.getArgumentName(i) + "_offset)");
- else if(javaArgType.isArray() && !javaArgType.isNIOBufferArray() && !javaArgType.isStringArray()) {
- writer.print(" + " + binding.getArgumentName(i) + "_offset)");
- }
- /* End of this section of new code for array offsets */
-
+ if (javaArgType.isArray() || javaArgType.isNIOBuffer() || javaArgType.isCompoundTypeWrapper()) {
+ writer.print(pointerConversionArgumentName(i));
+ if (javaArgTypeNeedsDataCopy(javaArgType)) {
+ writer.print("_copy");
+ }
} else {
if (javaArgType.isString()) { writer.print("_UTF8"); }
writer.print(binding.getArgumentName(i));
}
}
}
+ return binding.getNumArguments();
+ }
+
+ protected void emitBodyCallCFunction(PrintWriter writer) {
+
+ // Make the call to the actual C function
+ writer.print(" ");
+
+ // WARNING: this code assumes that the return type has already been
+ // typedef-resolved.
+ Type cReturnType = binding.getCReturnType();
+
+ if (!cReturnType.isVoid()) {
+ writer.print("_res = ");
+ }
+ if (binding.hasContainingType()) {
+ // Call through function pointer
+ writer.print(CMethodBindingEmitter.cThisArgumentName() + "->");
+ }
+ writer.print(binding.getCSymbol().getName());
+ writer.print("(");
+ emitBodyPassCArguments(writer);
writer.println(");");
}
@@ -1013,9 +965,6 @@ public class CMethodBindingEmitter extends FunctionEmitter
}
}
- // FIXME: refactor this so that subclasses (in particular,
- // net.java.games.gluegen.opengl.CGLPAWrapperEmitter) don't have to copy the whole
- // method
protected void emitBodyReturnResult(PrintWriter writer)
{
// WARNING: this code assumes that the return type has already been
@@ -1033,7 +982,8 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer.print("(" + javaReturnType.jniTypeName() + ") (intptr_t) ");
}
writer.println("_res;");
- } else if (javaReturnType.isNIOBuffer()) {
+ } else if (javaReturnType.isNIOBuffer() ||
+ javaReturnType.isCompoundTypeWrapper()) {
writer.println(" if (_res == NULL) return NULL;");
writer.print(" return (*env)->NewDirectByteBuffer(env, _res, ");
// See whether capacity has been specified
@@ -1051,7 +1001,7 @@ public class CMethodBindingEmitter extends FunctionEmitter
cReturnType.asPointer().getTargetType().isCompound()) {
sz = cReturnType.asPointer().getTargetType().getSize();
if (sz == -1) {
- throw new InternalError(
+ throw new RuntimeException(
"Error emitting code for compound return type "+
"for function \"" + binding + "\": " +
"Structs to be emitted should have been laid out by this point " +
@@ -1072,64 +1022,67 @@ public class CMethodBindingEmitter extends FunctionEmitter
} else if (javaReturnType.isString()) {
writer.print(" if (_res == NULL) return NULL;");
writer.println(" return (*env)->NewStringUTF(env, _res);");
- } else if (javaReturnType.isArray()) {
- if (javaReturnType.isNIOByteBufferArray()) {
- writer.println(" if (_res == NULL) return NULL;");
- if (returnValueLengthExpression == null) {
- 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(" " + 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();
- Type baseType;
- if (retType.isPointer()) {
- baseType = retType.asPointer().getTargetType().asPointer().getTargetType();
- } else {
- baseType = retType.asArray().getElementType().asPointer().getTargetType();
- }
- int sz = baseType.getSize();
- if (sz < 0)
- sz = 0;
- writer.println(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx +
- ", (*env)->NewDirectByteBuffer(env, _res[" + arrayIdx + "], " + sz + "));");
- writer.println(" }");
- writer.println(" return " + arrayRes + ";");
+ } else if (javaReturnType.isArrayOfCompoundTypeWrappers() ||
+ (javaReturnType.isArray() && javaReturnType.isNIOByteBufferArray())) {
+ writer.println(" if (_res == NULL) return NULL;");
+ if (returnValueLengthExpression == null) {
+ 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(" " + 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();
+ Type baseType;
+ if (retType.isPointer()) {
+ baseType = retType.asPointer().getTargetType().asPointer().getTargetType();
} else {
- // FIXME: must have user provide length of array in .cfg file
- // by providing a constant value, input parameter, or
- // expression which computes the array size (already present
- // as ReturnValueCapacity, not yet implemented / tested here)
-
- throw new RuntimeException(
- "Could not emit native code for function \"" + binding +
- "\": array return values for non-char types not implemented yet");
-
- // FIXME: This is approximately what will be required here
- //
- //writer.print(" ");
- //writer.print(arrayRes);
- //writer.print(" = (*env)->New");
- //writer.print(capitalizedComponentType);
- //writer.print("Array(env, ");
- //writer.print(arrayResLength);
- //writer.println(");");
- //writer.print(" (*env)->Set");
- //writer.print(capitalizedComponentType);
- //writer.print("ArrayRegion(env, ");
- //writer.print(arrayRes);
- //writer.print(", 0, ");
- //writer.print(arrayResLength);
- //writer.println(", _res);");
- //writer.print(" return ");
- //writer.print(arrayRes);
- //writer.println(";");
+ baseType = retType.asArray().getElementType().asPointer().getTargetType();
}
+ int sz = baseType.getSize();
+ if (sz < 0)
+ sz = 0;
+ writer.println(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx +
+ ", (*env)->NewDirectByteBuffer(env, _res[" + arrayIdx + "], " + sz + "));");
+ writer.println(" }");
+ writer.println(" return " + arrayRes + ";");
+ } else if (javaReturnType.isArray()) {
+ // FIXME: must have user provide length of array in .cfg file
+ // by providing a constant value, input parameter, or
+ // expression which computes the array size (already present
+ // as ReturnValueCapacity, not yet implemented / tested here)
+
+ throw new RuntimeException(
+ "Could not emit native code for function \"" + binding +
+ "\": array return values for non-char types not implemented yet");
+
+ // FIXME: This is approximately what will be required here
+ //
+ //writer.print(" ");
+ //writer.print(arrayRes);
+ //writer.print(" = (*env)->New");
+ //writer.print(capitalizedComponentType);
+ //writer.print("Array(env, ");
+ //writer.print(arrayResLength);
+ //writer.println(");");
+ //writer.print(" (*env)->Set");
+ //writer.print(capitalizedComponentType);
+ //writer.print("ArrayRegion(env, ");
+ //writer.print(arrayRes);
+ //writer.print(", 0, ");
+ //writer.print(arrayResLength);
+ //writer.println(", _res);");
+ //writer.print(" return ");
+ //writer.print(arrayRes);
+ //writer.println(";");
+ } else {
+ System.err.print("Unhandled return type: ");
+ javaReturnType.dump();
+ throw new RuntimeException("Unhandled return type");
}
}
}
@@ -1146,38 +1099,56 @@ public class CMethodBindingEmitter extends FunctionEmitter
protected String jniMangle(MethodBinding binding) {
StringBuffer buf = new StringBuffer();
buf.append(jniMangle(binding.getName()));
+ buf.append(getImplSuffix());
buf.append("__");
+ if (binding.hasContainingType()) {
+ // "this" argument always comes down in argument 0 as direct buffer
+ jniMangle(java.nio.ByteBuffer.class, buf, true);
+ }
for (int i = 0; i < binding.getNumArguments(); i++) {
+ if (binding.isArgumentThisPointer(i)) {
+ continue;
+ }
JavaType type = binding.getJavaArgumentType(i);
- Class c = type.getJavaClass();
- if (c != null) {
- jniMangle(c, buf);
- // If Buffer offset arguments were added, we need to mangle the JNI for the
- // extra arguments
- if(type.isNIOBuffer()) {
- jniMangle(Integer.TYPE, buf);
- } else if (type.isNIOBufferArray()) {
- int[] intArrayType = new int[0];
- c = intArrayType.getClass();
- jniMangle(c , buf);
- }
- if(type.isArray() && !type.isNIOBufferArray()) {
- jniMangle(Integer.TYPE, buf);
- }
+ if (type.isVoid()) {
+ // We should only see "void" as the first argument of a 1-argument function
+ // FIXME: should normalize this in the parser
+ if ((i != 0) || (binding.getNumArguments() > 1)) {
+ throw new RuntimeException("Saw illegal \"void\" argument while emitting \"" + binding.getName() + "\"");
+ }
} else {
- // FIXME: add support for char* -> String conversion
- throw new RuntimeException("Unknown kind of JavaType: name="+type.getName());
+ Class c = type.getJavaClass();
+ if (c != null) {
+ jniMangle(c, buf, false);
+ // If Buffer offset arguments were added, we need to mangle the JNI for the
+ // extra arguments
+ if (type.isNIOBuffer()) {
+ jniMangle(Integer.TYPE, buf, false);
+ } else if (type.isNIOBufferArray()) {
+ int[] intArrayType = new int[0];
+ c = intArrayType.getClass();
+ jniMangle(c , buf, true);
+ }
+ if (type.isPrimitiveArray()) {
+ jniMangle(Integer.TYPE, buf, false);
+ }
+ } else if (type.isCompoundTypeWrapper()) {
+ // Mangle wrappers for C structs as ByteBuffer
+ jniMangle(java.nio.ByteBuffer.class, buf, true);
+ } else if (type.isJNIEnv()) {
+ // These are not exposed at the Java level
+ } else {
+ // FIXME: add support for char* -> String conversion
+ throw new RuntimeException("Unknown kind of JavaType: name="+type.getName());
+ }
}
}
return buf.toString();
}
- protected void jniMangle(Class c, StringBuffer res) {
- if (c.isArray()) {
- res.append("_3");
- jniMangle(c.getComponentType(), res);
- } else if (c.isPrimitive()) {
+ protected void jniMangle(Class c, StringBuffer res, boolean syntheticArgument) {
+ if (c.isPrimitive()) {
if (c == Boolean.TYPE) res.append("Z");
else if (c == Byte.TYPE) res.append("B");
else if (c == Character.TYPE) res.append("C");
@@ -1186,35 +1157,37 @@ public class CMethodBindingEmitter extends FunctionEmitter
else if (c == Long.TYPE) res.append("J");
else if (c == Float.TYPE) res.append("F");
else if (c == Double.TYPE) res.append("D");
- else throw new InternalError("Illegal primitive type");
+ else throw new RuntimeException("Illegal primitive type \"" + c.getName() + "\"");
} else {
- if(!isIndirectBufferInterface()) {
- res.append("L");
- res.append(c.getName().replace('.', '_'));
- res.append("_2");
- } else { // indirect buffer sends array as object
- res.append("L");
- res.append("java_lang_Object");
- res.append("_2");
- }
+ // Arrays and NIO Buffers are always passed down as java.lang.Object.
+ // The only arrays that show up as true arrays in the signature
+ // are the synthetic byte offset arrays created when passing
+ // down arrays of direct Buffers. Compound type wrappers are
+ // passed down as ByteBuffers (no good reason, just to avoid
+ // accidental conflation) so we mangle them differently.
+ if (syntheticArgument) {
+ if (c.isArray()) {
+ res.append("_3");
+ jniMangle(c.getComponentType(), res, false);
+ } else {
+ res.append("L");
+ res.append(c.getName().replace('.', '_'));
+ res.append("_2");
+ }
+ } else {
+ if (c == java.lang.String.class) {
+ res.append("L");
+ res.append(c.getName().replace('.', '_'));
+ res.append("_2");
+ } else {
+ res.append("L");
+ res.append("java_lang_Object");
+ res.append("_2");
+ }
+ }
}
}
- private String jniType(Class javaType)
- {
- if (javaType.isPrimitive()) {
- return "j" + javaType.getName();
- } else if (javaType == java.lang.String.class) {
- return "jstring";
- } else if (isNIOBufferClass(javaType)) {
- return "jobject";
- } else {
- throw new RuntimeException(
- "Could not determine JNI type for Java class \"" +
- javaType.getName() + "\"; was not String, primitive or direct buffer");
- }
- }
-
private void emitOutOfMemoryCheck(PrintWriter writer, String varName,
String errorMessage)
{
@@ -1259,11 +1232,14 @@ public class CMethodBindingEmitter extends FunctionEmitter
private void emitGetStringUTFChars(PrintWriter writer,
String sourceVarName,
- String receivingVarName)
+ String receivingVarName,
+ boolean emitElseClause)
{
- writer.print(" if (");
- writer.print(sourceVarName);
- writer.println(" != NULL) {");
+ if (EMIT_NULL_CHECKS) {
+ writer.print(" if (");
+ writer.print(sourceVarName);
+ writer.println(" != NULL) {");
+ }
writer.print(" ");
writer.print(receivingVarName);
writer.print(" = (*env)->GetStringUTFChars(env, ");
@@ -1276,11 +1252,18 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer, receivingVarName,
"Failed to get UTF-8 chars for argument \\\""+sourceVarName+"\\\"");
}
- writer.println(" } else {");
- writer.print(" ");
- writer.print(receivingVarName);
- writer.println(" = NULL;");
- writer.println(" }");
+ if (EMIT_NULL_CHECKS) {
+ writer.print(" }");
+ if (emitElseClause) {
+ writer.print(" else {");
+ writer.print(" ");
+ writer.print(receivingVarName);
+ writer.println(" = NULL;");
+ writer.println(" }");
+ } else {
+ writer.println();
+ }
+ }
}
@@ -1289,56 +1272,37 @@ public class CMethodBindingEmitter extends FunctionEmitter
String sourceVarName,
String receivingVarTypeString,
String receivingVarName,
- String byteOffsetVarName) {
+ String byteOffsetVarName,
+ boolean emitElseClause) {
if (EMIT_NULL_CHECKS) {
- writer.print(" if (");
+ writer.print(" if (");
writer.print(sourceVarName);
writer.println(" != NULL) {");
+ writer.print(" ");
}
- /* Pre Buffer Offset code: In the case where there is NOT an integer offset
- in bytes for the direct buffer, we used to use:
- (type*) (*env)->GetDirectBufferAddress(env, buf);
- generated as follows:
- if(byteOffsetVarName == null) {
- writer.print(" ");
- writer.print(receivingVarName);
- writer.print(" = (");
- writer.print(receivingVarTypeString);
- writer.print(") (*env)->GetDirectBufferAddress(env, ");
- writer.print(sourceVarName);
- writer.println(");");
- */
-
- /* In the case (now always the case) where there is an integer offset in bytes for
- the direct buffer, we want to use:
- _ptrX = (type*) (*env)->GetDirectBufferAddress(env, buf);
- _ptrX = (type*) ((char*)buf + __byteOffset);
- Note that __byteOffset is an int */
- writer.print(" ");
- writer.print(receivingVarName);
- writer.print(" = (");
- writer.print(receivingVarTypeString);
-
- writer.print(") (*env)->GetDirectBufferAddress(env, ");
- writer.print(sourceVarName);
- writer.println(");");
-
- writer.print(" ");
- writer.print(receivingVarName);
- writer.print(" = (");
- writer.print(receivingVarTypeString);
- writer.print(") ((char*)" + receivingVarName + " + ");
- writer.println(byteOffsetVarName + ");");
+
+ writer.print(" ");
+ writer.print(receivingVarName);
+ writer.print(" = (");
+ writer.print(receivingVarTypeString);
+
+ writer.print(") (((char*) (*env)->GetDirectBufferAddress(env, ");
+ writer.print(sourceVarName);
+ writer.println(")) + " + ((byteOffsetVarName != null) ? byteOffsetVarName : "0") + ");");
if (EMIT_NULL_CHECKS) {
- writer.println(" } else {");
- writer.print(" ");
- writer.print(receivingVarName);
- writer.println(" = NULL;");
- writer.println(" }");
+ writer.print(" }");
+ if (emitElseClause) {
+ writer.println(" else {");
+ writer.print(" ");
+ writer.print(receivingVarName);
+ writer.println(" = NULL;");
+ writer.println(" }");
+ } else {
+ writer.println();
+ }
}
}
-
// Note: if the data in the Type needs to be converted from the Java memory
// model to the C memory model prior to calling any C-side functions, then
@@ -1356,80 +1320,54 @@ public class CMethodBindingEmitter extends FunctionEmitter
//
// Note that we don't need to obey const/volatile for outgoing arguments
//
- if (javaType.isNIOBuffer())
- {
+ if (javaType.isNIOBuffer()) {
ptrTypeString = cType.getName();
- }
- else if (javaType.isArray()) {
+ } else if (javaType.isArray()) {
needsDataCopy = javaArgTypeNeedsDataCopy(javaType);
- // It's an array; get the type of the elements in the array
- Class elementType = javaType.getJavaClass().getComponentType();
- if (elementType.isPrimitive())
- {
+ if (javaType.isPrimitiveArray() ||
+ javaType.isNIOBufferArray()) {
ptrTypeString = cType.getName();
- }
- else if (elementType == java.lang.String.class)
- {
- ptrTypeString = "jstring";
- }
- else if (elementType.isArray())
- {
- Class subElementType = elementType.getComponentType();
- if (subElementType.isPrimitive())
- {
- // type is pointer to pointer to primitive
- ptrTypeString = cType.getName();
- }
- else
- {
+ } else if (!javaType.isStringArray()) {
+ Class elementType = javaType.getJavaClass().getComponentType();
+ if (elementType.isArray()) {
+ Class subElementType = elementType.getComponentType();
+ if (subElementType.isPrimitive()) {
+ // type is pointer to pointer to primitive
+ ptrTypeString = cType.getName();
+ } else {
+ // type is pointer to pointer of some type we don't support (maybe
+ // it's an array of pointers to structs?)
+ throw new RuntimeException("Unsupported pointer type: \"" + cType.getName() + "\"");
+ }
+ } else {
// type is pointer to pointer of some type we don't support (maybe
// it's an array of pointers to structs?)
throw new RuntimeException("Unsupported pointer type: \"" + cType.getName() + "\"");
}
-
- }
- else if (isNIOBufferClass(elementType))
- {
- // type is an array of direct buffers of some sort
- ptrTypeString = cType.getName();
}
- else
- {
- // Type is pointer to something we can't/don't handle
- throw new RuntimeException("Unsupported pointer type: \"" + cType.getName() + "\"");
- }
- }
- else if (javaType.isArrayOfCompoundTypeWrappers())
- {
+ } else if (javaType.isArrayOfCompoundTypeWrappers()) {
// FIXME
throw new RuntimeException("Outgoing arrays of StructAccessors not yet implemented");
- }
- else
- {
+ } else {
ptrTypeString = cType.getName();
}
- if (!needsDataCopy)
- {
+ if (!needsDataCopy) {
// declare the pointer variable
writer.print(" ");
writer.print(ptrTypeString);
writer.print(" ");
writer.print(cVariableName);
writer.println(" = NULL;");
- }
- else
- {
+ } else {
// Declare a variable to hold a copy of the argument data in which the
// incoming data has been properly laid out in memory to match the C
// memory model
- //writer.print(" const ");
Class elementType = javaType.getJavaClass().getComponentType();
- if (javaType.isArray() &&
- javaType.getJavaClass().getComponentType() == java.lang.String.class) {
+ if (javaType.isStringArray()) {
writer.print(" const char **");
} else {
- writer.print(ptrTypeString);
+ writer.print(" " + ptrTypeString);
}
writer.print(" ");
writer.print(cVariableName);
@@ -1448,45 +1386,34 @@ public class CMethodBindingEmitter extends FunctionEmitter
String incomingArgumentName,
String cVariableName,
String byteOffsetVarName) {
+ // Compound type wrappers do not get byte offsets added on
+ if (type.isCompoundTypeWrapper()) {
+ byteOffsetVarName = null;
+ }
+
emitGetDirectBufferAddress(writer,
incomingArgumentName,
cType.getName(),
cVariableName,
- byteOffsetVarName);
-
- /*
- if (EMIT_NULL_CHECKS) {
- writer.print(" if (");
- writer.print(incomingArgumentName);
- writer.println(" != NULL) {");
- }
-
- writer.print(" ");
- writer.print(cVariableName);
- writer.print(" = (");
- writer.print(cType.getName());
- writer.print(") (*env)->GetDirectBufferAddress(env, ");
- writer.print(incomingArgumentName);
- writer.println(");");
-
- if (EMIT_NULL_CHECKS) {
- writer.println(" }");
- }
- */
+ byteOffsetVarName,
+ false);
}
- protected String pointerConversionArgumentName(int i) {
- return "_ptr" + i;
+ protected String byteOffsetArgName(int i) {
+ return byteOffsetArgName(binding.getArgumentName(i));
}
- protected String byteOffsetConversionArgName(int i) {
- return "__byteOffset" + i;
+ protected String byteOffsetArgName(String s) {
+ return s + "_byte_offset";
}
-
- protected String byteOffsetArrayConversionArgName(int i) {
- return "__byteOffsetArray" + i;
+
+ protected String byteOffsetArrayArgName(int i) {
+ return binding.getArgumentName(i) + "_byte_offset_array";
+ }
+
+ protected String pointerConversionArgumentName(int i) {
+ return "_ptr" + i;
}
-
/**
* Class that emits a generic comment for CMethodBindingEmitters; the comment
@@ -1515,16 +1442,10 @@ public class CMethodBindingEmitter extends FunctionEmitter
protected boolean javaArgTypeNeedsDataCopy(JavaType javaArgType) {
if (javaArgType.isArray()) {
- Class subArrayElementJavaType = javaArgType.getJavaClass().getComponentType();
- return (subArrayElementJavaType.isArray() ||
- subArrayElementJavaType == java.lang.String.class ||
- isNIOBufferClass(subArrayElementJavaType));
+ return (javaArgType.isNIOBufferArray() ||
+ javaArgType.isStringArray() ||
+ javaArgType.getJavaClass().getComponentType().isArray());
}
return false;
}
-
- protected static boolean isNIOBufferClass(Class c) {
- return java.nio.Buffer.class.isAssignableFrom(c);
- }
}
-
diff --git a/src/net/java/games/gluegen/CMethodBindingImplEmitter.java b/src/net/java/games/gluegen/CMethodBindingImplEmitter.java
deleted file mode 100644
index 3f3505896..000000000
--- a/src/net/java/games/gluegen/CMethodBindingImplEmitter.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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 Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package net.java.games.gluegen;
-
-import java.util.*;
-import java.io.*;
-import java.text.MessageFormat;
-
-public class CMethodBindingImplEmitter extends CMethodBindingEmitter
-{
- protected static final CommentEmitter defaultCImplCommentEmitter =
- new CImplCommentEmitter();
-
- protected boolean arrayImplRoutine = false;
-
- public CMethodBindingImplEmitter(MethodBinding binding,
- boolean isOverloadedBinding,
- boolean arrayImpl,
- String javaPackageName,
- String javaClassName,
- boolean isJavaMethodStatic,
- PrintWriter output)
- {
- super(binding, isOverloadedBinding,
- javaPackageName, javaClassName,
- isJavaMethodStatic, output);
- setCommentEmitter(defaultCImplCommentEmitter);
- arrayImplRoutine = arrayImpl;
- }
-
- protected void emitName(PrintWriter writer)
- {
- super.emitName(writer);
- if (!getIsOverloadedBinding()) {
- if( isIndirectBufferInterface() )
- writer.print("2");
- else if(!arrayImplRoutine)
- writer.print("0");
- else
- writer.print("1");
- }
- }
-
- /**
- * Gets the mangled name for the binding, but assumes that this is an Impl
- * routine
- */
- protected String jniMangle(MethodBinding binding) {
- StringBuffer buf = new StringBuffer();
- buf.append(jniMangle(binding.getName()));
-
- if( isIndirectBufferInterface() )
- buf.append("2");
- else if(!arrayImplRoutine)
- buf.append("0");
- else
- buf.append("1");
-
- buf.append("__");
- for (int i = 0; i < binding.getNumArguments(); i++) {
- JavaType type = binding.getJavaArgumentType(i);
-
- Class c = type.getJavaClass();
- if (c != null) {
- jniMangle(c, buf);
- // Add mangling for buffer offset arguments
- if(type.isNIOBuffer()) {
- jniMangle(Integer.TYPE, buf);
- } else if (type.isNIOBufferArray()) {
- int[] intArrayType = new int[0];
- c = intArrayType.getClass();
- jniMangle(c , buf);
- }
- if(type.isArray() && !type.isNIOBufferArray() && !type.isStringArray()) {
- jniMangle(Integer.TYPE, buf);
- }
- } else {
- // FIXME: add support for char* -> String conversion
- throw new RuntimeException("Unknown kind of JavaType: name="+type.getName());
- }
- }
- return buf.toString();
- }
-
- protected static class CImplCommentEmitter extends CMethodBindingEmitter.DefaultCommentEmitter {
- protected void emitBeginning(FunctionEmitter methodEmitter, PrintWriter writer) {
- writer.print(" -- FIXME: PUT A COMMENT HERE -- ");
- }
- }
-}
diff --git a/src/net/java/games/gluegen/JavaConfiguration.java b/src/net/java/games/gluegen/JavaConfiguration.java
index e39a147f8..51e22f7d6 100644
--- a/src/net/java/games/gluegen/JavaConfiguration.java
+++ b/src/net/java/games/gluegen/JavaConfiguration.java
@@ -50,28 +50,6 @@ import net.java.games.gluegen.cgram.types.*;
public class JavaConfiguration {
- /* possible PrimitiveArrayExpansionMode states */
- private int ALL_POINTERS = 1;
- private int NON_VOID_ONLY = 2;
- private int NO_POINTERS = 3;
-
- /* Default primitive array expansion mode is ALL_POINTERS, meaning all C
- pointers, including void pointers, will have Java primitive array
- expansions */
- private int primitiveArrayExpansionMode = ALL_POINTERS;
-
- /* Determines which primitive array types void * C signatures are
- expanded into (assuming PrimitiveArrayExpansionMode = ALL_POINTERS). */
- private boolean voidPointerExpansionToBoolean = true;
- private boolean voidPointerExpansionToChar = true;
- private boolean voidPointerExpansionToByte = true;
- private boolean voidPointerExpansionToShort = true;
- private boolean voidPointerExpansionToInt = true;
- private boolean voidPointerExpansionToLong = true;
- private boolean voidPointerExpansionToFloat = true;
- private boolean voidPointerExpansionToDouble = true;
-
-
private int nestedReads;
private String packageName;
private String implPackageName;
@@ -120,21 +98,12 @@ public class JavaConfiguration {
private Set/*<Pattern>*/ ignoreNots = new HashSet();
private Set/*<Pattern>*/ unimplemented = new HashSet();
private Set/*<String>*/ nioDirectOnly = new HashSet();
- /** See {@link #nioMode} */
- public static final int NIO_MODE_VOID_ONLY = 1;
- /** See {@link #nioMode} */
- public static final int NIO_MODE_ALL_POINTERS = 2;
- private int nioMode = NIO_MODE_VOID_ONLY;
- private Set/*<String>*/ noNio = new HashSet();
- private Set/*<String>*/ forcedNio = new HashSet();
- private boolean flattenNIOVariants = true;
private Set/*<String>*/ manuallyImplement = new HashSet();
private Map/*<String,List<String>>*/ customJavaCode = new HashMap();
private Map/*<String,List<String>>*/ classJavadoc = new HashMap();
private Map/*<String,String>*/ structPackages = new HashMap();
private List/*<String>*/ customCCode = new ArrayList();
private List/*<String>*/ forcedStructs = new ArrayList();
- private Map/*<String,List<Integer>>*/ mirroredArgs = new HashMap();
private Map/*<String, String>*/ returnValueCapacities = new HashMap();
private Map/*<String, String>*/ returnValueLengths = new HashMap();
private Map/*<String, List<String>>*/ temporaryCVariableDeclarations = new HashMap();
@@ -253,30 +222,6 @@ public class JavaConfiguration {
/** Returns the list of imports that should be emitted at the top of each .java file. */
public List/*<String>*/ imports() { return imports; }
-
- /* Return Primitive Array Expansion Mode state */
- public boolean isPrimArrayExpModeAllPtrs() {
- return (primitiveArrayExpansionMode == ALL_POINTERS);
- }
- public boolean isPrimArrayExpModeNonVoidPtrs() {
- return (primitiveArrayExpansionMode == NON_VOID_ONLY);
- }
- public boolean isPrimArrayExpModeNoPtrs() {
- return (primitiveArrayExpansionMode == NO_POINTERS);
- }
-
-
- /** Returns VoidPointerExpansion values */
- public boolean voidPointerExpansionToBoolean() { return voidPointerExpansionToBoolean; }
- public boolean voidPointerExpansionToChar() { return voidPointerExpansionToChar; }
- public boolean voidPointerExpansionToByte() { return voidPointerExpansionToByte; }
- public boolean voidPointerExpansionToShort() { return voidPointerExpansionToShort; }
- public boolean voidPointerExpansionToInt() { return voidPointerExpansionToInt; }
- public boolean voidPointerExpansionToLong() { return voidPointerExpansionToLong; }
- public boolean voidPointerExpansionToFloat() { return voidPointerExpansionToFloat; }
- public boolean voidPointerExpansionToDouble() { return voidPointerExpansionToDouble; }
-
-
/** If this type should be considered opaque, returns the TypeInfo
describing the replacement type. Returns null if this type
should not be considered opaque. */
@@ -367,40 +312,6 @@ public class JavaConfiguration {
return nioDirectOnly.contains(functionName);
}
- /** Returns true if the user requested that the given function
- should only create array variants, and no java.nio variant, for
- <code>void*</code> and other C primitive pointers, overriding
- the NIO mode default. */
- public boolean noNio(String functionName) {
- return noNio.contains(functionName);
- }
-
- /** Returns true if the user requested that the given function
- should create a java.nio variant for the given function's
- <code>void*</code> and other C primitive pointers, overriding
- the NIO mode default. */
- public boolean forcedNio(String functionName) {
- return forcedNio.contains(functionName);
- }
-
- /** Returns the default NIO generation mode for C primitive pointer
- arguments. NIO_MODE_VOID_ONLY is the default and specifies
- that only void* arguments will have java.nio variants generated
- for them. NIO_MODE_ALL_POINTERS specifies that all C
- primitive arguments will have java.nio variants generated. */
- public int nioMode() {
- return nioMode;
- }
-
- /** Returns true if, for the plethora of java.nio variants generated
- for primitive C pointer types, the emitter should flatten the
- output down to two variants: one taking only Java primitive
- arrays as arguments, and one taking only java.nio.Buffers as
- arguments. */
- public boolean flattenNIOVariants() {
- return flattenNIOVariants;
- }
-
/** Returns true if the glue code for the given function will be
manually implemented by the end user. */
public boolean manuallyImplement(String functionName) {
@@ -456,14 +367,6 @@ public class JavaConfiguration {
return forcedStructs;
}
- /** Returns a List of Integers indicating the indices of arguments
- in this function that should be expanded to the same type when
- binding functions with multiple void* arguments. Returns null if
- no such indices were specified. */
- public List/*<Integer>*/ mirroredArgs(String functionName) {
- return (List) mirroredArgs.get(functionName);
- }
-
/** Returns a MessageFormat string of the C expression calculating
the capacity of the java.nio.ByteBuffer being returned from a
native method, or null if no expression has been specified. */
@@ -676,22 +579,8 @@ public class JavaConfiguration {
// because readClassJavadoc changes them.
} else if (cmd.equalsIgnoreCase("NioDirectOnly")) {
nioDirectOnly.add(readString("NioDirectOnly", tok, filename, lineNo));
- } else if (cmd.equalsIgnoreCase("NoNio")) {
- noNio.add(readString("NoNio", tok, filename, lineNo));
- } else if (cmd.equalsIgnoreCase("ForcedNio")) {
- forcedNio.add(readString("ForcedNio", tok, filename, lineNo));
- } else if (cmd.equalsIgnoreCase("NioMode")) {
- readNioMode(tok, filename, lineNo);
- } else if (cmd.equalsIgnoreCase("FlattenNIOVariants")) {
- flattenNIOVariants = readBoolean("FlattenNIOVariants", tok, filename, lineNo).booleanValue();
- } else if (cmd.equalsIgnoreCase("PrimitiveArrayExpansionMode")) {
- readPrimitiveExpMode(tok, filename, lineNo);
- } else if (cmd.equalsIgnoreCase("VoidPointerExpansion")) {
- readVoidPointerExpansionSet(tok, filename, lineNo);
} else if (cmd.equalsIgnoreCase("EmitStruct")) {
forcedStructs.add(readString("EmitStruct", tok, filename, lineNo));
- } else if (cmd.equalsIgnoreCase("MirrorExpandedBindingArgs")) {
- readMirrorExpandedBindingArgs(tok, filename, lineNo);
} else if (cmd.equalsIgnoreCase("StructPackage")) {
readStructPackage(tok, filename, lineNo);
} else if (cmd.equalsIgnoreCase("TemporaryCVariableDeclaration")) {
@@ -899,226 +788,6 @@ public class JavaConfiguration {
codeList.add(code);
}
- /**
- * Sets the default NIO generation mode for C primitive
- * pointers. Options are VOID_ONLY or ALL_POINTERS. When the mode is
- * set to VOID_ONLY, java.nio variants of methods are only generated
- * for C primitive pointers of type <code>void*</code>. All other
- * pointers are translated by default into Java primitive arrays.
- * When the mode is set to ALL_POINTERS, C primitive pointers of
- * other types (i.e., <code>int*</code>) will have java.nio variants
- * generated for them (i.e., <code>IntBuffer</code> as opposed to
- * merely <code>int[]</code>). This default mode can be overridden
- * with the NioDirectOnly and NoNio directives. The default for this mode
- * is currently VOID_ONLY.
- */
- protected void readNioMode(StringTokenizer tok, String filename, int lineNo) {
- try {
- String mode = tok.nextToken();
- if (mode.equalsIgnoreCase("VOID_ONLY")) {
- nioMode = NIO_MODE_VOID_ONLY;
- } else if (mode.equalsIgnoreCase("ALL_POINTERS")) {
- nioMode = NIO_MODE_ALL_POINTERS;
- } else {
- throw new RuntimeException("Error parsing \"NioMode\" command at line " + lineNo +
- " in file \"" + filename + "\"; expected VOID_ONLY or ALL_POINTERS");
- }
- } catch (NoSuchElementException e) {
- throw new RuntimeException(
- "Error parsing \"NioMode\" command at line " + lineNo +
- " in file \"" + filename + "\"", e);
- }
- }
-
-
- /**
- * Sets the Primitive Array Expansion Mode. Options are ALL_POINTERS (default),
- * NON_VOID_ONLY, and NO_POINTERS. ALL_POINTERS means that all Primitive array
- * C pointers (float*, int*, void*, etc.) get expanded into non-NIO buffer
- * targets. The setting has no bearing on whether NIO buffer targets happen.
- * So float * goes to float[], int* goes to int[], and void* gets expanded to
- * (by default) double[], float[], long[], int[], short[], byte[], char[], and
- * boolean[]. NON_VOID_ONLY means that all Primitive array pointers except
- * for void * get expanded, and NO_POINTERS means that no C Primitive array
- * pointers get expanded.
- * For void * expansion the default is all 8 primitive types as listed above.
- * However, the types can be restricted by use of the VoidPointerExpansion
- * attribute defined elsewhere in this file.
- */
-
- protected void readPrimitiveExpMode(StringTokenizer tok, String filename, int lineNo) {
- try {
- String mode = tok.nextToken();
- if (mode.equalsIgnoreCase("ALL_POINTERS")) {
- primitiveArrayExpansionMode = ALL_POINTERS;
- } else if (mode.equalsIgnoreCase("NON_VOID_ONLY")) {
- primitiveArrayExpansionMode = NON_VOID_ONLY;
- } else if (mode.equalsIgnoreCase("NO_POINTERS")) {
- primitiveArrayExpansionMode = NO_POINTERS;
- } else {
- throw new RuntimeException("Error parsing \"PrimitiveArrayExpansionMode\" command at line " + lineNo +
- " in file \"" + filename
- + "\"; expected NO_POINTERS, NON_VOID_ONLY or ALL_POINTERS");
- }
- } catch (NoSuchElementException e) {
- throw new RuntimeException(
- "Error parsing \"PrimitiveArrayExpansionMode\" command at line " + lineNo +
- " in file \"" + filename + "\"", e);
- }
- }
-
-
-
- /**
- * readVoidPointerExpansionSet:
- * Parses VoidPointerExpansion arguments. Expecting subset of boolean, char, byte,
- * short, int, long,float, double. Example grammar file syntax:
- * VoidPointerExpansion short int float byte double
- * If PrimitiveArrayExpansionMode is set to NON_VOID_ONLY or NO_POINTERS, then
- * the VoidPointerExpansion attribute has no effect, since in that case void
- * pointers are not expanded.
- */
-
- protected void readVoidPointerExpansionSet(StringTokenizer tok, String filename, int lineNo) {
- int number_passes=0;
- boolean finished = false;
-
- voidPointerExpansionToBoolean = false;
- voidPointerExpansionToChar = false;
- voidPointerExpansionToByte = false;
- voidPointerExpansionToShort = false;
- voidPointerExpansionToInt = false;
- voidPointerExpansionToLong = false;
- voidPointerExpansionToFloat = false;
- voidPointerExpansionToDouble = false;
-
- while(!finished) {
- try {
- String mode = tok.nextToken();
- if (mode.equalsIgnoreCase("float")) {
- voidPointerExpansionToFloat = true;
- number_passes++;
- } else if (mode.equalsIgnoreCase("int")) {
- voidPointerExpansionToInt = true;
- number_passes++;
- } else if (mode.equalsIgnoreCase("byte")) {
- voidPointerExpansionToByte = true;
- number_passes++;
- } else if (mode.equalsIgnoreCase("short")) {
- voidPointerExpansionToShort = true;
- number_passes++;
- } else if (mode.equalsIgnoreCase("boolean")) {
- voidPointerExpansionToBoolean = true;
- number_passes++;
- } else if (mode.equalsIgnoreCase("char")) {
- voidPointerExpansionToChar = true;
- number_passes++;
- } else if (mode.equalsIgnoreCase("long")) {
- voidPointerExpansionToLong = true;
- number_passes++;
- } else if (mode.equalsIgnoreCase("double")) {
- voidPointerExpansionToDouble = true;
- number_passes++;
- } else {
- throw new RuntimeException("Error parsing \"VoidPointerExpansion\" command at line " + lineNo +
- " in file \"" + filename +
- "\"; expected some combination of boolean, char, byte, short, int, long, float, double");
- }
- } catch (NoSuchElementException e) {
- if(number_passes == 0) {
- throw new RuntimeException(
- "Error parsing \"VoidPointerExpansion\" command at line " + lineNo +
- " in file \"" + filename + "\"", e);
- }
- finished = true;
- }
- }
- }
-
-
-
- /**
- * When void* arguments in the C function prototypes are encountered, the
- * emitter will try to expand the binding and create Java entry points for
- * all possible array types. If there are 2 or more void* arguments in the C
- * prototype, this directive lets you specify which of those arguments
- * should always be expanded to the same type. <p>
- *
- * For example, given the C prototype:
- * <pre>
- * void FuncName(void *foo, void *bar);
- * </pre>
- *
- * The emitter will normally emit multiple Java entry points:
- * <pre>
- * public abstract void FuncName(boolean[] foo, java.nio.Buffer bar);
- * public abstract void FuncName(boolean[] foo, boolean[] bar);
- * public abstract void FuncName(boolean[] foo, byte[] bar);
- * public abstract void FuncName(boolean[] foo, char[] bar);
- * public abstract void FuncName(boolean[] foo, short[] bar);
- * public abstract void FuncName(boolean[] foo, int[] bar);
- * public abstract void FuncName(boolean[] foo, long[] bar);
- * public abstract void FuncName(boolean[] foo, float[] bar);
- * public abstract void FuncName(boolean[] foo, double[] bar);
- *
- * public abstract void FuncName(byte[] foo, java.nio.Buffer bar);
- * public abstract void FuncName(byte[] foo, boolean[] bar);
- * public abstract void FuncName(byte[] foo, byte[] bar);
- * <...etc for all variants on the second parameter...>
- *
- * public abstract void FuncName(char[] foo, java.nio.Buffer bar);
- * public abstract void FuncName(char[] foo, boolean[] bar);
- * public abstract void FuncName(char[] foo, byte[] bar);
- * <...etc for all variants on the second parameter...>
- * <...and so on for all remaining variants on the first parameter...>
- * </pre>
- *
- * This directive lets you specify that arguments at a particular index
- * should always be expanded to the same type. For example, the directive:
- * <pre>
- * MirrorExpandedBindingArgs FuncName 0 1
- * </pre>
- * will force the first and second arguments in function FuncName to be
- * expanded identically. This would result in the emission of the following
- * entry points only:
- * <pre>
- * public abstract void FuncName(java.nio.Buffer[] foo, java.nio.Buffer bar);
- * public abstract void FuncName(boolean[] foo, boolean[] bar);
- * public abstract void FuncName(byte[] foo, byte[] bar);
- * public abstract void FuncName(char[] foo, char[] bar);
- * public abstract void FuncName(short[] foo, short[] bar);
- * public abstract void FuncName(int[] foo, int[] bar);
- * public abstract void FuncName(long[] foo, long[] bar);
- * public abstract void FuncName(float[] foo, float[] bar);
- * public abstract void FuncName(double[] foo, double[] bar);
- * </pre>
- */
- protected void readMirrorExpandedBindingArgs(StringTokenizer tok, String filename, int lineNo) {
- try {
- String methodName = tok.nextToken();
- ArrayList argIndices = new ArrayList(2);
- while (tok.hasMoreTokens())
- {
- Integer idx = Integer.valueOf(tok.nextToken());
- argIndices.add(idx);
- }
-
- if(argIndices.size() > 1)
- {
- mirroredArgs.put(methodName, argIndices);
- }
- else
- {
- throw new RuntimeException("ERROR: Error parsing \"MirrorExpandedBindingArgs\" command at line " + lineNo +
- " in file \"" + filename + "\": directive requires at least 2 argument indices");
- }
- } catch (NoSuchElementException e) {
- throw new RuntimeException(
- "Error parsing \"MirrorExpandedBindingArgs\" command at line " + lineNo +
- " in file \"" + filename + "\"", e);
- }
- }
-
/**
* When const char* arguments in the C function prototypes are encountered,
* the emitter will normally convert them to <code>byte[]</code>
diff --git a/src/net/java/games/gluegen/JavaEmitter.java b/src/net/java/games/gluegen/JavaEmitter.java
index dad954db2..e260da992 100644
--- a/src/net/java/games/gluegen/JavaEmitter.java
+++ b/src/net/java/games/gluegen/JavaEmitter.java
@@ -300,170 +300,288 @@ public class JavaEmitter implements GlueEmitter {
}
/**
+ * Generates the public emitters for this MethodBinding which will
+ * produce either simply signatures (for the interface class, if
+ * any) or function definitions with or without a body (depending on
+ * whether or not the implementing function can go directly to
+ * native code because it doesn't need any processing of the
+ * outgoing arguments).
+ */
+ protected void generatePublicEmitters(MethodBinding binding,
+ List allEmitters,
+ boolean signatureOnly) {
+ PrintWriter writer = ((signatureOnly || cfg.allStatic()) ? javaWriter() : javaImplWriter());
+
+ if (cfg.manuallyImplement(binding.getName()) && !signatureOnly) {
+ // We only generate signatures for manually-implemented methods;
+ // user provides the implementation
+ return;
+ }
+
+ // It's possible we may not need a body even if signatureOnly is
+ // set to false; for example, if the routine doesn't take any
+ // arrays or buffers as arguments
+ boolean isUnimplemented = cfg.isUnimplemented(binding.getName());
+ boolean needsBody = (isUnimplemented ||
+ (binding.needsNIOWrappingOrUnwrapping() ||
+ binding.signatureUsesJavaPrimitiveArrays()));
+
+ JavaMethodBindingEmitter emitter =
+ new JavaMethodBindingEmitter(binding,
+ writer,
+ cfg.runtimeExceptionType(),
+ !signatureOnly && needsBody,
+ false,
+ cfg.nioDirectOnly(binding.getName()),
+ false,
+ false,
+ false,
+ isUnimplemented);
+ emitter.addModifier(JavaMethodBindingEmitter.PUBLIC);
+ if (cfg.allStatic()) {
+ emitter.addModifier(JavaMethodBindingEmitter.STATIC);
+ }
+ if (!isUnimplemented && !needsBody && !signatureOnly) {
+ emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
+ }
+ emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName()));
+ allEmitters.add(emitter);
+ }
+
+ /**
+ * Generates the private emitters for this MethodBinding. On the
+ * Java side these will simply produce signatures for native
+ * methods. On the C side these will create the emitters which will
+ * write the JNI code to interface to the functions. We need to be
+ * careful to make the signatures all match up and not produce too
+ * many emitters which would lead to compilation errors from
+ * creating duplicated methods / functions.
+ */
+ protected void generatePrivateEmitters(MethodBinding binding,
+ List allEmitters) {
+ if (cfg.manuallyImplement(binding.getName())) {
+ // Don't produce emitters for the implementation class
+ return;
+ }
+
+ // If we already generated a public native entry point for this
+ // method, don't emit another one
+ if (!cfg.isUnimplemented(binding.getName()) &&
+ (binding.needsNIOWrappingOrUnwrapping() ||
+ binding.signatureUsesJavaPrimitiveArrays())) {
+ PrintWriter writer = (cfg.allStatic() ? javaWriter() : javaImplWriter());
+
+ // If the binding uses primitive arrays, we are going to emit
+ // the private native entry point for it along with the version
+ // taking only NIO buffers
+ if (!binding.signatureUsesJavaPrimitiveArrays()) {
+ // (Always) emit the entry point taking only direct buffers
+ JavaMethodBindingEmitter emitter =
+ new JavaMethodBindingEmitter(binding,
+ writer,
+ cfg.runtimeExceptionType(),
+ false,
+ true,
+ cfg.nioDirectOnly(binding.getName()),
+ true,
+ true,
+ false,
+ false);
+ emitter.addModifier(JavaMethodBindingEmitter.PRIVATE);
+ if (cfg.allStatic()) {
+ emitter.addModifier(JavaMethodBindingEmitter.STATIC);
+ }
+ emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
+ emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName()));
+ allEmitters.add(emitter);
+
+ // Optionally emit the entry point taking arrays which handles
+ // both the public entry point taking arrays as well as the
+ // indirect buffer case
+ if (!cfg.nioDirectOnly(binding.getName()) &&
+ binding.signatureCanUseIndirectNIO()) {
+ emitter =
+ new JavaMethodBindingEmitter(binding,
+ writer,
+ cfg.runtimeExceptionType(),
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false);
+
+ emitter.addModifier(JavaMethodBindingEmitter.PRIVATE);
+ if (cfg.allStatic()) {
+ emitter.addModifier(JavaMethodBindingEmitter.STATIC);
+ }
+ emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
+ emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName()));
+ allEmitters.add(emitter);
+ }
+ }
+ }
+
+ // Now generate the C emitter(s). We need to produce one for every
+ // Java native entry point (public or private). The only
+ // situations where we don't produce one are (a) when the method
+ // is unimplemented, and (b) when the signature contains primitive
+ // arrays, since the latter is handled by the method binding
+ // variant taking only NIO Buffers.
+ if (!cfg.isUnimplemented(binding.getName()) &&
+ !binding.signatureUsesJavaPrimitiveArrays()) {
+ // See whether we need an expression to help calculate the
+ // length of any return type
+ MessageFormat returnValueCapacityFormat = null;
+ MessageFormat returnValueLengthFormat = null;
+ JavaType javaReturnType = binding.getJavaReturnType();
+ if (javaReturnType.isNIOBuffer() ||
+ javaReturnType.isCompoundTypeWrapper()) {
+ // See whether capacity has been specified
+ String capacity = cfg.returnValueCapacity(binding.getName());
+ if (capacity != null) {
+ returnValueCapacityFormat = new MessageFormat(capacity);
+ }
+ } else if (javaReturnType.isArray() ||
+ javaReturnType.isArrayOfCompoundTypeWrappers()) {
+ // NOTE: adding a check here because the CMethodBindingEmitter
+ // also doesn't yet handle returning scalar arrays. In order
+ // to implement this, return the type as a Buffer instead
+ // (i.e., IntBuffer, FloatBuffer) and add code as necessary.
+ if (javaReturnType.isPrimitiveArray()) {
+ throw new RuntimeException("Primitive array return types not yet supported");
+ }
+
+ // See whether length has been specified
+ String len = cfg.returnValueLength(binding.getName());
+ if (len != null) {
+ returnValueLengthFormat = new MessageFormat(len);
+ }
+ }
+
+ CMethodBindingEmitter cEmitter =
+ new CMethodBindingEmitter(binding,
+ cWriter(),
+ cfg.implPackageName(),
+ cfg.implClassName(),
+ true, /* NOTE: we always disambiguate with a suffix now, so this is optional */
+ cfg.allStatic(),
+ binding.needsNIOWrappingOrUnwrapping(),
+ false);
+ if (returnValueCapacityFormat != null) {
+ cEmitter.setReturnValueCapacityExpression(returnValueCapacityFormat);
+ }
+ if (returnValueLengthFormat != null) {
+ cEmitter.setReturnValueLengthExpression(returnValueLengthFormat);
+ }
+ cEmitter.setTemporaryCVariableDeclarations(cfg.temporaryCVariableDeclarations(binding.getName()));
+ cEmitter.setTemporaryCVariableAssignments(cfg.temporaryCVariableAssignments(binding.getName()));
+ allEmitters.add(cEmitter);
+
+ // Now see if we have to emit another entry point to handle the
+ // indirect buffer and array case
+ if (binding.argumentsUseNIO() &&
+ binding.signatureCanUseIndirectNIO() &&
+ !cfg.nioDirectOnly(binding.getName())) {
+ cEmitter =
+ new CMethodBindingEmitter(binding,
+ cWriter(),
+ cfg.implPackageName(),
+ cfg.implClassName(),
+ true, /* NOTE: we always disambiguate with a suffix now, so this is optional */
+ cfg.allStatic(),
+ binding.needsNIOWrappingOrUnwrapping(),
+ true);
+ if (returnValueCapacityFormat != null) {
+ cEmitter.setReturnValueCapacityExpression(returnValueCapacityFormat);
+ }
+ if (returnValueLengthFormat != null) {
+ cEmitter.setReturnValueLengthExpression(returnValueLengthFormat);
+ }
+ cEmitter.setTemporaryCVariableDeclarations(cfg.temporaryCVariableDeclarations(binding.getName()));
+ cEmitter.setTemporaryCVariableAssignments(cfg.temporaryCVariableAssignments(binding.getName()));
+ allEmitters.add(cEmitter);
+ }
+ }
+ }
+
+ /**
* Generate all appropriate Java bindings for the specified C function
* symbols.
*/
protected List generateMethodBindingEmitters(FunctionSymbol sym) throws Exception {
- ArrayList/*<FunctionEmitter>*/ allEmitters = new ArrayList(1);
+ ArrayList/*<FunctionEmitter>*/ allEmitters = new ArrayList();
try {
// Get Java binding for the function
MethodBinding mb = bindFunction(sym, null, null);
- // Expand all void* arguments
+ // JavaTypes representing C pointers in the initial
+ // MethodBinding have not been lowered yet to concrete types
List bindings = expandMethodBinding(mb);
- boolean overloaded = (bindings.size() > 1);
- if (overloaded) {
- // resize ahead of time for speed
- allEmitters.ensureCapacity(bindings.size());
- }
-
- // List of the indices of the arguments in this function that should be
- // expanded to the same type when binding functions with multiple void*
- // arguments
- List mirrorIdxs = cfg.mirroredArgs(sym.getName());
for (Iterator iter = bindings.iterator(); iter.hasNext(); ) {
MethodBinding binding = (MethodBinding) iter.next();
- // Honor the MirrorExpandedBindingArgs directive in .cfg files
- if (mirrorIdxs != null) {
- assert(mirrorIdxs.size() >= 2); // sanity check.
- boolean typesMatch = true;
- int argIndex = ((Integer)mirrorIdxs.get(0)).intValue();
- JavaType leftArgType = binding.getJavaArgumentType(argIndex);
- for (int i = 1; i < mirrorIdxs.size(); ++i) {
- argIndex = ((Integer)mirrorIdxs.get(i)).intValue();
- JavaType rightArgType = binding.getJavaArgumentType(argIndex);
- if (!(leftArgType.equals(rightArgType))) {
- typesMatch = false;
- break;
- }
- leftArgType = rightArgType;
- }
- // Don't emit the binding if the specified args aren't the same type
- if (!typesMatch) { continue; } // skip this binding
- }
-
- // Try to create an NIOBuffer variant for this expanded binding. If
- // it's the same as the original binding, then we'll be able to emit
- // the binding like any normal binding because no special binding
- // generation (wrapper methods, etc) will be necessary.
- MethodBinding specialBinding = binding.createNIOBufferVariant();
-
-
if (cfg.allStatic() && binding.hasContainingType()) {
// This should not currently happen since structs are emitted using a different mechanism
throw new IllegalArgumentException("Cannot create binding in AllStatic mode because method has containing type: \"" +
binding + "\"");
}
- boolean isUnimplemented = cfg.isUnimplemented(binding.getName());
- JavaMethodBindingImplEmitter entryPoint=null;
-
- if (cfg.emitImpl()) {
- // Generate the emitter for the method which may do conversion
- // from type wrappers to NIO Buffers or which may call the
- // underlying function directly
-
- boolean arrayImplMethod = false;
- if(binding.signatureUsesPrimitiveArrays()) {
- //overloaded = true;
- arrayImplMethod = true;
- }
-
- entryPoint = new JavaMethodBindingImplEmitter(binding,
- (cfg.allStatic() ? javaWriter() : javaImplWriter()),
- cfg.runtimeExceptionType(),
- isUnimplemented,
- arrayImplMethod);
- entryPoint.addModifier(JavaMethodBindingEmitter.PUBLIC);
- if (cfg.allStatic()) {
- entryPoint.addModifier(JavaMethodBindingEmitter.STATIC);
- }
- if (!isUnimplemented && !bindingNeedsBody(binding)) {
- entryPoint.addModifier(JavaMethodBindingEmitter.NATIVE);
- }
- entryPoint.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName()));
- allEmitters.add(entryPoint);
- }
+ // The structure of the generated glue code looks something like this:
+ // Simple method (no arrays, void pointers, etc.):
+ // Interface class:
+ // public void fooMethod();
+ // Implementation class:
+ // public native void fooMethod();
+ //
+ // Method taking void* argument:
+ // Interface class:
+ // public void fooMethod(Buffer arg);
+ // Implementation class:
+ // public void fooMethod(Buffer arg) {
+ // ... bounds checks, etc. ...
+ // if (arg.isDirect()) {
+ // fooMethod0(arg, computeDirectBufferByteOffset(arg));
+ // } else {
+ // fooMethod1(getIndirectBufferArray(arg), computeIndirectBufferByteOffset(arg));
+ // }
+ // }
+ // private native void fooMethod0(Object arg, int arg_byte_offset);
+ // private native void fooMethod1(Object arg, int arg_byte_offset);
+ //
+ // Method taking primitive array argument:
+ // Interface class:
+ // public void fooMethod(int[] arg, int arg_offset);
+ // public void fooMethod(IntBuffer arg);
+ // Implementing class:
+ // public void fooMethod(int[] arg, int arg_offset) {
+ // ... range checks, etc. ...
+ // fooMethod1(arg, SIZEOF_INT * arg_offset);
+ // }
+ // public void fooMethod(IntBuffer arg) {
+ // ... bounds checks, etc. ...
+ // if (arg.isDirect()) {
+ // fooMethod0(arg, computeDirectBufferByteOffset(arg));
+ // } else {
+ // fooMethod1(getIndirectBufferArray(arg), computeIndirectBufferByteOffset(arg));
+ // }
+ // }
+ // private native void fooMethod0(Object arg, int arg_byte_offset);
+ // private native void fooMethod1(Object arg, int arg_byte_offset);
+ //
+ // Note in particular that the public entry point taking an
+ // array is merely a special case of the indirect buffer case.
if (cfg.emitInterface()) {
- // Generate an emitter that will emit just the interface to the function
- JavaMethodBindingEmitter entryPointInterface =
- new JavaMethodBindingEmitter(binding, javaWriter(), cfg.runtimeExceptionType());
- entryPointInterface.addModifier(JavaMethodBindingEmitter.PUBLIC);
- entryPointInterface.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName()));
- allEmitters.add(entryPointInterface);
+ generatePublicEmitters(binding, allEmitters, true);
}
-
if (cfg.emitImpl()) {
- // If the user has stated that the function will be
- // manually implemented, then don't auto-generate a function body.
- if (!cfg.manuallyImplement(sym.getName()) && !isUnimplemented) {
- // need to check if should create CMethodBindingImplEmitter instead of just
- // CMethodBindingEmitter. Basically adds a "0" to JNI method name
- boolean arrayImplMethod = false;
-
- if (bindingNeedsBody(binding)) {
- // Generate the method which calls the underlying C function
- // after unboxing has occurred
- PrintWriter output = cfg.allStatic() ? javaWriter() : javaImplWriter();
- if(binding.signatureUsesPrimitiveArrays()) {
- arrayImplMethod = true;
- }
- JavaMethodBindingEmitter wrappedEntryPoint =
- new JavaMethodBindingEmitter(specialBinding, output, cfg.runtimeExceptionType(), true,
- arrayImplMethod);
- wrappedEntryPoint.addModifier(JavaMethodBindingEmitter.PRIVATE);
- wrappedEntryPoint.addModifier(JavaMethodBindingEmitter.STATIC); // Doesn't really matter
- wrappedEntryPoint.addModifier(JavaMethodBindingEmitter.NATIVE);
- allEmitters.add(wrappedEntryPoint);
-
- String bindingName = specialBinding.getName();
- if(binding != specialBinding && bindingName.contains("gl") && !bindingName.contains("glX")
- && !bindingName.contains("wgl") && !bindingName.contains("CGL")) {
- JavaMethodBindingEmitter wrappedEntryPoint2 =
- new JavaMethodBindingEmitter(specialBinding, output, cfg.runtimeExceptionType(),
- true, arrayImplMethod);
- wrappedEntryPoint2.addModifier(JavaMethodBindingEmitter.PRIVATE);
- wrappedEntryPoint2.addModifier(JavaMethodBindingEmitter.STATIC); // Doesn't really matter
- wrappedEntryPoint2.addModifier(JavaMethodBindingEmitter.NATIVE);
-
- entryPoint.setGenerateIndirectBufferInterface(true);
- wrappedEntryPoint2.setIndirectBufferInterface(true);
- allEmitters.add(wrappedEntryPoint2);
- }
-
- }
-
- CMethodBindingEmitter cEmitter =
- makeCEmitter(specialBinding,
- overloaded,
- (binding != specialBinding),
- arrayImplMethod,
- cfg.implPackageName(), cfg.implClassName(),
- cWriter());
- allEmitters.add(cEmitter);
-
- String bindingName = specialBinding.getName();
- if(binding != specialBinding && bindingName.contains("gl") && !bindingName.contains("glX")
- && !bindingName.contains("wgl") && !bindingName.contains("CGL") ) {
-
- CMethodBindingEmitter cEmitter2 =
- makeCEmitter(specialBinding,
- //overloaded,
- true,
- true,
- arrayImplMethod,
- cfg.implPackageName(), cfg.implClassName(),
- cWriter());
- cEmitter2.setIndirectBufferInterface(true);
- allEmitters.add(cEmitter2);
- }
-
- }
+ generatePublicEmitters(binding, allEmitters, false);
+ generatePrivateEmitters(binding, allEmitters);
}
} // end iteration over expanded bindings
} catch (Exception e) {
@@ -615,29 +733,49 @@ public class JavaEmitter implements GlueEmitter {
FunctionSymbol funcSym = new FunctionSymbol(field.getName(), funcType);
MethodBinding binding = bindFunction(funcSym, containingType, containingCType);
binding.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis
- MethodBinding specialBinding = binding.createNIOBufferVariant();
writer.println();
- JavaMethodBindingEmitter entryPoint = new JavaMethodBindingImplEmitter(binding, writer, cfg.runtimeExceptionType());
- entryPoint.addModifier(JavaMethodBindingEmitter.PUBLIC);
- if (!bindingNeedsBody(binding) && !binding.hasContainingType()) {
- entryPoint.addModifier(JavaMethodBindingEmitter.NATIVE);
- }
- entryPoint.emit();
-
- JavaMethodBindingEmitter wrappedEntryPoint = new JavaMethodBindingEmitter(specialBinding, writer, cfg.runtimeExceptionType(), true, false);
- wrappedEntryPoint.addModifier(JavaMethodBindingEmitter.PRIVATE);
- wrappedEntryPoint.addModifier(JavaMethodBindingEmitter.NATIVE);
- wrappedEntryPoint.emit();
-
+ // Emit public Java entry point for calling this function pointer
+ JavaMethodBindingEmitter emitter =
+ new JavaMethodBindingEmitter(binding,
+ writer,
+ cfg.runtimeExceptionType(),
+ true,
+ false,
+ true, // FIXME: should unify this with the general emission code
+ false,
+ false, // FIXME: should unify this with the general emission code
+ false, // FIXME: should unify this with the general emission code
+ false);
+ emitter.addModifier(JavaMethodBindingEmitter.PUBLIC);
+ emitter.emit();
+
+ // Emit private native Java entry point for calling this function pointer
+ emitter =
+ new JavaMethodBindingEmitter(binding,
+ writer,
+ cfg.runtimeExceptionType(),
+ false,
+ true,
+ true, // FIXME: should unify this with the general emission code
+ true,
+ true, // FIXME: should unify this with the general emission code
+ false, // FIXME: should unify this with the general emission code
+ false);
+ emitter.addModifier(JavaMethodBindingEmitter.PRIVATE);
+ emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
+ emitter.emit();
+
+ // Emit (private) C entry point for calling this function pointer
CMethodBindingEmitter cEmitter =
- makeCEmitter(specialBinding,
- false, // overloaded
- true, // doing NIO impl routine?
- false, // array impl method ?
- structClassPkg,
- containingTypeName,
- cWriter);
+ new CMethodBindingEmitter(binding,
+ cWriter,
+ structClassPkg,
+ containingTypeName,
+ true, // FIXME: this is optional at this point
+ false,
+ true,
+ false); // FIXME: should unify this with the general emission code
cEmitter.emit();
} catch (Exception e) {
System.err.println("While processing field " + field + " of type " + name + ":");
@@ -726,59 +864,6 @@ public class JavaEmitter implements GlueEmitter {
// Internals only below this point
//
- protected boolean bindingNeedsBody(MethodBinding binding) {
- // We need to perform NIO checks and conversions and array length
- // checks
- return binding.signatureUsesNIO() || binding.signatureUsesCArrays() || binding.signatureUsesPrimitiveArrays();
- }
-
- private CMethodBindingEmitter makeCEmitter(MethodBinding binding,
- boolean overloaded,
- boolean doingNIOImplRoutine,
- boolean doingArrayImplRoutine,
- String bindingJavaPackageName,
- String bindingJavaClassName,
- PrintWriter output) {
- MessageFormat returnValueCapacityFormat = null;
- MessageFormat returnValueLengthFormat = null;
- JavaType javaReturnType = binding.getJavaReturnType();
- if (javaReturnType.isNIOBuffer()) {
- // See whether capacity has been specified
- String capacity = cfg.returnValueCapacity(binding.getName());
- if (capacity != null) {
- returnValueCapacityFormat = new MessageFormat(capacity);
- }
- } else if (javaReturnType.isArray()) {
- // See whether length has been specified
- String len = cfg.returnValueLength(binding.getName());
- if (len != null) {
- returnValueLengthFormat = new MessageFormat(len);
- }
- }
- CMethodBindingEmitter cEmitter;
- if (doingNIOImplRoutine || doingArrayImplRoutine) {
- cEmitter = new CMethodBindingImplEmitter(binding, overloaded,
- doingArrayImplRoutine,
- bindingJavaPackageName,
- bindingJavaClassName,
- cfg.allStatic(), output);
- } else {
- cEmitter = new CMethodBindingEmitter(binding, overloaded,
- bindingJavaPackageName,
- bindingJavaClassName,
- cfg.allStatic(), output);
- }
- if (returnValueCapacityFormat != null) {
- cEmitter.setReturnValueCapacityExpression(returnValueCapacityFormat);
- }
- if (returnValueLengthFormat != null) {
- cEmitter.setReturnValueLengthExpression(returnValueLengthFormat);
- }
- cEmitter.setTemporaryCVariableDeclarations(cfg.temporaryCVariableDeclarations(binding.getName()));
- cEmitter.setTemporaryCVariableAssignments(cfg.temporaryCVariableAssignments(binding.getName()));
- return cEmitter;
- }
-
private JavaType typeToJavaType(Type cType, boolean outgoingArgument) {
// Recognize JNIEnv* case up front
PointerType opt = cType.asPointer();
@@ -1233,6 +1318,12 @@ public class JavaEmitter implements GlueEmitter {
return JavaType.createForClass(c);
}
+ /** Maps the C types in the specified function to Java types through
+ the MethodBinding interface. Note that the JavaTypes in the
+ returned MethodBinding are "intermediate" JavaTypes (some
+ potentially representing C pointers rather than true Java types)
+ and must be lowered to concrete Java types before creating
+ emitters for them. */
private MethodBinding bindFunction(FunctionSymbol sym,
JavaType containingType,
Type containingCType) {
@@ -1292,207 +1383,119 @@ public class JavaEmitter implements GlueEmitter {
return binding;
}
- // Expands a MethodBinding containing C primitive pointer types into
- // multiple variants taking Java primitive arrays and NIO buffers, subject
- // to the per-function "NIO only" rule in the configuration file
- private List/*<MethodBinding>*/ expandMethodBinding(MethodBinding binding) {
- List result = new ArrayList();
- result.add(binding);
- int i = 0;
- while (i < result.size()) {
- MethodBinding mb = (MethodBinding) result.get(i);
- boolean shouldRemoveCurrent = false;
- for (int j = 0; j < mb.getNumArguments(); j++) {
- JavaType t = mb.getJavaArgumentType(j);
- if (t.isCPrimitivePointerType()) {
- // Remove original from list
- shouldRemoveCurrent = true;
- MethodBinding variant = null;
-
- // Non-NIO variants for non-void C primitive pointer types
- if (!cfg.nioDirectOnly(mb.getCSymbol().getName()) && !t.isCVoidPointerType()
- && !cfg.isPrimArrayExpModeNoPtrs()) {
- if (t.isCCharPointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.byteArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (t.isCShortPointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.shortArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (t.isCInt32PointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.intArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (t.isCInt64PointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.longArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (t.isCFloatPointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.floatArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (t.isCDoublePointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.doubleArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- }
-
- // Non-NIO variants for void* C primitive pointer type
- if (!cfg.nioDirectOnly(mb.getCSymbol().getName()) && t.isCVoidPointerType()
- && cfg.isPrimArrayExpModeAllPtrs()) {
- if (cfg.voidPointerExpansionToBoolean()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.booleanArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (cfg.voidPointerExpansionToChar()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.charArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (cfg.voidPointerExpansionToByte()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.byteArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (cfg.voidPointerExpansionToShort()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.shortArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (cfg.voidPointerExpansionToInt()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.intArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (cfg.voidPointerExpansionToLong()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.longArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (cfg.voidPointerExpansionToFloat()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.floatArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- if (cfg.voidPointerExpansionToDouble()) {
- variant = mb.createCPrimitivePointerVariant(j, javaType(ArrayTypes.doubleArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
+ private MethodBinding lowerMethodBindingPointerTypes(MethodBinding inputBinding,
+ boolean convertToArrays,
+ boolean[] canProduceArrayVariant) {
+ MethodBinding result = inputBinding;
+ boolean arrayPossible = false;
+
+ for (int i = 0; i < inputBinding.getNumArguments(); i++) {
+ JavaType t = inputBinding.getJavaArgumentType(i);
+ if (t.isCPrimitivePointerType()) {
+ if (t.isCVoidPointerType()) {
+ // These are always bound to java.nio.Buffer
+ result = result.replaceJavaArgumentType(i, JavaType.forNIOBufferClass());
+ } else if (t.isCCharPointerType()) {
+ arrayPossible = true;
+ if (convertToArrays) {
+ result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.byteArrayClass));
+ } else {
+ result = result.replaceJavaArgumentType(i, JavaType.forNIOByteBufferClass());
}
-
-
- // NIO variant for void* C primitive pointer type
- if (!cfg.noNio(mb.getCSymbol().getName())) {
- if (t.isCVoidPointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, JavaType.forNIOBufferClass());
- if (! result.contains(variant)) result.add(variant);
- }
+ } else if (t.isCShortPointerType()) {
+ arrayPossible = true;
+ if (convertToArrays) {
+ result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.shortArrayClass));
+ } else {
+ result = result.replaceJavaArgumentType(i, JavaType.forNIOShortBufferClass());
}
-
-
- // NIO variants for non-void* C primitive pointer types
- if ((cfg.nioMode() == JavaConfiguration.NIO_MODE_ALL_POINTERS &&
- !cfg.noNio(mb.getCSymbol().getName())) ||
- (cfg.nioMode() == JavaConfiguration.NIO_MODE_VOID_ONLY &&
- cfg.forcedNio(mb.getCSymbol().getName()))) {
- if (t.isCCharPointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, JavaType.forNIOByteBufferClass());
- if (! result.contains(variant)) result.add(variant);
- }
-
- if (t.isCShortPointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, JavaType.forNIOShortBufferClass());
- if (! result.contains(variant)) result.add(variant);
- }
-
- if (t.isCInt32PointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, JavaType.forNIOIntBufferClass());
- if (! result.contains(variant)) result.add(variant);
- }
-
- if (t.isCInt64PointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, JavaType.forNIOLongBufferClass());
- if (! result.contains(variant)) result.add(variant);
- }
-
- if (t.isCFloatPointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, JavaType.forNIOFloatBufferClass());
- if (! result.contains(variant)) result.add(variant);
- }
-
- if (t.isCDoublePointerType()) {
- variant = mb.createCPrimitivePointerVariant(j, JavaType.forNIODoubleBufferClass());
- if (! result.contains(variant)) result.add(variant);
- }
+ } else if (t.isCInt32PointerType()) {
+ arrayPossible = true;
+ if (convertToArrays) {
+ result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.intArrayClass));
+ } else {
+ result = result.replaceJavaArgumentType(i, JavaType.forNIOIntBufferClass());
+ }
+ } else if (t.isCInt64PointerType()) {
+ arrayPossible = true;
+ if (convertToArrays) {
+ result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.longArrayClass));
+ } else {
+ result = result.replaceJavaArgumentType(i, JavaType.forNIOLongBufferClass());
+ }
+ } else if (t.isCFloatPointerType()) {
+ arrayPossible = true;
+ if (convertToArrays) {
+ result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.floatArrayClass));
+ } else {
+ result = result.replaceJavaArgumentType(i, JavaType.forNIOFloatBufferClass());
+ }
+ } else if (t.isCDoublePointerType()) {
+ arrayPossible = true;
+ if (convertToArrays) {
+ result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.doubleArrayClass));
+ } else {
+ result = result.replaceJavaArgumentType(i, JavaType.forNIODoubleBufferClass());
}
+ } else {
+ throw new RuntimeException("Unknown C pointer type " + t);
}
}
+ }
- if (mb.getJavaReturnType().isCPrimitivePointerType()) {
- MethodBinding variant = null;
- if (mb.getJavaReturnType().isCVoidPointerType()) {
- variant = mb.createCPrimitivePointerVariant(-1, JavaType.forNIOByteBufferClass());
- if (! result.contains(variant)) result.add(variant);
- } else if (mb.getJavaReturnType().isCCharPointerType()) {
- variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.byteArrayClass));
- if (! result.contains(variant)) result.add(variant);
- } else if (mb.getJavaReturnType().isCShortPointerType()) {
- variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.shortArrayClass));
- if (! result.contains(variant)) result.add(variant);
- } else if (mb.getJavaReturnType().isCInt32PointerType()) {
- variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.intArrayClass));
- if (! result.contains(variant)) result.add(variant);
- } else if (mb.getJavaReturnType().isCInt64PointerType()) {
- variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.longArrayClass));
- if (! result.contains(variant)) result.add(variant);
- } else if (mb.getJavaReturnType().isCFloatPointerType()) {
- variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.floatArrayClass));
- if (! result.contains(variant)) result.add(variant);
- } else if (mb.getJavaReturnType().isCDoublePointerType()) {
- variant = mb.createCPrimitivePointerVariant(-1, javaType(ArrayTypes.doubleArrayClass));
- if (! result.contains(variant)) result.add(variant);
- }
- shouldRemoveCurrent = true;
- }
- if (shouldRemoveCurrent) {
- result.remove(i);
- --i;
+ // Always return primitive pointer types as NIO buffers
+ JavaType t = result.getJavaReturnType();
+ if (t.isCPrimitivePointerType()) {
+ if (t.isCVoidPointerType()) {
+ result = result.replaceJavaArgumentType(-1, JavaType.forNIOByteBufferClass());
+ } else if (t.isCCharPointerType()) {
+ result = result.replaceJavaArgumentType(-1, JavaType.forNIOByteBufferClass());
+ } else if (t.isCShortPointerType()) {
+ result = result.replaceJavaArgumentType(-1, JavaType.forNIOShortBufferClass());
+ } else if (t.isCInt32PointerType()) {
+ result = result.replaceJavaArgumentType(-1, JavaType.forNIOIntBufferClass());
+ } else if (t.isCInt64PointerType()) {
+ result = result.replaceJavaArgumentType(-1, JavaType.forNIOLongBufferClass());
+ } else if (t.isCFloatPointerType()) {
+ result = result.replaceJavaArgumentType(-1, JavaType.forNIOFloatBufferClass());
+ } else if (t.isCDoublePointerType()) {
+ result = result.replaceJavaArgumentType(-1, JavaType.forNIODoubleBufferClass());
+ } else {
+ throw new RuntimeException("Unknown C pointer type " + t);
}
- ++i;
- }
-
- // Honor the flattenNIOVariants directive in the configuration file
- // FlattenNIOVariants <boolean>
- // true: If there are multiple arguments in a method signature that map
- // to NIO buffer, do not pair an NIO buffer argument with a primitive
- // array argument
- // false: Allow cross-pairing of nio and primitive array arguments in a
- // single method signature.
- if (cfg.flattenNIOVariants()) {
- i = 0;
- while (i < result.size()) {
- boolean shouldRemoveCurrent = false;
- MethodBinding mb = (MethodBinding) result.get(i);
- for (int j = 0; j < binding.getNumArguments() && !shouldRemoveCurrent; j++) {
- JavaType t1 = binding.getJavaArgumentType(j);
- if (t1.isCPrimitivePointerType() && !t1.isCVoidPointerType()) {
- for (int k = j + 1; k < binding.getNumArguments() && !shouldRemoveCurrent; k++) {
- JavaType t2 = binding.getJavaArgumentType(k);
- if (t2.isCPrimitivePointerType() && !t2.isCVoidPointerType()) {
- // The "NIO-ness" of the converted arguments in the
- // new binding must match
- JavaType nt1 = mb.getJavaArgumentType(j);
- JavaType nt2 = mb.getJavaArgumentType(k);
- if (nt1.isNIOBuffer() != nt2.isNIOBuffer()) {
- shouldRemoveCurrent = true;
- }
- }
- }
- }
- }
- if (shouldRemoveCurrent) {
- result.remove(i);
- --i;
- }
+ }
+
+ if (canProduceArrayVariant != null) {
+ canProduceArrayVariant[0] = arrayPossible;
+ }
- ++i;
+ return result;
+ }
+
+ // Expands a MethodBinding containing C primitive pointer types into
+ // multiple variants taking Java primitive arrays and NIO buffers, subject
+ // to the per-function "NIO only" rule in the configuration file
+ private List/*<MethodBinding>*/ expandMethodBinding(MethodBinding binding) {
+ List result = new ArrayList();
+ // Indicates whether it is possible to produce an array variant
+ // Prevents e.g. char* -> String conversions from emitting two entry points
+ boolean[] canProduceArrayVariant = new boolean[1];
+
+ if (binding.signatureUsesCPrimitivePointers() ||
+ binding.signatureUsesCVoidPointers() ||
+ binding.signatureUsesCArrays()) {
+ result.add(lowerMethodBindingPointerTypes(binding, false, canProduceArrayVariant));
+
+ // FIXME: should add new configuration flag for this
+ if (canProduceArrayVariant[0] &&
+ (binding.signatureUsesCPrimitivePointers() ||
+ binding.signatureUsesCArrays()) &&
+ !cfg.nioDirectOnly(binding.getName())) {
+ result.add(lowerMethodBindingPointerTypes(binding, true, null));
}
+ } else {
+ result.add(binding);
}
return result;
diff --git a/src/net/java/games/gluegen/JavaMethodBindingEmitter.java b/src/net/java/games/gluegen/JavaMethodBindingEmitter.java
index 1d227dfc9..8c5cd2caf 100644
--- a/src/net/java/games/gluegen/JavaMethodBindingEmitter.java
+++ b/src/net/java/games/gluegen/JavaMethodBindingEmitter.java
@@ -39,8 +39,9 @@
package net.java.games.gluegen;
-import java.util.*;
import java.io.*;
+import java.util.*;
+import java.text.MessageFormat;
import net.java.games.gluegen.cgram.types.*;
import net.java.games.gluegen.cgram.*;
@@ -58,20 +59,22 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
public static final EmissionModifier NATIVE = new EmissionModifier("native");
public static final EmissionModifier SYNCHRONIZED = new EmissionModifier("synchronized");
- protected static final CommentEmitter defaultJavaCommentEmitter = new DefaultCommentEmitter();
- protected static final CommentEmitter defaultInterfaceCommentEmitter =
+ protected final CommentEmitter defaultJavaCommentEmitter = new DefaultCommentEmitter();
+ protected final CommentEmitter defaultInterfaceCommentEmitter =
new InterfaceCommentEmitter();
// Exception type raised in the generated code if runtime checks fail
private String runtimeExceptionType;
- protected MethodBinding binding;
+ protected boolean emitBody;
+ protected boolean eraseBufferAndArrayTypes;
+ protected boolean directNIOOnly;
protected boolean forImplementingMethodCall;
- protected boolean forArrayImplementingMethodCall = false;
-
- protected boolean prefixedMethod = false;
+ protected boolean forDirectBufferImplementation;
+ protected boolean forIndirectBufferAndArrayImplementation;
+ protected boolean isUnimplemented;
- protected boolean indirectBufferInterface = false;
+ protected MethodBinding binding;
// A non-null value indicates that rather than returning a compound
// type accessor we are returning an array of such accessors; this
@@ -80,26 +83,45 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
// number of elements of the returned array.
private String returnedArrayLengthExpression;
- public JavaMethodBindingEmitter(MethodBinding binding, PrintWriter output, String runtimeExceptionType)
- {
- this(binding, output, runtimeExceptionType, false, false);
- }
-
- public JavaMethodBindingEmitter(MethodBinding binding, PrintWriter output, String runtimeExceptionType, boolean forImplementingMethodCall, boolean forArrayImplementingMethodCall)
+ public JavaMethodBindingEmitter(MethodBinding binding,
+ PrintWriter output,
+ String runtimeExceptionType,
+ boolean emitBody,
+ boolean eraseBufferAndArrayTypes,
+ boolean directNIOOnly,
+ boolean forImplementingMethodCall,
+ boolean forDirectBufferImplementation,
+ boolean forIndirectBufferAndArrayImplementation,
+ boolean isUnimplemented)
{
super(output);
this.binding = binding;
- this.forImplementingMethodCall = forImplementingMethodCall;
- this.forArrayImplementingMethodCall = forArrayImplementingMethodCall;
this.runtimeExceptionType = runtimeExceptionType;
- setCommentEmitter(defaultInterfaceCommentEmitter);
+ this.emitBody = emitBody;
+ this.eraseBufferAndArrayTypes = eraseBufferAndArrayTypes;
+ this.directNIOOnly = directNIOOnly;
+ this.forImplementingMethodCall = forImplementingMethodCall;
+ this.forDirectBufferImplementation = forDirectBufferImplementation;
+ this.forIndirectBufferAndArrayImplementation = forIndirectBufferAndArrayImplementation;
+ this.isUnimplemented = isUnimplemented;
+ if (forImplementingMethodCall) {
+ setCommentEmitter(defaultJavaCommentEmitter);
+ } else {
+ setCommentEmitter(defaultInterfaceCommentEmitter);
+ }
}
public JavaMethodBindingEmitter(JavaMethodBindingEmitter arg) {
super(arg);
- runtimeExceptionType = arg.runtimeExceptionType;
binding = arg.binding;
+ runtimeExceptionType = arg.runtimeExceptionType;
+ emitBody = arg.emitBody;
+ eraseBufferAndArrayTypes = arg.eraseBufferAndArrayTypes;
+ directNIOOnly = arg.directNIOOnly;
forImplementingMethodCall = arg.forImplementingMethodCall;
+ forDirectBufferImplementation = arg.forDirectBufferImplementation;
+ forIndirectBufferAndArrayImplementation = arg.forIndirectBufferAndArrayImplementation;
+ isUnimplemented = arg.isUnimplemented;
returnedArrayLengthExpression = arg.returnedArrayLengthExpression;
}
@@ -111,16 +133,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
return binding.getName();
}
- public boolean isIndirectBufferInterface() {
- return indirectBufferInterface;
- }
-
-
- public void setIndirectBufferInterface(boolean indirect) {
- indirectBufferInterface = indirect;
- }
-
-
/** The type of exception (must subclass
<code>java.lang.RuntimeException</code>) raised if runtime
checks fail in the generated code. */
@@ -139,23 +151,78 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
returnedArrayLengthExpression = expr;
}
+ /** Indicates whether this emitter will print only a signature, or
+ whether it will emit Java code for the body of the method as
+ well. */
+ public boolean signatureOnly() {
+ return !emitBody;
+ }
+
+ /** Accessor for subclasses. */
+ public void setEmitBody(boolean emitBody) {
+ this.emitBody = emitBody;
+ }
+
+ /** Accessor for subclasses. */
+ public void setEraseBufferAndArrayTypes(boolean erase) {
+ this.eraseBufferAndArrayTypes = erase;
+ }
+
+ /** Accessor for subclasses. */
+ public void setForImplementingMethodCall(boolean impl) {
+ this.forImplementingMethodCall = impl;
+ }
+
protected void emitReturnType(PrintWriter writer)
{
writer.print(getReturnTypeString(false));
}
+ protected String erasedTypeString(JavaType type, boolean skipBuffers) {
+ if (eraseBufferAndArrayTypes) {
+ if (type.isNIOBuffer() ||
+ type.isPrimitiveArray()) {
+ if (!skipBuffers) {
+ // Direct buffers and arrays sent down as Object (but
+ // returned as e.g. ByteBuffer)
+ return "Object";
+ }
+ } else if (type.isCompoundTypeWrapper()) {
+ // Compound type wrappers are unwrapped to ByteBuffer
+ return "java.nio.ByteBuffer";
+ } else if (type.isArrayOfCompoundTypeWrappers()) {
+ return "java.nio.ByteBuffer";
+ }
+ }
+ return type.getName();
+ }
+
protected String getReturnTypeString(boolean skipArray) {
- if (skipArray || (getReturnedArrayLengthExpression() == null &&
- !binding.getJavaReturnType().isArrayOfCompoundTypeWrappers())) {
- return binding.getJavaReturnType().getName();
+ // The first arm of the "if" clause is used by the glue code
+ // generation for arrays of compound type wrappers
+ if (skipArray ||
+ // The following arm is used by most other kinds of return types
+ (getReturnedArrayLengthExpression() == null &&
+ !binding.getJavaReturnType().isArrayOfCompoundTypeWrappers()) ||
+ // The following arm is used specifically to get the splitting up
+ // of one returned ByteBuffer into an array of compound type
+ // wrappers to work (e.g., XGetVisualInfo)
+ (eraseBufferAndArrayTypes &&
+ binding.getJavaReturnType().isCompoundTypeWrapper() &&
+ (getReturnedArrayLengthExpression() != null))) {
+ return erasedTypeString(binding.getJavaReturnType(), true);
}
- return binding.getJavaReturnType().getName() + "[]";
+ return erasedTypeString(binding.getJavaReturnType(), true) + "[]";
}
protected void emitName(PrintWriter writer)
{
if (forImplementingMethodCall) {
- writer.print(getImplMethodName());
+ if (forIndirectBufferAndArrayImplementation) {
+ writer.print(getImplMethodName(false));
+ } else {
+ writer.print(getImplMethodName(true));
+ }
} else {
writer.print(getName());
}
@@ -165,16 +232,13 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
{
boolean needComma = false;
int numEmitted = 0;
- int numBufferOffsetArgs = 0, numBufferOffsetArrayArgs = 0;
if (forImplementingMethodCall && binding.hasContainingType()) {
// Always emit outgoing "this" argument
- writer.print("java.nio.Buffer ");
+ writer.print("java.nio.ByteBuffer ");
writer.print(javaThisArgumentName());
++numEmitted;
needComma = true;
- numBufferOffsetArgs++;
- writer.print(", int " + byteOffsetConversionArgName(numBufferOffsetArgs));
}
for (int i = 0; i < binding.getNumArguments(); i++) {
@@ -199,69 +263,354 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
writer.print(", ");
}
- // indirect buffer array sent down as object
- if(isIndirectBufferInterface() && type.isNIOBuffer() ) {
- writer.print(" Object ");
- } else {
- writer.print(type.getName());
- }
-
+ writer.print(erasedTypeString(type, false));
writer.print(" ");
writer.print(binding.getArgumentName(i));
-
++numEmitted;
needComma = true;
- // Add Buffer offset argument to store the buffer offset
- if((forImplementingMethodCall || prefixedMethod) &&
- (type.isNIOBuffer() || type.isNIOBufferArray())) {
- if(!type.isArray()) {
- numBufferOffsetArgs++;
- writer.print(", int " + byteOffsetConversionArgName(numBufferOffsetArgs));
- } else {
- numBufferOffsetArrayArgs++;
- writer.print(", int[] " +
- byteOffsetArrayConversionArgName(numBufferOffsetArrayArgs));
- }
+ // Add Buffer and array index offset arguments after each associated argument
+ if (forDirectBufferImplementation || forIndirectBufferAndArrayImplementation) {
+ if (type.isNIOBuffer()) {
+ writer.print(", int " + byteOffsetArgName(i));
+ } else if (type.isNIOBufferArray()) {
+ writer.print(", int[] " +
+ byteOffsetArrayArgName(i));
+ }
}
- // Add array index offset argument after each primitive array
- if( type.isArray() && !type.isNIOBufferArray() && !type.isStringArray()) {
- writer.print(", int " + binding.getArgumentName(i) + "_offset");
+ // Add offset argument after each primitive array
+ if (type.isPrimitiveArray()) {
+ writer.print(", int " + offsetArgName(i));
}
-
}
return numEmitted;
}
- protected String getImplMethodName()
- {
- if( isIndirectBufferInterface() )
- return binding.getName() + "2";
- else if(!forArrayImplementingMethodCall)
- return binding.getName() + "0";
- else
- return binding.getName() + "1";
+ protected String getImplMethodName(boolean direct) {
+ if (direct) {
+ return binding.getName() + "0";
+ } else {
+ return binding.getName() + "1";
+ }
}
+ protected String byteOffsetArgName(int i) {
+ return byteOffsetArgName(binding.getArgumentName(i));
+ }
- protected String byteOffsetConversionArgName(int i) {
- return "__byteOffset" + i;
+ protected String byteOffsetArgName(String s) {
+ return s + "_byte_offset";
}
- protected String byteOffsetArrayConversionArgName(int i) {
- return "__byteOffsetArray" + i;
+ protected String byteOffsetArrayArgName(int i) {
+ return binding.getArgumentName(i) + "_byte_offset_array";
}
+ protected String offsetArgName(int i) {
+ return binding.getArgumentName(i) + "_offset";
+ }
protected void emitBody(PrintWriter writer)
{
- writer.println(';');
+ if (!emitBody) {
+ writer.println(';');
+ } else {
+ MethodBinding binding = getBinding();
+ writer.println();
+ writer.println(" {");
+ if (isUnimplemented) {
+ writer.println(" throw new " + getRuntimeExceptionType() + "(\"Unimplemented\");");
+ } else {
+ emitPreCallSetup(binding, writer);
+ //emitReturnVariableSetup(binding, writer);
+ emitReturnVariableSetupAndCall(binding, writer);
+ }
+ writer.println(" }");
+ }
}
- protected static String javaThisArgumentName() {
+ protected void emitPreCallSetup(MethodBinding binding, PrintWriter writer) {
+ emitArrayLengthAndNIOBufferChecks(binding, writer);
+ }
+
+ protected void emitArrayLengthAndNIOBufferChecks(MethodBinding binding, PrintWriter writer) {
+ int numBufferOffsetArrayArgs = 0;
+ boolean firstBuffer = true;
+ // Check lengths of any incoming arrays if necessary
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ Type type = binding.getCArgumentType(i);
+ if (type.isArray()) {
+ ArrayType arrayType = type.asArray();
+ writer.println(" if (" + binding.getArgumentName(i) + ".length < " +
+ arrayType.getLength() + ")");
+ writer.println(" throw new " + getRuntimeExceptionType() +
+ "(\"Length of array \\\"" + binding.getArgumentName(i) +
+ "\\\" was less than the required " + arrayType.getLength() + "\");");
+ } else {
+ JavaType javaType = binding.getJavaArgumentType(i);
+ if (javaType.isNIOBuffer()) {
+ if (directNIOOnly) {
+ writer.println(" if (!BufferFactory.isDirect(" + binding.getArgumentName(i) + "))");
+ writer.println(" throw new " + getRuntimeExceptionType() + "(\"Argument \\\"" +
+ binding.getArgumentName(i) + "\\\" was not a direct buffer\");");
+ } else {
+ if(firstBuffer) {
+ firstBuffer = false;
+ writer.println(" boolean _direct = BufferFactory.isDirect(" + binding.getArgumentName(i) + ");");
+ } else {
+ writer.println(" if (_direct != BufferFactory.isDirect(" + binding.getArgumentName(i) + "))");
+ writer.println(" throw new " + getRuntimeExceptionType() +
+ "(\"Argument \\\"" + binding.getArgumentName(i) +
+ "\\\" : Buffers passed to this method must all be either direct or indirect\");");
+ }
+ }
+ } else if (javaType.isNIOBufferArray()) {
+ // All buffers passed down in an array of NIO buffers must be direct
+ String argName = binding.getArgumentName(i);
+ String arrayName = byteOffsetArrayArgName(i);
+ writer.println(" int[] " + arrayName + " = new int[" + argName + ".length];");
+ // Check direct buffer properties of all buffers within
+ writer.println(" if (" + argName + " != null) {");
+ writer.println(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {");
+ writer.println(" if (!BufferFactory.isDirect(" + argName + "[_ctr])) {");
+ writer.println(" throw new " + getRuntimeExceptionType() +
+ "(\"Element \" + _ctr + \" of argument \\\"" +
+ binding.getArgumentName(i) + "\\\" was not a direct buffer\");");
+ writer.println(" }");
+ // get the Buffer Array offset values and save them into another array to send down to JNI
+ writer.print (" " + arrayName + "[_ctr] = BufferFactory.getDirectBufferByteOffset(");
+ writer.println(argName + "[_ctr]);");
+ writer.println(" }");
+ writer.println(" }");
+ } else if (javaType.isPrimitiveArray()) {
+ String argName = binding.getArgumentName(i);
+ String offsetArg = offsetArgName(i);
+ writer.println(" if(" + argName + " != null && " + argName + ".length <= " + offsetArg + ")");
+ writer.print (" throw new " + getRuntimeExceptionType());
+ writer.println("(\"array offset argument \\\"" + offsetArg + "\\\" (\" + " + offsetArg +
+ " + \") equals or exceeds array length (\" + " + argName + ".length + \")\");");
+ }
+ }
+ }
+ }
+
+ protected void emitCall(MethodBinding binding, PrintWriter writer, boolean direct) {
+ writer.print(getImplMethodName(direct));
+ writer.print("(");
+ emitCallArguments(binding, writer, direct);
+ writer.print(");");
+ }
+
+
+ protected void emitReturnVariableSetupAndCall(MethodBinding binding, PrintWriter writer) {
+ writer.print(" ");
+ JavaType returnType = binding.getJavaReturnType();
+ boolean needsResultAssignment = false;
+
+ if (!returnType.isVoid()) {
+ if (returnType.isCompoundTypeWrapper() ||
+ returnType.isNIOByteBuffer()) {
+ writer.println("ByteBuffer _res;");
+ needsResultAssignment = true;
+ } else if (returnType.isArrayOfCompoundTypeWrappers()) {
+ writer.println("ByteBuffer[] _res;");
+ needsResultAssignment = true;
+ }
+ }
+
+ if (binding.signatureCanUseIndirectNIO() && !directNIOOnly) {
+ // Must generate two calls for this gated on whether the NIO
+ // buffers coming in are all direct or indirect
+ writer.println("if (_direct) {");
+ writer.print (" ");
+ }
+
+ if (needsResultAssignment) {
+ writer.print(" _res = ");
+ } else {
+ writer.print(" ");
+ if (!returnType.isVoid()) {
+ writer.print("return ");
+ }
+ }
+
+ if (binding.signatureUsesJavaPrimitiveArrays() &&
+ !binding.signatureCanUseIndirectNIO()) {
+ // FIXME: what happens with a C function of the form
+ // void foo(int* arg0, void* arg1);
+ // ?
+
+ // Only one call being made in this body, going to indirect
+ // buffer / array entry point
+ emitCall(binding, writer, false);
+ writer.println();
+ } else {
+ emitCall(binding, writer, true);
+ }
+
+ if (binding.signatureCanUseIndirectNIO() && !directNIOOnly) {
+ // Must generate two calls for this gated on whether the NIO
+ // buffers coming in are all direct or indirect
+ writer.println();
+ writer.println(" } else {");
+ writer.print (" ");
+ if (needsResultAssignment) {
+ writer.print(" _res = ");
+ } else {
+ writer.print(" ");
+ if (!returnType.isVoid()) {
+ writer.print("return ");
+ }
+ }
+ emitCall(binding, writer, false);
+ writer.println();
+ writer.println(" }");
+ } else {
+ writer.println();
+ }
+ if (needsResultAssignment) {
+ emitCallResultReturn(binding, writer);
+ }
+ }
+
+ protected int emitCallArguments(MethodBinding binding, PrintWriter writer, boolean direct) {
+ boolean needComma = false;
+ int numArgsEmitted = 0;
+
+ if (binding.hasContainingType()) {
+ // Emit this pointer
+ assert(binding.getContainingType().isCompoundTypeWrapper());
+ writer.print("getBuffer()");
+ needComma = true;
+ ++numArgsEmitted;
+ }
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ JavaType type = binding.getJavaArgumentType(i);
+ if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) {
+ // Don't need to expose these at the Java level
+ continue;
+ }
+
+ if (type.isVoid()) {
+ // Make sure this is the only param to the method; if it isn't,
+ // there's something wrong with our parsing of the headers.
+ assert(binding.getNumArguments() == 1);
+ continue;
+ }
+
+ if (needComma) {
+ writer.print(", ");
+ }
+
+ if (type.isCompoundTypeWrapper()) {
+ writer.print("((");
+ }
+
+ if (type.isNIOBuffer() && !direct) {
+ writer.print("BufferFactory.getArray(" + binding.getArgumentName(i) + ")");
+ } else {
+ writer.print(binding.getArgumentName(i));
+ }
+
+ if (type.isCompoundTypeWrapper()) {
+ writer.print(" == null) ? null : ");
+ writer.print(binding.getArgumentName(i));
+ writer.print(".getBuffer())");
+ }
+ needComma = true;
+ ++numArgsEmitted;
+ if (type.isNIOBuffer()) {
+ if (direct) {
+ writer.print(", BufferFactory.getDirectBufferByteOffset(" + binding.getArgumentName(i) + ")");
+ } else {
+ writer.print(", BufferFactory.getIndirectBufferByteOffset(" + binding.getArgumentName(i) + ")");
+ }
+ } else if (type.isNIOBufferArray()) {
+ writer.print(", " + byteOffsetArrayArgName(i));
+ }
+
+ // Add Array offset parameter for primitive arrays
+ if (type.isPrimitiveArray()) {
+ if(type.isFloatArray()) {
+ writer.print(", BufferFactory.SIZEOF_FLOAT * ");
+ } else if(type.isDoubleArray()) {
+ writer.print(", BufferFactory.SIZEOF_DOUBLE * ");
+ } else if(type.isByteArray()) {
+ writer.print(", ");
+ } else if(type.isLongArray()) {
+ writer.print(", BufferFactory.SIZEOF_LONG * ");
+ } else if(type.isShortArray()) {
+ writer.print(", BufferFactory.SIZEOF_SHORT * ");
+ } else if(type.isIntArray()) {
+ writer.print(", BufferFactory.SIZEOF_INT * ");
+ } else {
+ throw new RuntimeException("Unsupported type for calculating array offset argument for " +
+ binding.getArgumentName(i) +
+ "-- error occurred while processing Java glue code for " + binding.getName());
+ }
+ writer.print(offsetArgName(i));
+ }
+ }
+ return numArgsEmitted;
+ }
+
+ protected void emitCallResultReturn(MethodBinding binding, PrintWriter writer) {
+ JavaType returnType = binding.getJavaReturnType();
+
+ if (returnType.isCompoundTypeWrapper()) {
+ String fmt = getReturnedArrayLengthExpression();
+ writer.println(" if (_res == null) return null;");
+ if (fmt == null) {
+ writer.print(" return new " + returnType.getName() + "(_res.order(ByteOrder.nativeOrder()))");
+ } else {
+ writer.println(" _res.order(ByteOrder.nativeOrder());");
+ String[] argumentNames = new String[binding.getNumArguments()];
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ argumentNames[i] = binding.getArgumentName(i);
+ }
+ String expr = new MessageFormat(fmt).format(argumentNames);
+ PointerType cReturnTypePointer = binding.getCReturnType().asPointer();
+ CompoundType cReturnType = null;
+ if (cReturnTypePointer != null) {
+ cReturnType = cReturnTypePointer.getTargetType().asCompound();
+ }
+ if (cReturnType == null) {
+ throw new RuntimeException("ReturnedArrayLength directive currently only supported for pointers to compound types " +
+ "(error occurred while generating Java glue code for " + binding.getName() + ")");
+ }
+ writer.println(" " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[" + expr + "];");
+ writer.println(" for (int _count = 0; _count < " + expr + "; _count++) {");
+ // Create temporary ByteBuffer slice
+ // FIXME: probably need Type.getAlignedSize() for arrays of
+ // compound types (rounding up to machine-dependent alignment)
+ writer.println(" _res.position(_count * " + cReturnType.getSize() + ");");
+ writer.println(" _res.limit ((1 + _count) * " + cReturnType.getSize() + ");");
+ writer.println(" ByteBuffer _tmp = _res.slice();");
+ writer.println(" _tmp.order(ByteOrder.nativeOrder());");
+ writer.println(" _res.position(0);");
+ writer.println(" _res.limit(_res.capacity());");
+ writer.println(" _retarray[_count] = new " + getReturnTypeString(true) + "(_tmp);");
+ writer.println(" }");
+ writer.print (" return _retarray");
+ }
+ writer.println(";");
+ } else if (returnType.isNIOBuffer()) {
+ writer.println(" if (_res == null) return null;");
+ writer.println(" return _res.order(ByteOrder.nativeOrder());");
+ } else if (returnType.isArrayOfCompoundTypeWrappers()) {
+ writer.println(" if (_res == null) return null;");
+ writer.println(" " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[_res.length];");
+ writer.println(" for (int _count = 0; _count < _res.length; _count++) {");
+ writer.println(" _retarray[_count] = new " + getReturnTypeString(true) + "(_res[_count]);");
+ writer.println(" }");
+ writer.println(" return _retarray;");
+ }
+ }
+
+ public static String javaThisArgumentName() {
return "jthis0";
}
@@ -278,7 +627,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
* includes the C signature of the native method that is being bound by the
* emitter java method.
*/
- protected static class DefaultCommentEmitter implements CommentEmitter {
+ protected class DefaultCommentEmitter implements CommentEmitter {
public void emit(FunctionEmitter emitter, PrintWriter writer) {
emitBeginning(emitter, writer);
emitBindingCSignature(((JavaMethodBindingEmitter)emitter).getBinding(), writer);
@@ -295,9 +644,12 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
protected void emitEnding(FunctionEmitter emitter, PrintWriter writer) {
// If argument type is a named enum, then emit a comment detailing the
// acceptable values of that enum.
+ // If we're emitting a direct buffer variant only, then declare
+ // that the NIO buffer arguments must be direct.
MethodBinding binding = ((JavaMethodBindingEmitter)emitter).getBinding();
for (int i = 0; i < binding.getNumArguments(); i++) {
Type type = binding.getCArgumentType(i);
+ JavaType javaType = binding.getJavaArgumentType(i);
// don't emit param comments for anonymous enums, since we can't
// distinguish between the values found within multiple anonymous
// enums in the same C translation unit.
@@ -314,12 +666,19 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
writer.print(enumType.getEnumName(j));
}
writer.println("</code>");
+ } else if (directNIOOnly && javaType.isNIOBuffer()) {
+ writer.println();
+ writer.print(emitter.getBaseIndentString());
+ writer.print(" ");
+ writer.print("@param ");
+ writer.print(binding.getArgumentName(i));
+ writer.print(" a direct {@link " + javaType.getName() + "}");
}
}
}
}
- protected static class InterfaceCommentEmitter
+ protected class InterfaceCommentEmitter
extends JavaMethodBindingEmitter.DefaultCommentEmitter
{
protected void emitBeginning(FunctionEmitter emitter,
diff --git a/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java b/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java
deleted file mode 100644
index 3cbc8081d..000000000
--- a/src/net/java/games/gluegen/JavaMethodBindingImplEmitter.java
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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 Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package net.java.games.gluegen;
-
-import java.io.*;
-import java.util.*;
-import java.text.MessageFormat;
-
-import net.java.games.gluegen.cgram.types.*;
-import net.java.games.jogl.util.BufferUtils;
-
-/** Emits the Java-side component of the Java<->C JNI binding. */
-public class JavaMethodBindingImplEmitter extends JavaMethodBindingEmitter
-{
- private boolean isUnimplemented;
-
- public JavaMethodBindingImplEmitter(MethodBinding binding, PrintWriter output, String runtimeExceptionType)
- {
- this(binding, output, runtimeExceptionType, false, false);
- }
-
- public JavaMethodBindingImplEmitter(MethodBinding binding,
- PrintWriter output,
- String runtimeExceptionType,
- boolean isUnimplemented,
- boolean arrayImplExpansion)
- {
- super(binding, output, runtimeExceptionType);
- setCommentEmitter(defaultJavaCommentEmitter);
- this.isUnimplemented = isUnimplemented;
- this.forArrayImplementingMethodCall = arrayImplExpansion;
- }
-
- public JavaMethodBindingImplEmitter(JavaMethodBindingEmitter arg) {
- super(arg);
- if (arg instanceof JavaMethodBindingImplEmitter) {
- this.isUnimplemented = ((JavaMethodBindingImplEmitter) arg).isUnimplemented;
- }
- }
-
- protected void emitBody(PrintWriter writer)
- {
- MethodBinding binding = getBinding();
- if (needsBody()) {
- writer.println();
- writer.println(" {");
- if (isUnimplemented) {
- writer.println(" throw new " + getRuntimeExceptionType() + "(\"Unimplemented\");");
- } else {
- emitPreCallSetup(binding, writer);
- //emitReturnVariableSetup(binding, writer);
- emitReturnVariableSetupAndCall(binding, writer);
- }
- writer.println(" }");
- } else {
- writer.println(";");
- }
- }
-
-
- protected boolean generateIndirectBufferInterface = false;
-
- public boolean isGenerateIndirectBufferInterface() {
- return generateIndirectBufferInterface;
- }
-
- public void setGenerateIndirectBufferInterface(boolean generateIndirect) {
- generateIndirectBufferInterface = generateIndirect;
- }
-
-
- protected boolean isUnimplemented() {
- return isUnimplemented;
- }
-
- protected boolean needsBody() {
- return (isUnimplemented ||
- getBinding().signatureUsesNIO() ||
- getBinding().signatureUsesCArrays() ||
- getBinding().signatureUsesPrimitiveArrays() ||
- getBinding().hasContainingType());
- }
-
- protected void emitPreCallSetup(MethodBinding binding, PrintWriter writer) {
- if(isGenerateIndirectBufferInterface()) {
- // case for when indirect Buffer is a possibility
- emitArrayLengthAndNIOInDirectBufferChecks(binding, writer);
- } else {
- emitArrayLengthAndNIOBufferChecks(binding, writer);
- }
- }
-
-
- protected void emitArrayLengthAndNIOBufferChecks(MethodBinding binding, PrintWriter writer) {
- int numBufferOffsetArrayArgs = 0;
- // Check lengths of any incoming arrays if necessary
- for (int i = 0; i < binding.getNumArguments(); i++) {
- Type type = binding.getCArgumentType(i);
- JavaType javaType = binding.getJavaArgumentType(i);
- if (type.isArray()) {
- ArrayType arrayType = type.asArray();
- writer.println(" if (" + binding.getArgumentName(i) + ".length < " + arrayType.getLength() + ")");
- writer.println(" throw new " + getRuntimeExceptionType() + "(\"Length of array \\\"" + binding.getArgumentName(i) +
- "\\\" was less than the required " + arrayType.getLength() + "\");");
- } else {
- if (javaType.isNIOBuffer()) {
- writer.println(" if (!BufferFactory.isDirect(" + binding.getArgumentName(i) + "))");
- writer.println(" throw new " + getRuntimeExceptionType() + "(\"Argument \\\"" +
- binding.getArgumentName(i) + "\\\" was not a direct buffer\");");
- } else if (javaType.isNIOBufferArray()) {
- numBufferOffsetArrayArgs++;
- String argName = binding.getArgumentName(i);
- String arrayName = byteOffsetArrayConversionArgName(numBufferOffsetArrayArgs);
- writer.println(" int[] " + arrayName + " = new int[" + argName + ".length];");
- // Check direct buffer properties of all buffers within
- writer.println(" if (" + argName + " != null) {");
- writer.println(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {");
- writer.println(" if (!BufferFactory.isDirect(" + argName + "[_ctr])) {");
- writer.println(" throw new " + getRuntimeExceptionType() +
- "(\"Element \" + _ctr + \" of argument \\\"" +
- binding.getArgumentName(i) + "\\\" was not a direct buffer\");");
- writer.println(" }");
- // get the Buffer Array offset values and save them into another array to send down to JNI
- writer.print(" " + arrayName + "[_ctr] = BufferFactory.getDirectBufferByteOffset(");
- writer.println(argName + "[_ctr]);");
- writer.println(" }");
- writer.println(" }");
- } else if (javaType.isArray() && !javaType.isNIOBufferArray() &&!javaType.isStringArray()) {
- String argName = binding.getArgumentName(i);
- String offsetArg = argName + "_offset";
- writer.println(" if(" + argName + " != null && " + argName + ".length <= " + offsetArg + ")");
- writer.print(" throw new " + getRuntimeExceptionType());
- writer.println("(\"array offset argument \\\"" + offsetArg + "\\\" equals or exceeds array length\");");
- }
- }
- }
- }
-
-
- protected void emitArrayLengthAndNIOInDirectBufferChecks(MethodBinding binding, PrintWriter writer) {
- int numBufferOffsetArrayArgs = 0;
- boolean firstBuffer = true;
- // Check lengths of any incoming arrays if necessary
- for (int i = 0; i < binding.getNumArguments(); i++) {
- Type type = binding.getCArgumentType(i);
- if (type.isArray()) {
- ArrayType arrayType = type.asArray();
- writer.println(" if (" + binding.getArgumentName(i) + ".length < " +
- arrayType.getLength() + ")");
- writer.println(" throw new " + getRuntimeExceptionType() +
- "(\"Length of array \\\"" + binding.getArgumentName(i) +
- "\\\" was less than the required " + arrayType.getLength() + "\");");
- } else {
- JavaType javaType = binding.getJavaArgumentType(i);
- if (javaType.isNIOBuffer()) {
- if(firstBuffer == true) {
- firstBuffer = false;
- writer.println(" boolean direct = true, firstTime = true, result = true;");
- }
- writer.println(" result = BufferFactory.isDirect(" + binding.getArgumentName(i) + ");");
- writer.println(" if(firstTime == true) {");
- writer.println(" direct = result;");
- writer.println(" firstTime = false;");
- writer.println(" } else {");
- writer.println(" if(direct != result)");
- writer.println(" throw new " + getRuntimeExceptionType() +
- "(\"Argument \\\"" + binding.getArgumentName(i) +
- "\\\" :Not all Buffers in this method were direct or indirect\");");
- writer.println(" }");
- } else if (javaType.isNIOBufferArray()) {
- if(firstBuffer == true) {
- firstBuffer = false;
- writer.println(" boolean direct = true, firstTime = true, result = true;");
- }
- numBufferOffsetArrayArgs++;
- String argName = binding.getArgumentName(i);
- String arrayName = byteOffsetArrayConversionArgName(numBufferOffsetArrayArgs);
- writer.println(" int[] " + arrayName + " = new int[" + argName + ".length];");
- writer.println(" if (" + argName + " != null) {");
- // Check direct/indirect buffer properties of all buffers within
- writer.println(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {");
- writer.println(" result = BufferFactory.isDirect(" + argName + "[_ctr]);");
-
- writer.println(" if(firstTime == true) {");
- writer.println(" direct = result;");
- writer.println(" firstTime = false;");
- writer.println(" } else {");
- writer.println(" if(direct != result)");
- writer.println(" throw new " + getRuntimeExceptionType() + "(\"Element \" + _ctr + \" of argument \\\"" + binding.getArgumentName(i) + "\\\":Mixture of Direct/Indirect Buffers in Method Args\");");
- writer.println(" }");
- // get the Buffer Array offset values and save them into another array to send down to JNI
- writer.println(" if(direct)");
- writer.print(" " + arrayName + "[_ctr] = BufferFactory.getDirectBufferByteOffset(");
- writer.println(argName + "[_ctr]);");
- writer.println(" else");
- writer.print(" " + arrayName + "[_ctr] = BufferFactory.getIndirectBufferByteOffset(");
- writer.println(argName + "[_ctr]);");
- writer.println(" }");
- writer.println(" }");
- }
- }
- }
- }
-
-
-
-/* old method before indirect buffer support was added
- protected void emitReturnVariableSetup(MethodBinding binding, PrintWriter writer) {
- writer.print(" ");
- JavaType returnType = binding.getJavaReturnType();
- if (!returnType.isVoid()) {
- if (returnType.isCompoundTypeWrapper() ||
- returnType.isNIOByteBuffer()) {
- writer.println("ByteBuffer _res;");
- writer.print(" _res = ");
- } else if (returnType.isArrayOfCompoundTypeWrappers()) {
- writer.println("ByteBuffer[] _res;");
- writer.print(" _res = ");
- } else {
- writer.print("return ");
- }
- }
- }
-*/
-
-
- protected void emitReturnVariableSetupAndCall(MethodBinding binding, PrintWriter writer) {
-
- boolean returnFunction = false;
-
- writer.print(" ");
- JavaType returnType = binding.getJavaReturnType();
- if (!returnType.isVoid()) {
- if (returnType.isCompoundTypeWrapper() ||
- returnType.isNIOByteBuffer()) {
- writer.println("ByteBuffer _res;");
- writer.print(" _res = ");
- } else if (returnType.isArrayOfCompoundTypeWrappers()) {
- writer.println("ByteBuffer[] _res;");
- writer.print(" _res = ");
- } else {
- if(isGenerateIndirectBufferInterface())
- returnFunction = true;
- else
- writer.print("return ");
- }
- }
-
-
- if(isGenerateIndirectBufferInterface()) {
- //binding.setIndirectVariant(false);
- //writer.println(" boolean direct = true;");
- writer.println(" if(direct) {");
- writer.print(" ");
- };
- if(returnFunction) writer.print("return ");
- writer.print(getImplMethodName());
- writer.print("(");
- emitCallArguments(binding, writer, false);
- writer.print(")");
- if(isGenerateIndirectBufferInterface()) {
- writer.println(";");
- //binding.setIndirectVariant(true);
- writer.println(" } else { ");
- if(returnFunction) writer.print("return ");
- // get the indirect Buffer implementation name
- setIndirectBufferInterface(true);
- writer.print(" " + getImplMethodName());
- writer.print("(");
- setIndirectBufferInterface(false);
- emitCallArguments(binding, writer, true);
- writer.println(");");
- writer.println(" }");
- };
- emitCallResultReturn(binding, writer);
- }
-
-
- protected int emitCallArguments(MethodBinding binding, PrintWriter writer, boolean indirectCase) {
- boolean needComma = false;
- int numArgsEmitted = 0;
- int numBufferOffsetArgs = 0, numBufferOffsetArrayArgs = 0;
- boolean generateDirectAndIndirect;
-
- generateDirectAndIndirect = isGenerateIndirectBufferInterface();
-
- if (binding.hasContainingType()) {
- // Emit this pointer
- assert(binding.getContainingType().isCompoundTypeWrapper());
- writer.print("getBuffer()");
- needComma = true;
- ++numArgsEmitted;
- numBufferOffsetArgs++;
- //writer.print(", " + byteOffsetConversionArgName(numBufferOffsetArgs));
- writer.print(", BufferFactory.getDirectBufferByteOffset(getBuffer())");
- }
- for (int i = 0; i < binding.getNumArguments(); i++) {
- JavaType type = binding.getJavaArgumentType(i);
- if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) {
- // Don't need to expose these at the Java level
- continue;
- }
-
- if (type.isVoid()) {
- // Make sure this is the only param to the method; if it isn't,
- // there's something wrong with our parsing of the headers.
- assert(binding.getNumArguments() == 1);
- continue;
- }
-
- if (needComma) {
- writer.print(", ");
- }
-
- if (type.isCompoundTypeWrapper()) {
- writer.print("((");
- }
-
- if(type.isNIOBuffer() && !type.isNIOBufferArray() && generateDirectAndIndirect && indirectCase) {
- writer.print("BufferFactory.getArray(" + binding.getArgumentName(i) + ")");
- } else {
- writer.print(binding.getArgumentName(i));
- }
-
- if (type.isCompoundTypeWrapper()) {
- writer.print(" == null) ? null : ");
- writer.print(binding.getArgumentName(i));
- writer.print(".getBuffer())");
- numBufferOffsetArgs++;
- //writer.print(", " + byteOffsetConversionArgName(numBufferOffsetArgs));
- writer.print(", BufferFactory.getDirectBufferByteOffset(((" + binding.getArgumentName(i));
- writer.print(" == null) ? null : " + binding.getArgumentName(i) + ".getBuffer()))");
- }
- needComma = true;
- ++numArgsEmitted;
- if(type.isNIOBuffer() || type.isNIOBufferArray()) {
- if(!type.isArray()) {
- numBufferOffsetArgs++;
- if(generateDirectAndIndirect) {
- if(!indirectCase) {
- writer.print
- (", BufferFactory.getDirectBufferByteOffset(" + binding.getArgumentName(i) + ")");
- } else {
- writer.print
- (", BufferFactory.getIndirectBufferByteOffset(" + binding.getArgumentName(i) + ")");
- }
- } else {
- writer.print
- (", BufferFactory.getDirectBufferByteOffset(" + binding.getArgumentName(i) + ")");
- }
- } else {
- numBufferOffsetArrayArgs++;
- writer.print(", " + byteOffsetArrayConversionArgName(numBufferOffsetArrayArgs));
- }
- }
-
- // Add Array offset parameter for primitive arrays
- if(type.isArray() && !type.isNIOBufferArray() && !type.isStringArray()) {
- // writer.print(", " + binding.getArgumentName(i) + "_offset");
- if(type.isFloatArray()) {
- writer.print(", BufferFactory.SIZEOF_FLOAT * " + binding.getArgumentName(i) + "_offset");
- } else if(type.isDoubleArray()) {
- writer.print(", BufferFactory.SIZEOF_DOUBLE * " + binding.getArgumentName(i) + "_offset");
- } else if(type.isByteArray()) {
- writer.print(", " + binding.getArgumentName(i) + "_offset");
- } else if(type.isLongArray()) {
- writer.print(", BufferFactory.SIZEOF_LONG * " + binding.getArgumentName(i) + "_offset");
- } else if(type.isShortArray()) {
- writer.print(", BufferFactory.SIZEOF_SHORT * " + binding.getArgumentName(i) + "_offset");
- } else if(type.isIntArray()) {
- writer.print(", BufferFactory.SIZEOF_INT * " + binding.getArgumentName(i) + "_offset");
- } else {
- throw new RuntimeException("Unsupported type for calculating array offset argument for " +
- binding.getArgumentName(i) + "-- error occurred while processing Java glue code for " + binding.getName());
- }
- }
-
- }
- return numArgsEmitted;
- }
-
- protected void emitCallResultReturn(MethodBinding binding, PrintWriter writer) {
- JavaType returnType = binding.getJavaReturnType();
- boolean indirect;
-
- indirect = isGenerateIndirectBufferInterface();
-
- if (returnType.isCompoundTypeWrapper()) {
- if(!indirect) writer.println(";");
- String fmt = getReturnedArrayLengthExpression();
- writer.println(" if (_res == null) return null;");
- if (fmt == null) {
- writer.print(" return new " + returnType.getName() + "(_res.order(ByteOrder.nativeOrder()))");
- } else {
- writer.println(" _res.order(ByteOrder.nativeOrder());");
- String[] argumentNames = new String[binding.getNumArguments()];
- for (int i = 0; i < binding.getNumArguments(); i++) {
- argumentNames[i] = binding.getArgumentName(i);
- }
- String expr = new MessageFormat(fmt).format(argumentNames);
- PointerType cReturnTypePointer = binding.getCReturnType().asPointer();
- CompoundType cReturnType = null;
- if (cReturnTypePointer != null) {
- cReturnType = cReturnTypePointer.getTargetType().asCompound();
- }
- if (cReturnType == null) {
- throw new RuntimeException("ReturnedArrayLength directive currently only supported for pointers to compound types " +
- "(error occurred while generating Java glue code for " + binding.getName() + ")");
- }
- writer.println(" " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[" + expr + "];");
- writer.println(" for (int _count = 0; _count < " + expr + "; _count++) {");
- // Create temporary ByteBuffer slice
- // FIXME: probably need Type.getAlignedSize() for arrays of
- // compound types (rounding up to machine-dependent alignment)
- writer.println(" _res.position(_count * " + cReturnType.getSize() + ");");
- writer.println(" _res.limit ((1 + _count) * " + cReturnType.getSize() + ");");
- writer.println(" ByteBuffer _tmp = _res.slice();");
- writer.println(" _tmp.order(ByteOrder.nativeOrder());");
- writer.println(" _res.position(0);");
- writer.println(" _res.limit(_res.capacity());");
- writer.println(" _retarray[_count] = new " + getReturnTypeString(true) + "(_tmp);");
- writer.println(" }");
- writer.print (" return _retarray");
- }
- writer.println(";");
- } else if (returnType.isNIOBuffer()) {
- if(!indirect) writer.println(";");
- writer.println(" if (_res == null) return null;");
- writer.print(" return _res.order(ByteOrder.nativeOrder())");
- writer.println(";");
- } else if (returnType.isArrayOfCompoundTypeWrappers()) {
- if(!indirect) writer.println(";");
- writer.println(" if (_res == null) return null;");
- writer.println(" " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[_res.length];");
- writer.println(" for (int _count = 0; _count < _res.length; _count++) {");
- writer.println(" _retarray[_count] = new " + getReturnTypeString(true) + "(_res[_count]);");
- writer.println(" }");
- writer.print (" return _retarray");
- writer.println(";");
- } else {
- if(!indirect) writer.println(";");
- }
- }
-}
-
diff --git a/src/net/java/games/gluegen/JavaType.java b/src/net/java/games/gluegen/JavaType.java
index 8917bede1..18c9c301d 100644
--- a/src/net/java/games/gluegen/JavaType.java
+++ b/src/net/java/games/gluegen/JavaType.java
@@ -222,8 +222,7 @@ public class JavaType {
}
/**
- * Returns the name corresponding to this type. Returns null when this
- * object does not represent a C-language "struct" type.
+ * Returns the Java type name corresponding to this type.
*/
public String getName() {
if (clazz != null) {
@@ -242,6 +241,16 @@ public class JavaType {
or NULL if it can't be represented (i.e., it's a boxing class
that we need to call getBuffer() on.) */
public String jniTypeName() {
+ if (isCompoundTypeWrapper()) {
+ // These are sent down as Buffers (e.g., jobject)
+ return "jobject";
+ }
+
+ if (isArrayOfCompoundTypeWrappers()) {
+ // These are returned as arrays of ByteBuffers (e.g., jobjectArray)
+ return "jobjectArray /* of ByteBuffer */";
+ }
+
if (clazz == null) {
return null;
}
@@ -250,48 +259,41 @@ public class JavaType {
return "void";
}
- if (clazz.isPrimitive()) {
+ if (isPrimitive()) {
return "j" + clazz.getName();
}
- if (clazz.isArray()) {
- Class elementType = clazz.getComponentType();
- if (elementType.isPrimitive())
- {
- // Type is array-of-primitive
- return "j" + elementType.getName() + "Array";
- }
- else if (elementType == java.lang.String.class)
- {
- // Type is array-of-string
+ if (isPrimitiveArray() || isNIOBuffer()) {
+ // We now pass primitive arrays and buffers uniformly down to native code as java.lang.Object.
+ return "jobject";
+ }
+
+ if (isArray()) {
+ if (isStringArray()) {
return "jobjectArray /*elements are String*/";
- //return "jobjectArray";
}
- else if (java.nio.Buffer.class.isAssignableFrom(elementType))
- {
+
+ Class elementType = clazz.getComponentType();
+
+ if (isNIOBufferArray()) {
return "jobjectArray /*elements are " + elementType.getName() + "*/";
}
- else if (elementType.isArray())
- {
+
+ if (elementType.isArray()) {
// Type is array-of-arrays-of-something
- if (elementType.getComponentType().isPrimitive())
- {
+ if (elementType.getComponentType().isPrimitive()) {
// Type is an array-of-arrays-of-primitive
return "jobjectArray /* elements are " + elementType.getComponentType() + "[]*/";
//return "jobjectArray";
- }
- else
- {
+ } else {
throw new RuntimeException("Multi-dimensional arrays of types that are not primitives or Strings are not supported.");
}
}
- else
- {
- // Some unusual type that we don't handle
- throw new RuntimeException("Unexpected and unsupported type: \"" + this + "\"");
- }
- } // end array type case
+
+ // Some unusual type that we don't handle
+ throw new RuntimeException("Unexpected and unsupported array type: \"" + this + "\"");
+ }
if (isString()) {
return "jstring";
@@ -452,6 +454,11 @@ public class JavaType {
// Internals only below this point
//
+ // For debugging
+ public void dump() {
+ System.err.println("[clazz = " + clazz + " , name = " + name + " , elementType = " + elementType + " , primitivePointerType = " + primitivePointerType + "]");
+ }
+
/**
* Constructs a representation for a type corresponding to the given Class
* argument.
diff --git a/src/net/java/games/gluegen/MethodBinding.java b/src/net/java/games/gluegen/MethodBinding.java
index 11513ed36..7576ec3f8 100644
--- a/src/net/java/games/gluegen/MethodBinding.java
+++ b/src/net/java/games/gluegen/MethodBinding.java
@@ -53,9 +53,14 @@ public class MethodBinding {
private JavaType javaReturnType;
private List javaArgumentTypes;
private boolean computedSignatureProperties;
+ private boolean argumentsUseNIO;
private boolean signatureUsesNIO;
+ private boolean signatureCanUseIndirectNIO;
+ private boolean signatureUsesCompoundTypeWrappers;
+ private boolean signatureUsesCVoidPointers;
+ private boolean signatureUsesCPrimitivePointers;
private boolean signatureUsesCArrays;
- private boolean signatureUsesPrimitiveArrays;
+ private boolean signatureUsesJavaPrimitiveArrays;
private JavaType containingType;
private Type containingCType;
private int thisPointerIndex = -1;
@@ -68,15 +73,20 @@ public class MethodBinding {
public MethodBinding(MethodBinding bindingToCopy) {
this.sym = bindingToCopy.sym;
- this.containingType = bindingToCopy.containingType;
- this.containingCType = bindingToCopy.containingCType;
- this.javaReturnType = bindingToCopy.javaReturnType;
- this.javaArgumentTypes = (List)((ArrayList)bindingToCopy.javaArgumentTypes).clone();
- this.computedSignatureProperties = bindingToCopy.computedSignatureProperties;
- this.signatureUsesNIO = bindingToCopy.signatureUsesNIO;
- this.signatureUsesCArrays = bindingToCopy.signatureUsesCArrays;
- this.signatureUsesPrimitiveArrays = bindingToCopy.signatureUsesPrimitiveArrays;
- this.thisPointerIndex = bindingToCopy.thisPointerIndex;
+ this.containingType = bindingToCopy.containingType;
+ this.containingCType = bindingToCopy.containingCType;
+ this.javaReturnType = bindingToCopy.javaReturnType;
+ this.javaArgumentTypes = (List)((ArrayList)bindingToCopy.javaArgumentTypes).clone();
+ this.computedSignatureProperties = bindingToCopy.computedSignatureProperties;
+ this.argumentsUseNIO = bindingToCopy.argumentsUseNIO;
+ this.signatureUsesNIO = bindingToCopy.signatureUsesNIO;
+ this.signatureCanUseIndirectNIO = bindingToCopy.signatureCanUseIndirectNIO;
+ this.signatureUsesCompoundTypeWrappers = bindingToCopy.signatureUsesCompoundTypeWrappers;
+ this.signatureUsesCVoidPointers = bindingToCopy.signatureUsesCVoidPointers;
+ this.signatureUsesCPrimitivePointers = bindingToCopy.signatureUsesCPrimitivePointers;
+ this.signatureUsesCArrays = bindingToCopy.signatureUsesCArrays;
+ this.signatureUsesJavaPrimitiveArrays = bindingToCopy.signatureUsesJavaPrimitiveArrays;
+ this.thisPointerIndex = bindingToCopy.thisPointerIndex;
}
/** Constructor for calling a C function. */
@@ -146,11 +156,11 @@ public class MethodBinding {
return sym.getName();
}
- /** Replaces the C primitive pointer argument at slot <i>argumentNumber</i>
- (0..getNumArguments() - 1) with the specified type. If
- argumentNumber is less than 0 then replaces the return type. */
- public MethodBinding createCPrimitivePointerVariant(int argumentNumber,
- JavaType newArgType) {
+ /** Creates a new MethodBinding replacing the specified Java
+ argument type with a new argument type. If argumentNumber is
+ less than 0 then replaces the return type. */
+ public MethodBinding replaceJavaArgumentType(int argumentNumber,
+ JavaType newArgType) {
MethodBinding binding = new MethodBinding(sym);
if (argumentNumber < 0) {
binding.setJavaReturnType(newArgType);
@@ -168,6 +178,16 @@ public class MethodBinding {
}
/**
+ * Returns true if any of the outgoing arguments in the method's
+ * signature require conversion or checking due to the use of New
+ * I/O.
+ */
+ public boolean argumentsUseNIO() {
+ computeSignatureProperties();
+ return argumentsUseNIO;
+ }
+
+ /**
* Returns true if the return type or any of the outgoing arguments
* in the method's signature require conversion or checking due to
* the use of New I/O.
@@ -178,9 +198,55 @@ public class MethodBinding {
}
/**
- * Returns true if any of the outgoing arguments in the method's
- * signature represent fixed-length C arrays which require length
- * checking during the call.
+ * Returns true if it is possible for any of the outgoing arguments
+ * to be indirect NIO buffers.
+ */
+ public boolean signatureCanUseIndirectNIO() {
+ computeSignatureProperties();
+ return signatureCanUseIndirectNIO;
+ }
+
+ /**
+ * Returns true if the return type or any of the outgoing arguments
+ * in the method's signature use "compound type wrappers", or
+ * NIO-based wrappers for C data structures.
+ */
+ public boolean signatureUsesCompoundTypeWrappers() {
+ computeSignatureProperties();
+ return signatureUsesCompoundTypeWrappers;
+ }
+
+ /**
+ * Returns true if the function needs NIO-related
+ * wrapping/unwrapping or conversion of various arguments. Currently
+ * this returns the logical OR of signatureUsesNIO() and
+ * signatureUsesCompoundTypeWrappers().
+ */
+ public boolean needsNIOWrappingOrUnwrapping() {
+ return (signatureUsesNIO() || signatureUsesCompoundTypeWrappers());
+ }
+
+ /**
+ * Returns true if the return type or any of the outgoing arguments
+ * in the method's signature represent C void* pointers.
+ */
+ public boolean signatureUsesCVoidPointers() {
+ computeSignatureProperties();
+ return signatureUsesCVoidPointers;
+ }
+
+ /**
+ * Returns true if the return type or any of the outgoing arguments
+ * in the method's signature represent C primitive pointers.
+ */
+ public boolean signatureUsesCPrimitivePointers() {
+ computeSignatureProperties();
+ return signatureUsesCPrimitivePointers;
+ }
+
+ /**
+ * Returns true if the return type or any of the outgoing arguments
+ * in the method's signature represent C arrays.
*/
public boolean signatureUsesCArrays() {
computeSignatureProperties();
@@ -188,13 +254,12 @@ public class MethodBinding {
}
/**
- * Returns true if any of the outgoing arguments in the method's
- * signature represent primitive arrays which require a
- * GetPrimitiveArrayCritical or similar operation during the call.
+ * Returns true if the return type or any of the outgoing arguments
+ * in the method's signature represent Java primitive arrays.
*/
- public boolean signatureUsesPrimitiveArrays() {
+ public boolean signatureUsesJavaPrimitiveArrays() {
computeSignatureProperties();
- return signatureUsesPrimitiveArrays;
+ return signatureUsesJavaPrimitiveArrays;
}
/**
@@ -205,68 +270,91 @@ public class MethodBinding {
if (computedSignatureProperties)
return;
+ argumentsUseNIO = false;
signatureUsesNIO = false;
+ signatureCanUseIndirectNIO = false;
+ signatureUsesCompoundTypeWrappers = false;
+ signatureUsesCVoidPointers = false;
+ signatureUsesCPrimitivePointers = false;
signatureUsesCArrays = false;
- signatureUsesPrimitiveArrays = false;
+ signatureUsesJavaPrimitiveArrays = false;
- if (javaReturnType.isCompoundTypeWrapper() ||
- javaReturnType.isNIOByteBuffer() ||
+ if (javaReturnType.isCompoundTypeWrapper()) {
+ // Needs wrapping and/or setting of byte order (neither of which
+ // can be done easily from native code)
+ signatureUsesCompoundTypeWrappers = true;
+ }
+
+ if (javaReturnType.isNIOByteBuffer() ||
javaReturnType.isArrayOfCompoundTypeWrappers()) {
- // Needs wrapping and/or setting of byte order (neither of
- // which can be done easily from native code)
+ // Needs setting of byte order which can't be done easily from
+ // native code
signatureUsesNIO = true;
}
+ Type cRetType = sym.getReturnType();
+ if (cRetType.isArray()) {
+ // Needs checking of array lengths
+ signatureUsesCArrays = true;
+ if (cRetType.asArray().getElementType().isPrimitive()) {
+ signatureUsesCPrimitivePointers = true;
+ }
+ }
+
+ if (cRetType.isPointer()) {
+ if (cRetType.asPointer().getTargetType().isPrimitive()) {
+ signatureUsesCPrimitivePointers = true;
+ } else if (cRetType.asPointer().getTargetType().isVoid()) {
+ signatureUsesCVoidPointers = true;
+ }
+ }
+
for (int i = 0; i < getNumArguments(); i++) {
JavaType javaArgType = getJavaArgumentType(i);
Type cArgType = getCArgumentType(i);
- if (javaArgType.isCompoundTypeWrapper() ||
- javaArgType.isNIOBuffer() ||
+ if (javaArgType.isCompoundTypeWrapper()) {
+ // Needs unwrapping of accessors
+ signatureUsesCompoundTypeWrappers = true;
+ }
+
+ if (javaArgType.isNIOBuffer() ||
javaArgType.isNIOBufferArray()) {
- // Needs unwrapping of accessors or checking of direct
- // buffer property
+ // Needs checking of direct buffer property
signatureUsesNIO = true;
+ argumentsUseNIO = true;
+
+ if (javaArgType.isNIOBuffer()) {
+ // Potential conversion to indirect buffer
+ signatureCanUseIndirectNIO = true;
+ }
}
if (cArgType.isArray()) {
// Needs checking of array lengths
signatureUsesCArrays = true;
+ if (cArgType.asArray().getElementType().isPrimitive()) {
+ signatureUsesCPrimitivePointers = true;
+ }
}
- if (javaArgType.isPrimitiveArray() && !javaArgType.isStringArray() ) {
+ if (cArgType.isPointer()) {
+ if (cArgType.asPointer().getTargetType().isPrimitive()) {
+ signatureUsesCPrimitivePointers = true;
+ } else if (cArgType.asPointer().getTargetType().isVoid()) {
+ signatureUsesCVoidPointers = true;
+ }
+ }
+
+ if (javaArgType.isPrimitiveArray()) {
// Needs getPrimitiveArrayCritical or similar construct
// depending on native code calling convention
- signatureUsesPrimitiveArrays = true;
+ signatureUsesJavaPrimitiveArrays = true;
}
}
computedSignatureProperties = true;
}
-
- public MethodBinding createNIOBufferVariant() {
- if (!signatureUsesNIO()) {
- return this;
- }
- MethodBinding binding = new MethodBinding(sym, containingType, containingCType);
- binding.thisPointerIndex = thisPointerIndex;
- if (javaReturnType.isCompoundTypeWrapper()) {
- binding.setJavaReturnType(JavaType.forNIOByteBufferClass());
- } else if (javaReturnType.isArrayOfCompoundTypeWrappers()) {
- binding.setJavaReturnType(JavaType.forNIOByteBufferArrayClass());
- } else {
- binding.setJavaReturnType(javaReturnType);
- }
- for (int i = 0; i < getNumArguments(); i++) {
- JavaType type = getJavaArgumentType(i);
- if (type.isCompoundTypeWrapper()) {
- type = JavaType.forNIOBufferClass();
- }
- binding.addJavaArgumentType(type);
- }
- return binding;
- }
-
/** Indicates whether this MethodBinding is for a function pointer
contained in a struct. */
public boolean hasContainingType() {
diff --git a/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java b/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java
index e233d7155..ceee9f1be 100644
--- a/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java
+++ b/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java
@@ -44,37 +44,29 @@ import java.util.*;
import net.java.games.gluegen.*;
import net.java.games.gluegen.cgram.types.*;
-public class CGLPAWrapperEmitter extends CMethodBindingEmitter
-{
+public class CGLPAWrapperEmitter extends CMethodBindingEmitter {
private static final CommentEmitter defaultCommentEmitter =
new CGLPAWrapperCommentEmitter();
- private CMethodBindingEmitter emitterBeingWrapped;
private String glFuncPtrTypedefValue;
private static String procAddressJavaTypeName =
JavaType.createForClass(Long.TYPE).jniTypeName();
- protected boolean arrayImplRoutine = false;
-
- public CGLPAWrapperEmitter(CMethodBindingEmitter methodToWrap)
- {
+ public CGLPAWrapperEmitter(CMethodBindingEmitter methodToWrap) {
super(
new MethodBinding(methodToWrap.getBinding()) {
public String getName() {
return GLEmitter.WRAP_PREFIX + super.getName();
}
},
- methodToWrap.getIsOverloadedBinding(),
+ methodToWrap.getDefaultOutput(),
methodToWrap.getJavaPackageName(),
methodToWrap.getJavaClassName(),
+ methodToWrap.getIsOverloadedBinding(),
methodToWrap.getIsJavaMethodStatic(),
- methodToWrap.getDefaultOutput()
- );
-
-// if(binding.signatureUsesPrimitiveArrays())
-// arrayImplRoutine = true;
-
- indirectBufferInterface = methodToWrap.isIndirectBufferInterface();
+ true,
+ methodToWrap.forIndirectBufferAndArrayImplementation()
+ );
if (methodToWrap.getReturnValueCapacityExpression() != null) {
setReturnValueCapacityExpression(methodToWrap.getReturnValueCapacityExpression());
@@ -88,8 +80,7 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter
setCommentEmitter(defaultCommentEmitter);
}
- protected int emitArguments(PrintWriter writer)
- {
+ protected int emitArguments(PrintWriter writer) {
int numEmitted = super.emitArguments(writer);
if (numEmitted > 0)
{
@@ -103,8 +94,7 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter
return numEmitted;
}
- protected void emitBodyVariableDeclarations(PrintWriter writer)
- {
+ protected void emitBodyVariableDeclarations(PrintWriter writer) {
// create variable for the function pointer with the right type, and set
// it to the value of the passed-in glProcAddress
FunctionSymbol cSym = getBinding().getCSymbol();
@@ -121,8 +111,7 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter
}
protected void emitBodyVariablePreCallSetup(PrintWriter writer,
- boolean emittingPrimitiveArrayCritical)
- {
+ boolean emittingPrimitiveArrayCritical) {
super.emitBodyVariablePreCallSetup(writer, emittingPrimitiveArrayCritical);
if (!emittingPrimitiveArrayCritical) {
@@ -143,23 +132,17 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter
}
}
- // FIXME: refactor this and the superclass version so we don't have to copy
- // the whole function
- protected void emitBodyCallCFunction(PrintWriter writer)
- {
+ protected void emitBodyCallCFunction(PrintWriter writer) {
// Make the call to the actual C function
writer.print(" ");
// WARNING: this code assumes that the return type has already been
// typedef-resolved.
- Type cReturnType = getBinding().getCReturnType();
+ Type cReturnType = binding.getCReturnType();
if (!cReturnType.isVoid()) {
writer.print("_res = ");
}
-
- // !!!!!!!!! BEGIN CHANGES FROM SUPERCLASS METHOD
-
MethodBinding binding = getBinding();
if (binding.hasContainingType()) {
// Cannot call GL func through function pointer
@@ -171,106 +154,16 @@ public class CGLPAWrapperEmitter extends CMethodBindingEmitter
writer.print("(* ptr_");
writer.print(binding.getCSymbol().getName());
writer.print(") ");
-
- // !!!!!!!!! END CHANGES FROM SUPERCLASS METHOD
-
-
writer.print("(");
- for (int i = 0; i < binding.getNumArguments(); i++) {
- if (i != 0) {
- writer.print(", ");
- }
- JavaType javaType = binding.getJavaArgumentType(i);
- // Handle case where only param is void.
- if (javaType.isVoid()) {
- // Make sure this is the only param to the method; if it isn't,
- // there's something wrong with our parsing of the headers.
- assert(binding.getNumArguments() == 1);
- continue;
- }
-
- if (javaType.isJNIEnv()) {
- writer.print("env");
- } else if (binding.isArgumentThisPointer(i)) {
- writer.print(CMethodBindingEmitter.cThisArgumentName());
- } else {
- writer.print("(");
- writer.print(binding.getCSymbol().getArgumentType(i).getName());
- writer.print(") ");
- if (binding.getCArgumentType(i).isPointer() && binding.getJavaArgumentType(i).isPrimitive()) {
- writer.print("(intptr_t) ");
- }
- if (javaType.isArray() || javaType.isNIOBuffer()) {
-
- Type cArgType = binding.getCSymbol().getArgumentType(i);
- boolean containsVoid = false;
- // Add special code for accounting for array offsets
- //
- // For mapping from byte primitive array type to type* case produces code:
- // (GLtype*)((char*)_ptr0 + varName_offset)
- // where varName_offset is the number of bytes offset as calculated in Java code
-
- if(javaType.isArray() && !javaType.isNIOBufferArray() && !javaType.isStringArray()) {
- writer.print("( (char*)");
- }
- /* End of special code section for accounting for array offsets */
-
- writer.print(pointerConversionArgumentName(i));
- if (javaArgTypeNeedsDataCopy(javaType)) {
- writer.print("_copy");
- }
-
- /* Add special code for accounting for array offsets */
- if(javaType.isArray() && !javaType.isNIOBufferArray() && !javaType.isStringArray()) {
- writer.print(" + " + binding.getArgumentName(i) + "_offset)");
- }
- /* End of special code section for accounting for array offsets */
-
- } else {
- if (javaType.isString()) { writer.print("_UTF8"); }
- writer.print(binding.getArgumentName(i));
- }
- }
- }
+ emitBodyPassCArguments(writer);
writer.println(");");
}
protected String jniMangle(MethodBinding binding) {
- StringBuffer buf = new StringBuffer();
- buf.append(jniMangle(binding.getName()));
-
- if( isIndirectBufferInterface() )
- buf.append("2");
- else if(binding.signatureUsesPrimitiveArrays())
- buf.append("1");
-
- buf.append("__");
- for (int i = 0; i < binding.getNumArguments(); i++) {
- JavaType type = binding.getJavaArgumentType(i);
- Class c = type.getJavaClass();
- if (c != null) {
- jniMangle(c, buf);
- // If Buffer offset arguments were added, we need to mangle the JNI for the
- // extra arguments
- if(type.isNIOBuffer()) {
- jniMangle(Integer.TYPE, buf);
- } else if (type.isNIOBufferArray()) {
- int[] intArrayType = new int[0];
- c = intArrayType.getClass();
- jniMangle(c , buf);
- }
- if(type.isArray() && !type.isNIOBufferArray() && !type.isStringArray()) {
- jniMangle(Integer.TYPE, buf);
- }
- } else {
- // FIXME: add support for char* -> String conversion
- throw new RuntimeException("Unknown kind of JavaType: name="+type.getName());
- }
- }
-
- jniMangle(Long.TYPE, buf); // to account for the additional _addr_ parameter
+ StringBuffer buf = new StringBuffer(super.jniMangle(binding));
+ jniMangle(Long.TYPE, buf, false); // to account for the additional _addr_ parameter
return buf.toString();
- }
+ }
/** This class emits the comment for the wrapper method */
private static class CGLPAWrapperCommentEmitter extends CMethodBindingEmitter.DefaultCommentEmitter {
diff --git a/src/net/java/games/gluegen/opengl/GLEmitter.java b/src/net/java/games/gluegen/opengl/GLEmitter.java
index b3581bd73..e6c44bd4d 100644
--- a/src/net/java/games/gluegen/opengl/GLEmitter.java
+++ b/src/net/java/games/gluegen/opengl/GLEmitter.java
@@ -145,16 +145,11 @@ public class GLEmitter extends JavaEmitter
FunctionEmitter emitter = (FunctionEmitter) iter.next();
if (emitter instanceof JavaMethodBindingEmitter)
{
- JavaMethodBindingEmitter newEmitter =
- generateModifiedEmitter((JavaMethodBindingEmitter)emitter);
- if (newEmitter != null) {
- modifiedEmitters.add(newEmitter);
- }
+ generateModifiedEmitters((JavaMethodBindingEmitter) emitter, modifiedEmitters);
}
else if (emitter instanceof CMethodBindingEmitter)
{
- modifiedEmitters.add(
- generateModifiedEmitter((CMethodBindingEmitter)emitter));
+ generateModifiedEmitters((CMethodBindingEmitter) emitter, modifiedEmitters);
}
else
{
@@ -187,9 +182,40 @@ public class GLEmitter extends JavaEmitter
// Internals only below this point
//
- protected JavaMethodBindingEmitter generateModifiedEmitter(JavaMethodBindingEmitter baseJavaEmitter)
- {
- if (!(baseJavaEmitter instanceof JavaMethodBindingImplEmitter)) {
+ protected void generateModifiedEmitters(JavaMethodBindingEmitter baseJavaEmitter, List emitters) {
+ if (getGLConfig().manuallyImplement(baseJavaEmitter.getName())) {
+ // User will provide Java-side implementation of this routine;
+ // pass through any emitters which will produce signatures for
+ // it unmodified
+ emitters.add(baseJavaEmitter);
+ return;
+ }
+
+ JavaGLPAWrapperEmitter emitter =
+ new JavaGLPAWrapperEmitter(baseJavaEmitter,
+ getGLConfig().getProcAddressTableExpr(),
+ baseJavaEmitter.hasModifier(JavaMethodBindingEmitter.PRIVATE));
+ emitters.add(emitter);
+
+ // If this emitter doesn't have a body (i.e., is a public native
+ // call), we need to force it to emit a body, and produce another
+ // one to act as the entry point
+ if (baseJavaEmitter.signatureOnly() &&
+ baseJavaEmitter.hasModifier(JavaMethodBindingEmitter.PUBLIC) &&
+ baseJavaEmitter.hasModifier(JavaMethodBindingEmitter.NATIVE)) {
+ emitter.setEmitBody(true);
+ emitter.removeModifier(JavaMethodBindingEmitter.NATIVE);
+ emitter = new JavaGLPAWrapperEmitter(baseJavaEmitter,
+ getGLConfig().getProcAddressTableExpr(),
+ true);
+ emitter.setForImplementingMethodCall(true);
+ emitters.add(emitter);
+ }
+
+ /*****
+ FIXME: OLD CODE (DELETE)
+
+ if (baseJavaEmitter.signatureOnly()) {
// We only want to wrap the native entry point in the implementation
// class, not the public interface in the interface class.
//
@@ -201,14 +227,11 @@ public class GLEmitter extends JavaEmitter
return null;
return baseJavaEmitter;
}
- if (getGLConfig().manuallyImplement(baseJavaEmitter.getName())) {
- // User will provide Java-side implementation of this routine
- return null;
- }
return new JavaGLPAWrapperEmitter(baseJavaEmitter, getGLConfig().getProcAddressTableExpr());
+ ****/
}
- protected CMethodBindingEmitter generateModifiedEmitter(CMethodBindingEmitter baseCEmitter)
+ protected void generateModifiedEmitters(CMethodBindingEmitter baseCEmitter, List emitters)
{
// The C-side JNI binding for this particular function will have an
// extra final argument, which is the address (the OpenGL procedure
@@ -218,7 +241,7 @@ public class GLEmitter extends JavaEmitter
if (exp != null) {
res.setReturnValueCapacityExpression(exp);
}
- return res;
+ emitters.add(res);
}
protected boolean needsProcAddressWrapper(FunctionSymbol sym)
diff --git a/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java b/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java
index d0eafa8de..51f5579f4 100644
--- a/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java
+++ b/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java
@@ -44,18 +44,20 @@ import java.util.*;
import net.java.games.gluegen.*;
import net.java.games.gluegen.cgram.types.*;
-public class JavaGLPAWrapperEmitter extends JavaMethodBindingImplEmitter
-{
- private static final CommentEmitter commentEmitterForWrappedMethod =
+public class JavaGLPAWrapperEmitter extends JavaMethodBindingEmitter {
+ private final CommentEmitter commentEmitterForWrappedMethod =
new WrappedMethodCommentEmitter();
- private JavaMethodBindingEmitter emitterBeingWrapped;
+ private boolean changeNameAndArguments;
private String getProcAddressTableExpr;
- public JavaGLPAWrapperEmitter(JavaMethodBindingEmitter methodToWrap, String getProcAddressTableExpr)
- {
- super(methodToWrap.getBinding(), methodToWrap.getDefaultOutput(), methodToWrap.getRuntimeExceptionType());
+ public JavaGLPAWrapperEmitter(JavaMethodBindingEmitter methodToWrap,
+ String getProcAddressTableExpr,
+ boolean changeNameAndArguments) {
+ super(methodToWrap);
+ this.changeNameAndArguments = changeNameAndArguments;
this.getProcAddressTableExpr = getProcAddressTableExpr;
+ setCommentEmitter(new WrappedMethodCommentEmitter());
if (methodToWrap.getBinding().hasContainingType())
{
@@ -63,111 +65,39 @@ public class JavaGLPAWrapperEmitter extends JavaMethodBindingImplEmitter
"Cannot create OpenGL proc. address wrapper; method has containing type: \"" +
methodToWrap.getBinding() + "\"");
}
+ }
- // make a new emitter that will emit the original method's binding, but
- // with WRAP_PREFIX before its name. If a body is needed (for array
- // length checking, unwrapping of wrapper objects to java.nio.Buffers,
- // etc.) then it will be generated; therefore the emitter being wrapped
- // should be an "NIO buffer variant" (i.e., after all unpacking has
- // occurred).
- emitterBeingWrapped =
- new JavaMethodBindingEmitter(methodToWrap.getBinding().createNIOBufferVariant(),
- methodToWrap.getDefaultOutput(),
- methodToWrap.getRuntimeExceptionType())
- {
-
- protected void emitName(PrintWriter writer)
- {
- writer.print(GLEmitter.WRAP_PREFIX);
- super.emitName(writer);
-
- if(getBinding().signatureUsesPrimitiveArrays())
- writer.print("1");
-
- }
- protected int emitArguments(PrintWriter writer)
- {
- // following is set to true so that Buffer offset parameters are generated
- // in parent class method, when appropriate
- prefixedMethod = true;
- int numEmitted = super.emitArguments(writer);
- if (numEmitted > 0)
- {
- writer.print(", ");
- }
-
- writer.print("long glProcAddress");
- ++numEmitted;
-
- return numEmitted;
- }
- };
-
- // copy the modifiers from the original emitter
- emitterBeingWrapped.addModifiers(methodToWrap.getModifiers());
-
- // Change the access of the method we're wrapping to PRIVATE
- EmissionModifier origAccess = null; // null is equivalent if package access
- if (emitterBeingWrapped.hasModifier(PUBLIC))
- {
- origAccess = PUBLIC;
- }
- else if (emitterBeingWrapped.hasModifier(PROTECTED))
- {
- origAccess = PROTECTED;
- }
- else if (emitterBeingWrapped.hasModifier(PRIVATE))
- {
- origAccess = PRIVATE;
- }
-
- if (origAccess != null)
- {
- emitterBeingWrapped.removeModifier(origAccess);
- }
- emitterBeingWrapped.addModifier(PRIVATE);
- emitterBeingWrapped.addModifier(NATIVE);
-
- // Now make our binding use the original access of the wrapped method
- this.addModifier(origAccess);
- if (emitterBeingWrapped.hasModifier(STATIC)) {
- this.addModifier(STATIC);
+ public String getName() {
+ String res = super.getName();
+ if (changeNameAndArguments) {
+ return GLEmitter.WRAP_PREFIX + res;
}
+ return res;
}
- protected boolean needsBody() {
- return true;
- }
+ protected int emitArguments(PrintWriter writer) {
+ int numEmitted = super.emitArguments(writer);
+ if (changeNameAndArguments) {
+ if (numEmitted > 0) {
+ writer.print(", ");
+ }
- protected String getImplMethodName() {
- if(getBinding().signatureUsesPrimitiveArrays())
- return GLEmitter.WRAP_PREFIX + getBinding().getName() + "1";
- else
- return GLEmitter.WRAP_PREFIX + getBinding().getName();
+ writer.print("long glProcAddress");
+ ++numEmitted;
+ }
+
+ return numEmitted;
}
- public void emit(PrintWriter writer)
- {
- // Emit a wrapper that will call the method we want to wrap
- //writer.println(" // Emitter being wrapped = " + emitterBeingWrapped.getClass().getName());
- super.emit(writer);
- writer.println();
-
- // emit the wrapped method
- CommentEmitter origComment = emitterBeingWrapped.getCommentEmitter();
- emitterBeingWrapped.setCommentEmitter(commentEmitterForWrappedMethod);
- emitterBeingWrapped.emit(writer);
- emitterBeingWrapped.setCommentEmitter(origComment);
- writer.println();
+ protected String getImplMethodName(boolean direct) {
+ return GLEmitter.WRAP_PREFIX + super.getImplMethodName(direct);
}
protected void emitPreCallSetup(MethodBinding binding, PrintWriter writer) {
super.emitPreCallSetup(binding, writer);
- MethodBinding wrappedBinding = emitterBeingWrapped.getBinding();
String procAddressVariable =
- GLEmitter.PROCADDRESS_VAR_PREFIX + wrappedBinding.getName();
-
+ GLEmitter.PROCADDRESS_VAR_PREFIX + binding.getName();
writer.println(" final long __addr_ = " + getProcAddressTableExpr + "." + procAddressVariable + ";");
writer.println(" if (__addr_ == 0) {");
writer.println(" throw new GLException(\"Method \\\"" + binding.getName() + "\\\" not available\");");
@@ -184,7 +114,7 @@ public class JavaGLPAWrapperEmitter extends JavaMethodBindingImplEmitter
}
/** This class emits the comment for the wrapper method */
- private static class WrappedMethodCommentEmitter extends JavaMethodBindingEmitter.DefaultCommentEmitter {
+ private class WrappedMethodCommentEmitter extends JavaMethodBindingEmitter.DefaultCommentEmitter {
protected void emitBeginning(FunctionEmitter methodEmitter, PrintWriter writer) {
writer.print("Encapsulates function pointer for OpenGL function <br>: ");
}
diff --git a/src/net/java/games/gluegen/runtime/BufferFactory.java b/src/net/java/games/gluegen/runtime/BufferFactory.java
index cae81b1b3..81334b77a 100644
--- a/src/net/java/games/gluegen/runtime/BufferFactory.java
+++ b/src/net/java/games/gluegen/runtime/BufferFactory.java
@@ -87,25 +87,25 @@ public class BufferFactory {
the total offset for Direct Buffers. */
public static int getDirectBufferByteOffset(Buffer buf) {
- if(buf == null) {
- return 0;
- }
- if(buf instanceof ByteBuffer) {
- return (buf.position());
- } else if (buf instanceof FloatBuffer) {
- return (buf.position() * BufferUtils.SIZEOF_FLOAT);
- } else if (buf instanceof IntBuffer) {
- return (buf.position() * BufferUtils.SIZEOF_INT);
- } else if (buf instanceof ShortBuffer) {
- return (buf.position() * BufferUtils.SIZEOF_SHORT);
- } else if (buf instanceof DoubleBuffer) {
- return (buf.position() * BufferUtils.SIZEOF_DOUBLE);
- } else if (buf instanceof LongBuffer) {
- return (buf.position() * BufferUtils.SIZEOF_LONG);
- }
-
- throw new RuntimeException("Disallowed array backing store type in buffer "
- + buf.getClass().getName());
+ if(buf == null) {
+ return 0;
+ }
+ if(buf instanceof ByteBuffer) {
+ return (buf.position());
+ } else if (buf instanceof FloatBuffer) {
+ return (buf.position() * BufferUtils.SIZEOF_FLOAT);
+ } else if (buf instanceof IntBuffer) {
+ return (buf.position() * BufferUtils.SIZEOF_INT);
+ } else if (buf instanceof ShortBuffer) {
+ return (buf.position() * BufferUtils.SIZEOF_SHORT);
+ } else if (buf instanceof DoubleBuffer) {
+ return (buf.position() * BufferUtils.SIZEOF_DOUBLE);
+ } else if (buf instanceof LongBuffer) {
+ return (buf.position() * BufferUtils.SIZEOF_LONG);
+ }
+
+ throw new RuntimeException("Disallowed array backing store type in buffer "
+ + buf.getClass().getName());
}
@@ -113,25 +113,25 @@ public class BufferFactory {
a Buffer object. */
public static Object getArray(Buffer buf) {
- if (buf == null) {
- return null;
- }
- if(buf instanceof ByteBuffer) {
- return ((ByteBuffer) buf).array();
- } else if (buf instanceof FloatBuffer) {
- return ((FloatBuffer) buf).array();
- } else if (buf instanceof IntBuffer) {
- return ((IntBuffer) buf).array();
- } else if (buf instanceof ShortBuffer) {
- return ((ShortBuffer) buf).array();
- } else if (buf instanceof DoubleBuffer) {
- return ((DoubleBuffer) buf).array();
- } else if (buf instanceof LongBuffer) {
- return ((LongBuffer) buf).array();
- }
-
- throw new RuntimeException("Disallowed array backing store type in buffer "
- + buf.getClass().getName());
+ if (buf == null) {
+ return null;
+ }
+ if(buf instanceof ByteBuffer) {
+ return ((ByteBuffer) buf).array();
+ } else if (buf instanceof FloatBuffer) {
+ return ((FloatBuffer) buf).array();
+ } else if (buf instanceof IntBuffer) {
+ return ((IntBuffer) buf).array();
+ } else if (buf instanceof ShortBuffer) {
+ return ((ShortBuffer) buf).array();
+ } else if (buf instanceof DoubleBuffer) {
+ return ((DoubleBuffer) buf).array();
+ } else if (buf instanceof LongBuffer) {
+ return ((LongBuffer) buf).array();
+ }
+
+ throw new RuntimeException("Disallowed array backing store type in buffer "
+ + buf.getClass().getName());
}
@@ -161,5 +161,4 @@ public class BufferFactory {
throw new RuntimeException("Unknown buffer type " + buf.getClass().getName());
}
-
}
diff --git a/src/net/java/games/jogl/Animator.java b/src/net/java/games/jogl/Animator.java
index 15d31c224..ac6248487 100644
--- a/src/net/java/games/jogl/Animator.java
+++ b/src/net/java/games/jogl/Animator.java
@@ -67,6 +67,7 @@ public class Animator {
private volatile boolean shouldStop;
protected boolean ignoreExceptions;
protected boolean printExceptions;
+ private boolean runAsFastAsPossible;
// For efficient rendering of Swing components, in particular when
// they overlap one another
@@ -119,6 +120,14 @@ public class Animator {
this.printExceptions = printExceptions;
}
+ /** Sets a flag in this Animator indicating that it is to run as
+ fast as possible. By default there is a brief pause in the
+ animation loop which prevents the CPU from getting swamped.
+ This method may not have an effect on subclasses. */
+ public final void setRunAsFastAsPossible(boolean runFast) {
+ runAsFastAsPossible = runFast;
+ }
+
/** Called every frame to cause redrawing of all of the
GLAutoDrawables this Animator manages. Subclasses should call
this to get the most optimized painting behavior for the set of
@@ -174,10 +183,12 @@ public class Animator {
}
}
display();
- // Avoid swamping the CPU
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
+ if (!runAsFastAsPossible) {
+ // Avoid swamping the CPU
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ }
}
}
} finally {
diff --git a/src/net/java/games/jogl/GLJPanel.java b/src/net/java/games/jogl/GLJPanel.java
index d3d95166c..c5b3b7d95 100644
--- a/src/net/java/games/jogl/GLJPanel.java
+++ b/src/net/java/games/jogl/GLJPanel.java
@@ -48,6 +48,7 @@ import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
+import java.nio.*;
import java.security.*;
import javax.swing.JComponent;
import javax.swing.JPanel;
@@ -98,8 +99,8 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
private BufferedImage offscreenImage;
// One of these is used to store the read back pixels before storing
// in the BufferedImage
- private byte[] readBackBytes;
- private int[] readBackInts;
+ private ByteBuffer readBackBytes;
+ private IntBuffer readBackInts;
private int readBackWidthInPixels;
private int readBackHeightInPixels;
// Width of the actual GLJPanel
@@ -514,7 +515,7 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
case BufferedImage.TYPE_3BYTE_BGR:
glFormat = GL.GL_BGR;
glType = GL.GL_UNSIGNED_BYTE;
- readBackBytes = new byte[readBackWidthInPixels * readBackHeightInPixels * 3];
+ readBackBytes = ByteBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels * 3);
break;
case BufferedImage.TYPE_INT_RGB:
@@ -523,7 +524,7 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
glType = (hardwareAccelerationDisabled
? offscreenContext.getOffscreenContextPixelDataType()
: hwGLFormat);
- readBackInts = new int[readBackWidthInPixels * readBackHeightInPixels];
+ readBackInts = IntBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels);
break;
default:
@@ -554,12 +555,9 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
// Actually read the pixels.
gl.glReadBuffer(GL.GL_FRONT);
if (readBackBytes != null) {
- gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackBytes, 0);
+ gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackBytes);
} else if (readBackInts != null) {
- if (DEBUG && VERBOSE) {
- System.err.println("GLJPanel$Updater.display(): readBackInts.length == " + readBackInts.length);
- }
- gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts, 0);
+ gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts);
}
// Restore saved modes.
@@ -581,12 +579,12 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
int destIncr = 0;
if (readBackBytes != null) {
- src = readBackBytes;
+ src = readBackBytes.array();
dest = ((DataBufferByte) offscreenImage.getRaster().getDataBuffer()).getData();
srcIncr = readBackWidthInPixels * 3;
destIncr = offscreenImage.getWidth() * 3;
} else {
- src = readBackInts;
+ src = readBackInts.array();
dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData();
srcIncr = readBackWidthInPixels;
destIncr = offscreenImage.getWidth();
diff --git a/src/net/java/games/jogl/impl/Project.java b/src/net/java/games/jogl/impl/Project.java
index 41cf9d45e..6138a4108 100755
--- a/src/net/java/games/jogl/impl/Project.java
+++ b/src/net/java/games/jogl/impl/Project.java
@@ -104,11 +104,11 @@
*/
package net.java.games.jogl.impl;
+import java.nio.*;
+
import net.java.games.jogl.*;
import net.java.games.jogl.util.*;
-import java.nio.DoubleBuffer;
-
/**
* Project.java
* <p/>
@@ -589,6 +589,33 @@ class Project {
double y,
double deltaX,
double deltaY,
+ IntBuffer viewport) {
+ if (deltaX <= 0 || deltaY <= 0) {
+ return;
+ }
+
+ /* Translate and scale the picked region to the entire window */
+ gl.glTranslated((viewport.get(2) - 2 * (x - viewport.get(0))) / deltaX,
+ (viewport.get(3) - 2 * (y - viewport.get(1))) / deltaY,
+ 0);
+ gl.glScaled(viewport.get(2) / deltaX, viewport.get(3) / deltaY, 1.0);
+ }
+
+ /**
+ * Method gluPickMatrix
+ *
+ * @param x
+ * @param y
+ * @param deltaX
+ * @param deltaY
+ * @param viewport
+ * @param viewport_offset
+ */
+ public void gluPickMatrix(GL gl,
+ double x,
+ double y,
+ double deltaX,
+ double deltaY,
int[] viewport,
int viewport_offset) {
if (deltaX <= 0 || deltaY <= 0) {
diff --git a/src/net/java/games/jogl/impl/mipmap/Mipmap.java b/src/net/java/games/jogl/impl/mipmap/Mipmap.java
index 8b697f37c..c80d25a12 100644
--- a/src/net/java/games/jogl/impl/mipmap/Mipmap.java
+++ b/src/net/java/games/jogl/impl/mipmap/Mipmap.java
@@ -263,7 +263,7 @@ public class Mipmap {
if( target == GL.GL_TEXTURE_2D || target == GL.GL_PROXY_TEXTURE_2D ) {
proxyTarget = GL.GL_PROXY_TEXTURE_2D;
gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
- heightAtLevelOne, 0, format, type, (double[])null, 0 );
+ heightAtLevelOne, 0, format, type, null );
} else if( (target == GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB) ||
(target == GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB) ||
(target == GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB) ||
@@ -272,12 +272,12 @@ public class Mipmap {
(target == GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ) {
proxyTarget = GL.GL_PROXY_TEXTURE_CUBE_MAP_ARB;
gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
- heightAtLevelOne, 0, format, type, (double[])null, 0 );
+ heightAtLevelOne, 0, format, type, null );
} else {
assert( target == GL.GL_TEXTURE_1D || target == GL.GL_PROXY_TEXTURE_1D );
proxyTarget = GL.GL_PROXY_TEXTURE_1D;
gl.glTexImage1D( proxyTarget, 1, internalFormat, widthAtLevelOne,
- 0, format, type, (double[])null, 0 );
+ 0, format, type, null );
}
gl.glGetTexLevelParameteriv( proxyTarget, 1, GL.GL_TEXTURE_WIDTH, proxyWidth, 0 );
// does it fit?
@@ -342,7 +342,7 @@ public class Mipmap {
if( target == GL.GL_TEXTURE_3D || target == GL.GL_PROXY_TEXTURE_3D ) {
proxyTarget = GL.GL_PROXY_TEXTURE_3D;
gl.glTexImage3D( proxyTarget, 1, internalFormat, widthAtLevelOne,
- heightAtLevelOne, depthAtLevelOne, 0, format, type, (double[])null, 0 );
+ heightAtLevelOne, depthAtLevelOne, 0, format, type, null );
}
gl.glGetTexLevelParameteriv( proxyTarget, 1, GL.GL_TEXTURE_WIDTH, proxyWidth, 0 );
// does it fit