diff options
Diffstat (limited to 'src/net/java/games/gluegen/CMethodBindingEmitter.java')
-rw-r--r-- | src/net/java/games/gluegen/CMethodBindingEmitter.java | 139 |
1 files changed, 123 insertions, 16 deletions
diff --git a/src/net/java/games/gluegen/CMethodBindingEmitter.java b/src/net/java/games/gluegen/CMethodBindingEmitter.java index 8abcdcd78..ffe0ebbd3 100644 --- a/src/net/java/games/gluegen/CMethodBindingEmitter.java +++ b/src/net/java/games/gluegen/CMethodBindingEmitter.java @@ -303,6 +303,7 @@ public class CMethodBindingEmitter extends FunctionEmitter 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()) @@ -320,6 +321,9 @@ 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); @@ -338,8 +342,18 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.print(" "); writer.print(binding.getArgumentName(i)); ++numEmitted; + // Add Buffer offset argument immediately after any Buffer arguments + if(javaArgType.isNIOBuffer() || javaArgType.isNIOBufferArray()) { + if(!javaArgType.isArray()) { + numBufferOffsetArgs++; + writer.print(", jint " + byteOffsetConversionArgName(numBufferOffsetArgs)); + } else { + numBufferOffsetArrayArgs++; + writer.print(", jintArray " + + byteOffsetArrayConversionArgName(numBufferOffsetArrayArgs)); + } + } } - return numEmitted; } @@ -393,6 +407,10 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.println(" jobject _tmpObj;"); writer.println(" int _copyIndex;"); writer.println(" jsize _tmpArrayLen;"); + + // Pointer to the data in the Buffer, taking the offset into account + writer.println(" GLint * _offsetHandle = NULL;"); + emittedDataCopyTemps = true; } } else if (type.isString()) { @@ -468,16 +486,20 @@ 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 if (binding.hasContainingType()) { + byteOffsetCounter++; emitPointerConversion(writer, binding, binding.getContainingType(), binding.getContainingCType(), JavaMethodBindingEmitter.javaThisArgumentName(), - CMethodBindingEmitter.cThisArgumentName()); + CMethodBindingEmitter.cThisArgumentName(), + byteOffsetConversionArgName(byteOffsetCounter)); } for (int i = 0; i < binding.getNumArguments(); i++) { @@ -486,10 +508,12 @@ public class CMethodBindingEmitter extends FunctionEmitter continue; } if (type.isNIOBuffer()) { + byteOffsetCounter++; emitPointerConversion(writer, binding, type, binding.getCArgumentType(i), binding.getArgumentName(i), - pointerConversionArgumentName(i)); + pointerConversionArgumentName(i), + byteOffsetConversionArgName(byteOffsetCounter)); } } } @@ -506,6 +530,7 @@ public class CMethodBindingEmitter extends FunctionEmitter 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 // we're calling @@ -592,6 +617,18 @@ 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) + writer.println + (" _offsetHandle = (GLint *) (*env)->GetPrimitiveArrayCritical(env, " + + byteOffsetArrayConversionArgName(byteOffsetArrayCounter) + + ", NULL);"); + + // process each element in the array writer.println(" for (_copyIndex = 0; _copyIndex < "+arrayLenName+"; ++_copyIndex) {"); @@ -609,14 +646,17 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.print(" "); emitGetStringUTFChars(writer, "(jstring) _tmpObj", - convName+"_copy[_copyIndex]"); + "(const char*)"+convName+"_copy[_copyIndex]"); } else if (isNIOBufferClass(subArrayElementJavaType)) { + /* We always assume an integer "byte offset" argument follows any Buffer + in the method binding. */ emitGetDirectBufferAddress(writer, "_tmpObj", cArgElementType.getName(), - convName + "_copy[_copyIndex]"); + convName + "_copy[_copyIndex]", + "_offsetHandle[_copyIndex]"); } else { @@ -641,6 +681,13 @@ public class CMethodBindingEmitter extends FunctionEmitter } writer.println(" }"); + if(subArrayElementJavaType != java.lang.String.class) { + writer.println + (" (*env)->ReleasePrimitiveArrayCritical(env, " + + byteOffsetArrayConversionArgName(byteOffsetArrayCounter) + + ", _offsetHandle, JNI_ABORT);"); + } + writer.println(); } // end of data copy @@ -781,7 +828,7 @@ public class CMethodBindingEmitter extends FunctionEmitter } // free the main array - writer.print(" free((void*) "); + writer.print(" free("); writer.print(convName+"_copy"); writer.println(");"); } // end of cleaning up copied data @@ -1019,6 +1066,7 @@ public class CMethodBindingEmitter extends FunctionEmitter protected String jniMangle(MethodBinding binding) { StringBuffer buf = new StringBuffer(); + int numBufferOffsetArgs = 0; buf.append(jniMangle(binding.getName())); buf.append("__"); for (int i = 0; i < binding.getNumArguments(); i++) { @@ -1026,11 +1074,28 @@ public class CMethodBindingEmitter extends FunctionEmitter 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 == JavaType.forNIOBufferClass() || + type == JavaType.forNIOByteBufferClass() || + type == JavaType.forNIOShortBufferClass() || + type == JavaType.forNIOIntBufferClass() || + type == JavaType.forNIOLongBufferClass() || + type == JavaType.forNIOFloatBufferClass() || + type == JavaType.forNIODoubleBufferClass()) { + jniMangle(Integer.TYPE, buf); + } else if (type.isNIOByteBufferArray() || + type.isNIOBufferArray()) { + int[] intArrayType = new int[0]; + c = intArrayType.getClass(); + jniMangle(c , buf); + } } else { // FIXME: add support for char* -> String conversion throw new RuntimeException("Unknown kind of JavaType: name="+type.getName()); } } + return buf.toString(); } @@ -1138,22 +1203,53 @@ public class CMethodBindingEmitter extends FunctionEmitter writer.println(" }"); } + + private void emitGetDirectBufferAddress(PrintWriter writer, String sourceVarName, String receivingVarTypeString, - String receivingVarName) { + String receivingVarName, + String byteOffsetVarName) { if (EMIT_NULL_CHECKS) { writer.print(" if ("); writer.print(sourceVarName); writer.println(" != NULL) {"); } - writer.print(" "); - writer.print(receivingVarName); - writer.print(" = ("); - writer.print(receivingVarTypeString); - writer.print(") (*env)->GetDirectBufferAddress(env, "); - writer.print(sourceVarName); - writer.println(");"); + /* 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 + ");"); + if (EMIT_NULL_CHECKS) { writer.println(" } else {"); writer.print(" "); @@ -1270,11 +1366,13 @@ public class CMethodBindingEmitter extends FunctionEmitter JavaType type, Type cType, String incomingArgumentName, - String cVariableName) { + String cVariableName, + String byteOffsetVarName) { emitGetDirectBufferAddress(writer, incomingArgumentName, cType.getName(), - cVariableName); + cVariableName, + byteOffsetVarName); /* if (EMIT_NULL_CHECKS) { @@ -1301,6 +1399,15 @@ public class CMethodBindingEmitter extends FunctionEmitter return "_ptr" + i; } + protected String byteOffsetConversionArgName(int i) { + return "__byteOffset" + i; + } + + protected String byteOffsetArrayConversionArgName(int i) { + return "__byteOffsetArray" + i; + } + + /** * Class that emits a generic comment for CMethodBindingEmitters; the comment * includes the C signature of the native method that is being bound by the |