/* * 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.opengl; import java.io.*; import java.util.*; import net.java.games.gluegen.*; import net.java.games.gluegen.cgram.types.*; 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) { super( new MethodBinding(methodToWrap.getBinding()) { public String getName() { return GLEmitter.WRAP_PREFIX + super.getName(); } }, methodToWrap.getIsOverloadedBinding(), methodToWrap.getJavaPackageName(), methodToWrap.getJavaClassName(), methodToWrap.getIsJavaMethodStatic(), methodToWrap.getDefaultOutput() ); // if(binding.signatureUsesPrimitiveArrays()) // arrayImplRoutine = true; if (methodToWrap.getReturnValueCapacityExpression() != null) { setReturnValueCapacityExpression(methodToWrap.getReturnValueCapacityExpression()); } if (methodToWrap.getReturnValueLengthExpression() != null) { setReturnValueLengthExpression(methodToWrap.getReturnValueLengthExpression()); } setTemporaryCVariableDeclarations(methodToWrap.getTemporaryCVariableDeclarations()); setTemporaryCVariableAssignments (methodToWrap.getTemporaryCVariableAssignments ()); setCommentEmitter(defaultCommentEmitter); } protected int emitArguments(PrintWriter writer) { int numEmitted = super.emitArguments(writer); if (numEmitted > 0) { writer.print(", "); } //writer.print("long glProcAddress"); writer.print(procAddressJavaTypeName); writer.print(" glProcAddress"); ++numEmitted; return numEmitted; } 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(); String funcPointerTypedefName = GLEmitter.getGLFunctionPointerTypedefName(cSym); writer.print(" "); writer.print(funcPointerTypedefName); writer.print(" ptr_"); writer.print(cSym.getName()); writer.println(";"); super.emitBodyVariableDeclarations(writer); } protected void emitBodyVariablePreCallSetup(PrintWriter writer, boolean emittingPrimitiveArrayCritical) { super.emitBodyVariablePreCallSetup(writer, emittingPrimitiveArrayCritical); if (!emittingPrimitiveArrayCritical) { // set the function pointer to the value of the passed-in glProcAddress FunctionSymbol cSym = getBinding().getCSymbol(); String funcPointerTypedefName = GLEmitter.getGLFunctionPointerTypedefName(cSym); String ptrVarName = "ptr_" + cSym.getName(); writer.print(" "); writer.print(ptrVarName); writer.print(" = ("); writer.print(funcPointerTypedefName); writer.println(") (intptr_t) glProcAddress;"); writer.println(" assert(" + ptrVarName + " != NULL);"); } } // FIXME: refactor this and the superclass version so we don't have to copy // the whole function 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(); if (!cReturnType.isVoid()) { writer.print("_res = "); } // !!!!!!!!! BEGIN CHANGES FROM SUPERCLASS METHOD MethodBinding binding = getBinding(); if (binding.hasContainingType()) { // Cannot call GL func through function pointer throw new IllegalStateException( "Cannot call GL func through function pointer: " + binding); } // call throught the run-time function pointer 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)); } } } writer.println(");"); } protected String jniMangle(MethodBinding binding) { StringBuffer buf = new StringBuffer(); buf.append(jniMangle(binding.getName())); 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 return buf.toString(); } /** This class emits the comment for the wrapper method */ private static class CGLPAWrapperCommentEmitter extends CMethodBindingEmitter.DefaultCommentEmitter { protected void emitBeginning(FunctionEmitter methodEmitter, PrintWriter writer) { writer.print(" -- FIXME: IMPLEMENT COMMENT FOR CGLPAWrapperCommentEmitter -- "); } } } // end class CGLPAWrapperEmitter