aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/games/gluegen/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/games/gluegen/opengl')
-rw-r--r--src/net/java/games/gluegen/opengl/BuildComposablePipeline.java498
-rw-r--r--src/net/java/games/gluegen/opengl/BuildStaticGLInfo.java258
-rw-r--r--src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java201
-rw-r--r--src/net/java/games/gluegen/opengl/ConvertFromGL4Java.java91
-rw-r--r--src/net/java/games/gluegen/opengl/GLEmitter.java330
-rw-r--r--src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java178
6 files changed, 1556 insertions, 0 deletions
diff --git a/src/net/java/games/gluegen/opengl/BuildComposablePipeline.java b/src/net/java/games/gluegen/opengl/BuildComposablePipeline.java
new file mode 100644
index 000000000..90ec97113
--- /dev/null
+++ b/src/net/java/games/gluegen/opengl/BuildComposablePipeline.java
@@ -0,0 +1,498 @@
+/*
+ * 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
+ * MIDROSYSTEMS, 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 net.java.games.gluegen.*;
+
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+public class BuildComposablePipeline
+{
+ private String outputDirectory;
+ private Class classToComposeAround;
+
+ public static void main(String[] args)
+ {
+ String nameOfClassToComposeAround = args[0];
+ Class classToComposeAround;
+ try {
+ classToComposeAround = Class.forName(nameOfClassToComposeAround);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Could not find class \"" + nameOfClassToComposeAround + "\"", e);
+ }
+
+ String outputDir = args[1];
+
+ BuildComposablePipeline composer =
+ new BuildComposablePipeline(classToComposeAround, outputDir);
+
+ try
+ {
+ composer.emit();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(
+ "Error generating composable pipeline source files", e);
+ }
+ }
+
+ protected BuildComposablePipeline(Class classToComposeAround, String outputDirectory)
+ {
+ this.outputDirectory = outputDirectory;
+ this.classToComposeAround = classToComposeAround;
+
+ if (! classToComposeAround.isInterface())
+ {
+ throw new IllegalArgumentException(
+ classToComposeAround.getName() + " is not an interface class");
+ }
+ }
+
+ /**
+ * Emit the java source code for the classes that comprise the composable
+ * pipeline.
+ */
+ public void emit() throws IOException
+ {
+ String pDir = outputDirectory;
+ String pInterface = classToComposeAround.getName();
+ List/*<Method>*/ publicMethods = Arrays.asList(classToComposeAround.getMethods());
+
+ (new DebugPipeline(pDir, pInterface)).emit(publicMethods);
+ (new TracePipeline(pDir, pInterface)).emit(publicMethods);
+ }
+
+ //-------------------------------------------------------
+
+ /**
+ * Emits a Java source file that represents one element of the composable
+ * pipeline.
+ */
+ protected static abstract class PipelineEmitter
+ {
+ private File file;
+ private String basePackage;
+ private String baseName; // does not include package!
+ private String outputDir;
+
+ /**
+ * @param outputDir the directory into which the pipeline classes will be
+ * generated.
+ * @param baseInterfaceClassName the full class name (including package,
+ * e.g. "java.lang.String") of the interface that the pipeline wraps
+ * @exception IllegalArgumentException if classToComposeAround is not an
+ * interface.
+ */
+ public PipelineEmitter(String outputDir, String baseInterfaceClassName)
+ {
+ int lastDot = baseInterfaceClassName.lastIndexOf('.');
+ if (lastDot == -1)
+ {
+ // no package, class is at root level
+ this.baseName = baseInterfaceClassName;
+ this.basePackage = null;
+ }
+ else
+ {
+ this.baseName = baseInterfaceClassName.substring(lastDot+1);
+ this.basePackage = baseInterfaceClassName.substring(0, lastDot);
+ }
+
+ this.outputDir = outputDir;
+ }
+
+ public void emit(List/*<Method>*/ methodsToWrap) throws IOException
+ {
+ String pipelineClassName = getPipelineName();
+ this.file = new File(outputDir + File.separatorChar + pipelineClassName + ".java");
+ String parentDir = file.getParent();
+ if (parentDir != null)
+ {
+ File pDirFile = new File(parentDir);
+ pDirFile.mkdirs();
+ }
+
+ PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(file)));
+
+ CodeGenUtils.emitJavaHeaders(output,
+ basePackage,
+ pipelineClassName,
+ true,
+ new String[] { "java.io.*" },
+ new String[] { "public" },
+ new String[] { baseName },
+ null,
+ new CodeGenUtils.EmissionCallback() {
+ public void emit(PrintWriter w) { emitClassDocComment(w); }
+ }
+ );
+
+ preMethodEmissionHook(output);
+
+ constructorHook(output);
+
+ for (int i = 0; i < methodsToWrap.size(); ++i)
+ {
+ Method m = (Method)methodsToWrap.get(i);
+ emitMethodDocComment(output, m);
+ emitSignature(output, m);
+ emitBody(output, m);
+ }
+
+ postMethodEmissionHook(output);
+
+ output.println();
+ output.print(" private " + baseName + " " + getDownstreamObjectName() + ";");
+
+ // end the class
+ output.println();
+ output.print("} // end class ");
+ output.println(pipelineClassName);
+
+ output.flush();
+ output.close();
+ }
+
+ /** Get the name of the object through which API calls should be routed. */
+ protected String getDownstreamObjectName()
+ {
+ return "downstream" + baseName;
+ }
+
+ protected void emitMethodDocComment(PrintWriter output, Method m)
+ {
+ }
+
+ protected void emitSignature(PrintWriter output, Method m)
+ {
+ output.print(" public ");
+ output.print(' ');
+ output.print(m.getReturnType().getName());
+ output.print(' ');
+ output.print(m.getName());
+ output.print('(');
+ output.print(getArgListAsString(m, true, true));
+ output.println(")");
+ }
+
+ protected void emitBody(PrintWriter output, Method m)
+ {
+ output.println(" {");
+ output.print(" ");
+ Class retType = m.getReturnType();
+
+ preDownstreamCallHook(output, m);
+
+ if (retType != Void.TYPE)
+ {
+ output.print(JavaType.createForClass(retType).getName());
+ output.print(" _res = ");
+ }
+ output.print(getDownstreamObjectName());
+ output.print('.');
+ output.print(m.getName());
+ output.print('(');
+ output.print(getArgListAsString(m, false, true));
+ output.println(");");
+
+ postDownstreamCallHook(output, m);
+
+ if (retType != Void.TYPE)
+ {
+ output.println(" return _res;");
+ }
+ output.println(" }");
+
+ }
+
+ private String getArgListAsString(Method m, boolean includeArgTypes, boolean includeArgNames)
+ {
+ StringBuffer buf = new StringBuffer(256);
+ if (!includeArgNames && !includeArgTypes)
+ {
+ throw new IllegalArgumentException(
+ "Cannot generate arglist without both arg types and arg names");
+ }
+
+ Class[] argTypes = m.getParameterTypes();
+ for (int i = 0; i < argTypes.length; ++i)
+ {
+ if (includeArgTypes)
+ {
+ buf.append(JavaType.createForClass(argTypes[i]).getName());
+ buf.append(' ');
+ }
+
+ if (includeArgNames)
+ {
+ buf.append("arg");
+ buf.append(i);
+ }
+ if (i < argTypes.length-1) { buf.append(','); }
+ }
+
+ return buf.toString();
+ }
+
+ /** The name of the class around which this pipeline is being
+ * composed. E.g., if this pipeline was constructed with
+ * "java.util.Set" as the baseInterfaceClassName, then this method will
+ * return "Set".
+ */
+ protected String getBaseInterfaceName()
+ {
+ return baseName;
+ }
+
+ /** Get the name for this pipeline class. */
+ protected abstract String getPipelineName();
+
+ /**
+ * Called after the class headers have been generated, but before any
+ * method wrappers have been generated.
+ */
+ protected abstract void preMethodEmissionHook(PrintWriter output);
+
+ /**
+ * Emits the constructor for the pipeline; called after the preMethodEmissionHook.
+ */
+ protected void constructorHook(PrintWriter output) {
+ output.print( " public " + getPipelineName() + "(" + baseName + " ");
+ output.println(getDownstreamObjectName() + ")");
+ output.println(" {");
+ output.print( " this." + getDownstreamObjectName());
+ output.println(" = " + getDownstreamObjectName() + ";");
+ output.println(" }");
+ output.println();
+ }
+
+ /**
+ * Called after the method wrappers have been generated, but before the
+ * closing parenthesis of the class is emitted.
+ */
+ protected abstract void postMethodEmissionHook(PrintWriter output);
+
+ /**
+ * Called before the pipeline routes the call to the downstream object.
+ */
+ protected abstract void preDownstreamCallHook(PrintWriter output, Method m);
+
+ /**
+ * Called after the pipeline has routed the call to the downstream object,
+ * but before the calling function exits or returns a value.
+ */
+ protected abstract void postDownstreamCallHook(PrintWriter output, Method m);
+
+ /** Emit a Javadoc comment for this pipeline class. */
+ protected abstract void emitClassDocComment(PrintWriter output);
+
+ } // end class PipelineEmitter
+
+ //-------------------------------------------------------
+
+ protected class DebugPipeline extends PipelineEmitter
+ {
+ String className;
+ String baseInterfaceClassName;
+ public DebugPipeline(String outputDir, String baseInterfaceClassName)
+ {
+ super(outputDir, baseInterfaceClassName);
+ className = "Debug" + getBaseInterfaceName();
+ }
+
+ protected String getPipelineName()
+ {
+ return className;
+ }
+
+ protected void preMethodEmissionHook(PrintWriter output)
+ {
+ }
+
+ protected void postMethodEmissionHook(PrintWriter output)
+ {
+ output.println(" private void checkGLGetError(String caller)");
+ output.println(" {");
+ output.println(" // Debug code to make sure the pipeline is working; leave commented out unless testing this class");
+ output.println(" //System.err.println(\"Checking for GL errors " +
+ "after call to \" + caller + \"()\");");
+ output.println();
+ output.println(" int err = " +
+ getDownstreamObjectName() +
+ ".glGetError();");
+ output.println(" if (err == GL_NO_ERROR) { return; }");
+ output.println();
+ output.println(" StringBuffer buf = new StringBuffer(");
+ output.println(" \"glGetError() returned the following error codes " +
+ "after a call to \" + caller + \"(): \");");
+ output.println();
+ output.println(" // Loop repeatedly to allow for distributed GL implementations,");
+ output.println(" // as detailed in the glGetError() specification");
+ output.println(" do {");
+ output.println(" switch (err) {");
+ output.println(" case GL_INVALID_ENUM: buf.append(\"GL_INVALID_ENUM \"); break;");
+ output.println(" case GL_INVALID_VALUE: buf.append(\"GL_INVALID_VALUE \"); break;");
+ output.println(" case GL_INVALID_OPERATION: buf.append(\"GL_INVALID_OPERATION \"); break;");
+ output.println(" case GL_STACK_OVERFLOW: buf.append(\"GL_STACK_OVERFLOW \"); break;");
+ output.println(" case GL_STACK_UNDERFLOW: buf.append(\"GL_STACK_UNDERFLOW \"); break;");
+ output.println(" case GL_OUT_OF_MEMORY: buf.append(\"GL_OUT_OF_MEMORY \"); break;");
+ output.println(" case GL_NO_ERROR: throw new InternalError(\"Should not be treating GL_NO_ERROR as error\");");
+ output.println(" default: throw new InternalError(\"Unknown glGetError() return value: \" + err);");
+ output.println(" }");
+ output.println( " } while ((err = " +
+ getDownstreamObjectName() +
+ ".glGetError()) != GL_NO_ERROR);");
+ output.println(" throw new GLException(buf.toString());");
+ output.println(" }");
+
+ output.println(" /** True if the pipeline is inside a glBegin/glEnd pair.*/");
+ output.println(" private boolean insideBeginEndPair = false;");
+ output.println();
+
+ }
+ protected void emitClassDocComment(PrintWriter output)
+ {
+ output.println("/** <P> Composable pipline which wraps an underlying {@link GL} implementation,");
+ output.println(" providing error checking after each OpenGL method call. If an error occurs,");
+ output.println(" causes a {@link GLException} to be thrown at exactly the point of failure.");
+ output.println(" Sample code which installs this pipeline: </P>");
+ output.println();
+ output.println("<PRE>");
+ output.println(" drawable.setGL(new DebugGL(drawable.getGL()));");
+ output.println("</PRE>");
+ output.println("*/");
+ }
+
+ protected void preDownstreamCallHook(PrintWriter output, Method m)
+ {
+ }
+
+ protected void postDownstreamCallHook(PrintWriter output, Method m)
+ {
+ if (m.getName().equals("glBegin"))
+ {
+ output.println(" insideBeginEndPair = true;");
+ output.println(" // NOTE: can't check glGetError(); it's not allowed inside glBegin/glEnd pair");
+ }
+ else
+ {
+ if (m.getName().equals("glEnd"))
+ {
+ output.println(" insideBeginEndPair = false;");
+ }
+
+ // calls to glGetError() are only allowed outside of glBegin/glEnd pairs
+ output.println(" checkGLGetError(\"" + m.getName() + "\");");
+ }
+ }
+
+ } // end class DebugPipeline
+
+ //-------------------------------------------------------
+
+ protected class TracePipeline extends PipelineEmitter
+ {
+ String className;
+ String baseInterfaceClassName;
+ public TracePipeline(String outputDir, String baseInterfaceClassName)
+ {
+ super(outputDir, baseInterfaceClassName);
+ className = "Trace" + getBaseInterfaceName();
+ }
+
+ protected String getPipelineName()
+ {
+ return className;
+ }
+
+ protected void preMethodEmissionHook(PrintWriter output)
+ {
+ }
+
+ protected void constructorHook(PrintWriter output) {
+ output.print( " public " + getPipelineName() + "(" + getBaseInterfaceName() + " ");
+ output.println(getDownstreamObjectName() + ", PrintStream " + getOutputStreamName() + ")");
+ output.println(" {");
+ output.print( " this." + getDownstreamObjectName());
+ output.println(" = " + getDownstreamObjectName() + ";");
+ output.print( " this." + getOutputStreamName());
+ output.println(" = " + getOutputStreamName() + ";");
+ output.println(" }");
+ output.println();
+ }
+
+ protected void postMethodEmissionHook(PrintWriter output)
+ {
+ output.println("private PrintStream " + getOutputStreamName() + ";");
+ }
+ protected void emitClassDocComment(PrintWriter output)
+ {
+ output.println("/** <P> Composable pipline which wraps an underlying {@link GL} implementation,");
+ output.println(" providing tracing information to a user-specified {@link java.io.PrintStream}");
+ output.println(" before after each OpenGL method call. Sample code which installs this pipeline: </P>");
+ output.println();
+ output.println("<PRE>");
+ output.println(" drawable.setGL(new TraceGL(drawable.getGL(), System.err));");
+ output.println("</PRE>");
+ output.println("*/");
+ }
+
+ protected void preDownstreamCallHook(PrintWriter output, Method m)
+ {
+ output.println(getOutputStreamName() + ".println(\"Entered " + m.getName() + "\");");
+ output.print(" ");
+ }
+
+ protected void postDownstreamCallHook(PrintWriter output, Method m)
+ {
+ output.println(" " + getOutputStreamName() + ".println(\"Exited " + m.getName() + "\");");
+ }
+
+ private String getOutputStreamName() {
+ return "stream";
+ }
+
+ } // end class TracePipeline
+}
diff --git a/src/net/java/games/gluegen/opengl/BuildStaticGLInfo.java b/src/net/java/games/gluegen/opengl/BuildStaticGLInfo.java
new file mode 100644
index 000000000..ed0c83445
--- /dev/null
+++ b/src/net/java/games/gluegen/opengl/BuildStaticGLInfo.java
@@ -0,0 +1,258 @@
+/*
+ * 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
+ * MIDROSYSTEMS, 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 java.util.regex.*;
+
+ /**
+ * Builds the StaticGLInfo class from the OpenGL header files (i.e., gl.h
+ * and glext.h) whose paths were passed as arguments to {@link
+ * #main(String[])}.
+ *
+ * It relies upon the assumption that a function's membership is scoped by
+ * preprocessor blocks in the header files that match the following pattern:
+ * <br>
+ *
+ * <pre>
+ *
+ * #ifndef GL_XXXX
+ * GLAPI <returnType> <APIENTRY|GLAPIENTRY> glFuncName(<params>)
+ * #endif GL_XXXX
+ *
+ * </pre>
+ *
+ * For example, if it parses the following data:
+ *
+ * <pre>
+ *
+ * #ifndef GL_VERSION_1_3
+ * GLAPI void APIENTRY glActiveTexture (GLenum);
+ * GLAPI void APIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *);
+ * GLAPI void <APIENTRY|GLAPIENTRY> glFuncName(<params>)
+ * #endif GL_VERSION_1_3
+ *
+ * #ifndef GL_ARB_texture_compression
+ * GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+ * GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+ * #endif
+ *
+ * </pre>
+ *
+ * It will associate
+ * <code> glActiveTexture </code> and
+ * <code> glMultiTexCoord1dv </code>
+ * with the symbol
+ * <code> GL_VERSION_1_3 </code>,
+ * and associate
+ * <code> glCompressedTexImage2DARB </code> and
+ * <code> glCompressedTexImage3DARB </code>
+ * with the symbol
+ * <code> GL_ARB_texture_compression </code>.
+ * */
+public class BuildStaticGLInfo
+{
+ protected static Pattern funcPattern =
+ Pattern.compile("^(GLAPI|extern)?(\\s*)(\\w+)(\\*)?(\\s+)(APIENTRY|WINAPI)?(\\s*)([w]?gl\\w+)\\s?(\\(.*)");
+ protected static Pattern associationPattern =
+ Pattern.compile("\\#ifndef ([W]?GL[X]?_[A-Za-z0-9_]+)");
+
+ /**
+ * The first argument is the package to which the StaticGLInfo class
+ * belongs, the second is the path to the directory in which that package's
+ * classes reside, and the remaining arguments are paths to the C header
+ * files that should be parsed
+ */
+ public static void main(String[] args)
+ {
+ String packageName = args[0];
+ String packageDir = args[1];
+
+ String[] cHeaderFilePaths = new String[args.length-2];
+ System.arraycopy(args, 2, cHeaderFilePaths, 0, cHeaderFilePaths.length);
+
+ BuildStaticGLInfo builder = new BuildStaticGLInfo();
+ try
+ {
+ File file = new File(packageDir + File.separatorChar + "StaticGLInfo.java");
+ String parentDir = file.getParent();
+ if (parentDir != null)
+ {
+ File pDirFile = new File(parentDir);
+ pDirFile.mkdirs();
+ }
+
+ PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));
+ builder.build(writer, packageName, cHeaderFilePaths);
+
+ writer.flush();
+ writer.close();
+ }
+ catch (Exception e)
+ {
+ StringBuffer buf = new StringBuffer("{ ");
+ for (int i = 0; i < cHeaderFilePaths.length; ++i)
+ {
+ buf.append(cHeaderFilePaths[i]);
+ buf.append(" ");
+ }
+ buf.append('}');
+ throw new RuntimeException(
+ "Error building StaticGLInfo.java from " + buf.toString(), e);
+ }
+ }
+
+ protected void build(PrintWriter output, String packageName, String[] cHeaderFilePaths) throws IOException
+ {
+ HashMap groupToFuncHash = new HashMap(50);
+ for (int i = 0; i < cHeaderFilePaths.length; ++i)
+ {
+ process(groupToFuncHash, new FileReader(cHeaderFilePaths[i]));
+ }
+
+ emitJavaCode(output, packageName, groupToFuncHash);
+ }
+
+ protected void process(HashMap groupToFuncHash, FileReader headerFile) throws IOException
+ {
+ BufferedReader reader = new BufferedReader(headerFile);
+ String line, activeAssociation = null;
+ Matcher m;
+ while ((line = reader.readLine()) != null)
+ {
+ // see if we're inside a #ifndef GL_XXX block and matching a function
+ if (activeAssociation != null && (m = funcPattern.matcher(line)).matches())
+ {
+ // We found a new function associated with the last #ifndef block we
+ // were associated with
+
+ String funcName = m.group(8);
+ HashSet funcsForGroup = (HashSet)groupToFuncHash.get(activeAssociation);
+ if (funcsForGroup == null)
+ {
+ funcsForGroup = new HashSet(8);
+ groupToFuncHash.put(activeAssociation, funcsForGroup);
+ }
+ funcsForGroup.add(funcName);
+
+ //System.err.println("FOUND ASSOCIATION FOR " + activeAssociation + ": " + funcName);
+ }
+ else if ((m = associationPattern.matcher(line)).matches())
+ {
+ // found a new #ifndef GL_XXX block
+ activeAssociation = m.group(1);
+
+ //System.err.println("FOUND NEW ASSOCIATION BLOCK: " + activeAssociation);
+ }
+ }
+ }
+
+ protected void emitJavaCode(PrintWriter output, String packageName, HashMap groupToFuncHash)
+ {
+ output.println("package " + packageName + ";");
+ output.println();
+ output.println("import java.util.*;");
+ output.println();
+ output.println("public final class StaticGLInfo");
+ output.println("{");
+
+ output.println(" // maps function names to the extension string or OpenGL");
+ output.println(" // specification version string to which they correspond.");
+ output.println(" private static HashMap funcToAssocMap = null;");
+ output.println();
+
+ output.println(" /**");
+ output.println(" * Returns the OpenGL extension string or GL_VERSION string with which the");
+ output.println(" * given function is associated. <P>");
+ output.println(" *");
+ output.println(" * If the");
+ output.println(" * function is part of the OpenGL core, the returned value will be");
+ output.println(" * GL_VERSION_XXX where XXX represents the OpenGL version of which the");
+ output.println(" * function is a member (XXX will be of the form \"A\" or \"A_B\" or \"A_B_C\";");
+ output.println(" * e.g., GL_VERSION_1_2_1 for OpenGL version 1.2.1).");
+ output.println(" *");
+ output.println(" * If the function is an extension function, the returned value will the");
+ output.println(" * OpenGL extension string for the extension to which the function");
+ output.println(" * corresponds. For example, if glLoadTransposeMatrixfARB is the argument,");
+ output.println(" * GL_ARB_transpose_matrix will be the value returned.");
+ output.println(" * Please see http://oss.sgi.com/projects/ogl-sample/registry/index.html for");
+ output.println(" * a list of extension names and the functions they expose.");
+ output.println(" *");
+ output.println(" * If the function specified is not part of any known OpenGL core version or");
+ output.println(" * extension, then NULL will be returned.");
+ output.println(" */");
+ output.println(" public static String getFunctionAssociation(String glFunctionName)");
+ output.println(" {");
+ output.println(" if (funcToAssocMap == null) { init(); }");
+ output.println(" return (String)funcToAssocMap.get(glFunctionName);");
+ output.println(" }");
+ output.println();
+
+ output.println(" private static void init()");
+ output.println(" {");
+ output.println(" funcToAssocMap = new HashMap(1536); // approximate max capacity");
+ output.println(" String group;");
+ ArrayList sets = new ArrayList(groupToFuncHash.keySet());
+ Collections.sort(sets);
+ for (int i = 0; i < sets.size(); ++i)
+ {
+ String groupName = (String) sets.get(i);
+ //System.err.println(groupName); // debug
+ output.println();
+ output.println(" //----------------------------------------------------------------");
+ output.println(" // " + groupName);
+ output.println(" //----------------------------------------------------------------");
+ output.println(" group = \"" + groupName + "\";");
+ HashSet funcs = (HashSet)groupToFuncHash.get(groupName);
+ Iterator funcIter = funcs.iterator();
+ while (funcIter.hasNext())
+ {
+ String funcName = (String)funcIter.next();
+ //System.err.println(" " + funcName); // debug
+ output.println(" funcToAssocMap.put(\"" + funcName + "\", group);");
+ }
+ }
+ output.println(" }");
+
+ output.println("} // end class StaticGLInfo");
+ }
+
+}
diff --git a/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java b/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java
new file mode 100644
index 000000000..cd0554dc3
--- /dev/null
+++ b/src/net/java/games/gluegen/opengl/CGLPAWrapperEmitter.java
@@ -0,0 +1,201 @@
+/*
+ * 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
+ * MIDROSYSTEMS, 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();
+
+ 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()
+ );
+
+ 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)
+ {
+ super.emitBodyVariablePreCallSetup(writer);
+
+ // 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()) {
+ writer.print(pointerConversionArgumentName(i));
+ } else {
+ if (javaType.isString()) { writer.print("_UTF8"); }
+ writer.print(binding.getArgumentName(i));
+ }
+ }
+ }
+ writer.println(");");
+ }
+
+ /** 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
diff --git a/src/net/java/games/gluegen/opengl/ConvertFromGL4Java.java b/src/net/java/games/gluegen/opengl/ConvertFromGL4Java.java
new file mode 100644
index 000000000..c026dbd50
--- /dev/null
+++ b/src/net/java/games/gluegen/opengl/ConvertFromGL4Java.java
@@ -0,0 +1,91 @@
+/*
+ * 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
+ * MIDROSYSTEMS, 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.*;
+
+public class ConvertFromGL4Java {
+ public static void main(String[] args) throws IOException {
+ for (int i = 0; i < args.length; i++) {
+ convert(new File(args[i]));
+ }
+ }
+
+ private static void convert(File src) throws IOException {
+ File orig = new File(src.getAbsolutePath() + ".orig");
+ if (!src.renameTo(orig)) {
+ throw new IOException("Error renaming original file to " + orig);
+ }
+ File dest = src;
+ BufferedReader reader = new BufferedReader(new FileReader(orig));
+ BufferedWriter writer = new BufferedWriter(new FileWriter(dest));
+ boolean handledImports = false;
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ String trimmed = line.trim();
+ boolean isImport = false;
+ if (trimmed.startsWith("import gl4java")) {
+ line = "import net.java.games.jogl.*;";
+ isImport = true;
+ }
+ if (!isImport ||
+ (isImport && !handledImports)) {
+ line = line.replaceAll("GLFunc14", "GL");
+ line = line.replaceAll("GLUFunc14", "GLU");
+ line = line.replaceAll("GLFunc", "GL");
+ line = line.replaceAll("GLUFunc", "GLU");
+ line = line.replaceAll("implements GLEnum,", "implements ");
+ line = line.replaceAll(", GLEnum\\s", " ");
+ line = line.replaceAll("GLEnum,", "");
+ line = line.replaceAll("GLEnum.", "");
+ line = line.replaceAll("GLEnum", "");
+ line = line.replaceAll("GL_", "GL.GL_");
+ writer.write(line);
+ writer.newLine();
+ if (isImport) {
+ handledImports = true;
+ }
+ }
+ }
+ writer.flush();
+ reader.close();
+ writer.close();
+ }
+}
diff --git a/src/net/java/games/gluegen/opengl/GLEmitter.java b/src/net/java/games/gluegen/opengl/GLEmitter.java
new file mode 100644
index 000000000..27cc07e2c
--- /dev/null
+++ b/src/net/java/games/gluegen/opengl/GLEmitter.java
@@ -0,0 +1,330 @@
+/*
+ * 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
+ * MIDROSYSTEMS, 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.text.MessageFormat;
+import java.util.*;
+import net.java.games.gluegen.*;
+import net.java.games.gluegen.cgram.types.*;
+
+/**
+ * A subclass of JavaEmitter that modifies the normal emission of C and Java
+ * code in order to allow a high-performance, cross-platform binding of Java
+ * to OpenGL.
+ */
+public class GLEmitter extends JavaEmitter
+{
+ public static final String PROCADDRESS_VAR_PREFIX = "_addressof_";
+ protected static final String WRAP_PREFIX = "dispatch_";
+ private TypeDictionary typedefDictionary;
+ private PrintWriter tableWriter;
+ private String tableClassName = "ProcAddressTable";
+ private int numProcAddressEntries;
+
+ public void beginFunctions(TypeDictionary typedefDictionary,
+ TypeDictionary structDictionary,
+ Map canonMap) throws Exception
+ {
+ this.typedefDictionary = typedefDictionary;
+
+ if (getConfig().emitImpl()) {
+ cWriter().println("#include <assert.h> /* this include emitted by GLEmitter.java */");
+ cWriter().println();
+ }
+
+ if (((GLConfiguration)getConfig()).emitProcAddressTable())
+ {
+ beginGLProcAddressTable();
+ }
+ super.beginFunctions(typedefDictionary, structDictionary, canonMap);
+ }
+
+ public void endFunctions() throws Exception
+ {
+ if (((GLConfiguration)getConfig()).emitProcAddressTable())
+ {
+ endGLProcAddressTable();
+ }
+ super.endFunctions();
+ }
+
+ public void beginStructs(TypeDictionary typedefDictionary,
+ TypeDictionary structDictionary,
+ Map canonMap) throws Exception {
+ super.beginStructs(typedefDictionary, structDictionary, canonMap);
+ }
+
+ protected JavaConfiguration createConfig() {
+ return new GLConfiguration();
+ }
+
+ protected Iterator generateMethodBindingEmitters(FunctionSymbol sym) throws Exception
+ {
+ Iterator defaultEmitters = super.generateMethodBindingEmitters(sym);
+
+ // if the superclass didn't generate any bindings for the symbol, let's
+ // honor that (for example, the superclass might have caught an Ignore
+ // direction that matched the symbol's name).
+ if (!defaultEmitters.hasNext())
+ {
+ return defaultEmitters;
+ }
+
+ // Don't do anything special if this symbol doesn't require passing of
+ // Opengl procedure addresses in order to function correctly.
+ if (!needsProcAddressWrapper(sym) || getConfig().isUnimplemented(sym.getName()))
+ {
+ return defaultEmitters;
+ }
+
+ // 9 is default # expanded bindings for void*
+ ArrayList modifiedEmitters = new ArrayList(9);
+
+ if (((GLConfiguration)getConfig()).emitProcAddressTable())
+ {
+ // emit an entry in the GL proc address table for this method.
+ emitGLProcAddressTableEntryForSymbol(sym);
+ }
+
+ while (defaultEmitters.hasNext())
+ {
+ FunctionEmitter emitter = (FunctionEmitter)defaultEmitters.next();
+ if (emitter instanceof JavaMethodBindingEmitter)
+ {
+ JavaMethodBindingEmitter newEmitter =
+ generateModifiedEmitter((JavaMethodBindingEmitter)emitter);
+ if (newEmitter != null) {
+ modifiedEmitters.add(newEmitter);
+ }
+ }
+ else if (emitter instanceof CMethodBindingEmitter)
+ {
+ modifiedEmitters.add(
+ generateModifiedEmitter((CMethodBindingEmitter)emitter));
+ }
+ else
+ {
+ throw new RuntimeException("Unexpected emitter type: " +
+ emitter.getClass().getName());
+ }
+ }
+
+ return modifiedEmitters.iterator();
+ }
+
+ /**
+ * Returns the name of the typedef for a pointer to the GL function
+ * represented by the argument. For example, if the argument is the function
+ * "glFuncName", the value returned will be "PFNGLFUNCNAMEPROC". This
+ * returns a valid string regardless of whether or not the typedef is
+ * actually defined.
+ */
+ static String getGLFunctionPointerTypedefName(FunctionSymbol sym)
+ {
+ String symName = sym.getName();
+ StringBuffer buf = new StringBuffer(symName.length() + 8);
+ buf.append("PFN");
+ buf.append(symName.toUpperCase());
+ buf.append("PROC");
+ return buf.toString();
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ private JavaMethodBindingEmitter generateModifiedEmitter(JavaMethodBindingEmitter baseJavaEmitter)
+ {
+ if (!(baseJavaEmitter instanceof JavaMethodBindingImplEmitter)) {
+ // We only want to wrap the native entry point in the implementation
+ // class, not the public interface in the interface class.
+ //
+ // If the superclass has generated a "0" emitter for this routine because
+ // it needs argument conversion or similar, filter that out since we will
+ // be providing such an emitter ourselves. Otherwise return the emitter
+ // unmodified.
+ if (baseJavaEmitter.isForNIOBufferBaseRoutine())
+ return null;
+ return baseJavaEmitter;
+ }
+ return new JavaGLPAWrapperEmitter(baseJavaEmitter);
+ }
+
+ private CMethodBindingEmitter generateModifiedEmitter(CMethodBindingEmitter baseCEmitter)
+ {
+ // The C-side JNI binding for this particular function will have an
+ // extra final argument, which is the address (the OpenGL procedure
+ // address) of the function it needs to call
+ CGLPAWrapperEmitter res = new CGLPAWrapperEmitter(baseCEmitter);
+ MessageFormat exp = baseCEmitter.getReturnValueCapacityExpression();
+ if (exp != null) {
+ res.setReturnValueCapacityExpression(exp);
+ }
+ return res;
+ }
+
+ private boolean needsProcAddressWrapper(FunctionSymbol sym)
+ {
+ String symName = sym.getName();
+
+ // We should only wrap the GL symbol if its function pointer typedef has
+ // been defined (most likely in glext.h).
+ String funcPointerTypedefName = getGLFunctionPointerTypedefName(sym);
+ boolean shouldWrap = typedefDictionary.containsKey(funcPointerTypedefName);
+ //System.err.println(funcPointerTypedefName + " defined: " + shouldWrap);
+
+ if (!shouldWrap)
+ {
+ //System.err.println("WARNING (GL): *not* run-time linking: " + sym +
+ // "(" + funcPointerTypedefName + " undefined)");
+ }
+ return shouldWrap;
+ }
+
+ private void beginGLProcAddressTable() throws Exception
+ {
+ String implPackageName = getImplPackageName();
+ String jImplRoot =
+ getJavaOutputDir() + File.separator +
+ CodeGenUtils.packageAsPath(implPackageName);
+
+ // HACK: until we have a way to make the impl dir different from the
+ // WindowsGLImpl dir and the interface dir
+ //tableWriter = openFile(jImplRoot + File.separator + tableClassName + ".java");
+ File tmpFile = new File(jImplRoot);
+ tmpFile = tmpFile.getParentFile();
+ tmpFile = new File(tmpFile, tableClassName + ".java");
+ tableWriter = openFile(tmpFile.getPath());
+ // tableWriter = openFile(jImplRoot + File.separator + ".." + File.separator + tableClassName + ".java");
+
+ CodeGenUtils.emitAutogeneratedWarning(tableWriter, this);
+
+ // HACK: until we have a way to make the impl dir different from the
+ // WindowsGLImpl dir and the interface dir
+ //tableWriter.println("package " + implPackageName + ";");
+ tableWriter.println("package " + getJavaPackageName() + ".impl;");
+ tableWriter.println();
+ tableWriter.println("/**");
+ tableWriter.println(" * This table is a cache of the native pointers to OpenGL extension");
+ tableWriter.println(" * functions, to be used for run-time linking of these extensions. ");
+ tableWriter.println(" * These pointers are obtained by the OpenGL context via a ");
+ tableWriter.println(" * platform-specific function (e.g., wglGetProcAddress() on Win32,");
+ tableWriter.println(" * glXGetProcAddress() on X11, etc). If the member variable ");
+ tableWriter.println(" * " + PROCADDRESS_VAR_PREFIX + "glFuncName is non-zero then function");
+ tableWriter.println(" * \"glFuncName\" can be called through the associated GLContext; ");
+ tableWriter.println(" * if it is 0, then the extension is not available and cannot be called.");
+ tableWriter.println(" */");
+ tableWriter.println("public class " + tableClassName);
+ tableWriter.println("{");
+ numProcAddressEntries = 0;
+ }
+
+ private void endGLProcAddressTable() throws Exception
+ {
+ PrintWriter w = tableWriter;
+ w.print(" protected static long __PROCADDRESSINDEX__LASTINDEX = ");
+ w.print(numProcAddressEntries-1);
+ w.println(';');
+
+ w.println();
+ w.println(" /**");
+ w.println(" * This is a convenience method to get (by name) the native function ");
+ w.println(" * pointer for a given extension function. It lets you avoid ");
+ w.println(" * having to manually compute the " + PROCADDRESS_VAR_PREFIX + "<glFunctionName>");
+ w.println(" * member variable name and look it up via reflection; it also");
+ w.println(" * will throw an exception if you try to get the address of an");
+ w.println(" * unknown GL extension, or one that is statically linked ");
+ w.println(" * and therefore does not have a valid GL procedure address. ");
+ w.println(" */");
+ w.println(" public long getAddressFor(String glFunctionName) {");
+ w.println(" String addressFieldName = net.java.games.gluegen.opengl.GLEmitter.PROCADDRESS_VAR_PREFIX + glFunctionName;");
+ w.println(" try { ");
+ w.println(" java.lang.reflect.Field addressField = this.getClass().getField(addressFieldName);");
+ w.println(" return addressField.getLong(this);");
+ w.println(" } catch (Exception e) {");
+ w.println(" // The user is calling a bogus function or one which is not runtime");
+ w.println(" // linked (extensions and core post-OpenGL 1.1 functions are runtime linked)");
+ w.println(" if (!FunctionAvailabilityCache.isPartOfGLCore(\"1.1\", glFunctionName)) ");
+ w.println(" {");
+ w.println(" throw new RuntimeException(" );
+ w.println(" \"WARNING: Address query failed for \\\"\" + glFunctionName +");
+ w.println(" \"\\\"; either it's not runtime linked or it is not a known \" +");
+ w.println(" \"OpenGL function\", e);");
+ w.println(" }");
+ w.println(" } ");
+ w.println(" assert(false); // should never get this far");
+ w.println(" return 0;");
+ w.println(" }");
+
+ w.println("} // end of class " + tableClassName);
+ w.flush();
+ w.close();
+ }
+
+ private void emitGLProcAddressTableEntryForSymbol(FunctionSymbol cFunc)
+ {
+ tableWriter.print(" public static long ");
+ tableWriter.print(PROCADDRESS_VAR_PREFIX);
+ tableWriter.print(cFunc.getName());
+ tableWriter.println(";");
+ ++numProcAddressEntries;
+ }
+
+ protected static class GLConfiguration extends JavaConfiguration
+ {
+ private boolean emitProcAddressTable = false;
+
+ protected void dispatch(String cmd, StringTokenizer tok, File file, String filename, int lineNo) throws IOException {
+ if (cmd.equalsIgnoreCase("EmitProcAddressTable"))
+ {
+ emitProcAddressTable =
+ readBoolean("EmitProcAddressTable", tok, filename, lineNo).booleanValue();
+ }
+ else
+ {
+ super.dispatch(cmd,tok,file,filename,lineNo);
+ }
+ }
+
+ public boolean emitProcAddressTable() { return emitProcAddressTable; }
+ } // end class GLConfiguration
+}
+
diff --git a/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java b/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java
new file mode 100644
index 000000000..e0a098f2a
--- /dev/null
+++ b/src/net/java/games/gluegen/opengl/JavaGLPAWrapperEmitter.java
@@ -0,0 +1,178 @@
+/*
+ * 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
+ * MIDROSYSTEMS, 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 JavaGLPAWrapperEmitter extends JavaMethodBindingImplEmitter
+{
+ private static final CommentEmitter commentEmitterForWrappedMethod =
+ new WrappedMethodCommentEmitter();
+
+ private JavaMethodBindingEmitter emitterBeingWrapped;
+
+ public JavaGLPAWrapperEmitter(JavaMethodBindingEmitter methodToWrap)
+ {
+ super(methodToWrap.getBinding(), methodToWrap.getDefaultOutput(), methodToWrap.getRuntimeExceptionType());
+
+ if (methodToWrap.getBinding().hasContainingType())
+ {
+ throw new IllegalArgumentException(
+ "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);
+ }
+ protected int emitArguments(PrintWriter writer)
+ {
+ 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);
+ }
+
+ protected boolean needsBody() {
+ return true;
+ }
+
+ protected String getImplMethodName() {
+ return GLEmitter.WRAP_PREFIX + getBinding().getName();
+ }
+
+ 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 void emitPreCallSetup(MethodBinding binding, PrintWriter writer) {
+ super.emitPreCallSetup(binding, writer);
+ JavaType returnType = binding.getJavaReturnType();
+
+ MethodBinding wrappedBinding = emitterBeingWrapped.getBinding();
+ String procAddressVariable =
+ GLEmitter.PROCADDRESS_VAR_PREFIX + wrappedBinding.getName();
+
+ writer.print(" final long addr = context.getGLProcAddressTable().");
+ writer.print(procAddressVariable);
+ writer.println(';');
+ writer.println(" if (addr == 0) {");
+ writer.println(" throw new GLException(\"Method \\\"" + binding.getName() + "\\\" not available\");");
+ writer.println(" }");
+ }
+
+ protected int emitCallArguments(MethodBinding binding, PrintWriter writer) {
+ int numEmitted = super.emitCallArguments(binding, writer);
+ if (numEmitted > 0) {
+ writer.print(", ");
+ }
+ writer.print("addr");
+ return 1 + numEmitted;
+ }
+
+ /** This class emits the comment for the wrapper method */
+ private static class WrappedMethodCommentEmitter extends JavaMethodBindingEmitter.DefaultCommentEmitter {
+ protected void emitBeginning(FunctionEmitter methodEmitter, PrintWriter writer) {
+ writer.print("Encapsulates function pointer for OpenGL function <br>: ");
+ }
+ }
+} // end class JavaGLPAWrapperEmitter