aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java1089
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java347
-rwxr-xr-xsrc/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java297
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java456
-rwxr-xr-xsrc/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java124
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java305
-rwxr-xr-xsrc/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java192
-rwxr-xr-xsrc/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java485
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java193
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java62
10 files changed, 3550 insertions, 0 deletions
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
new file mode 100644
index 000000000..1bc5df959
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. 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 com.jogamp.gluegen.opengl;
+
+import com.jogamp.gluegen.*;
+
+import java.lang.reflect.*;
+import java.io.*;
+import java.nio.Buffer;
+import java.util.*;
+import java.util.ArrayList;
+
+public class BuildComposablePipeline {
+
+ public static final int GEN_DEBUG = 1 << 0; // default
+ public static final int GEN_TRACE = 1 << 1; // default
+ public static final int GEN_CUSTOM = 1 << 2;
+ public static final int GEN_PROLOG_XOR_DOWNSTREAM = 1 << 3;
+ int mode;
+ private String outputDir;
+ private String outputPackage;
+ private String outputName;
+ private Class<?> classToComposeAround;
+ private Class<?> classPrologOpt;
+ private Class<?> classDownstream;
+ // Only desktop OpenGL has immediate mode glBegin / glEnd
+ private boolean hasImmediateMode;
+ // Desktop OpenGL and GLES1 have GL_STACK_OVERFLOW and GL_STACK_UNDERFLOW errors
+ private boolean hasStackOverflow;
+
+ public static Class<?> getClass(String name) {
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName(name);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Could not find class \"" + name + "\"", e);
+ }
+ return clazz;
+ }
+
+ public static Method getMethod(Class<?> clazz, Method m) {
+ Method res = null;
+ try {
+ res = clazz.getMethod(m.getName(), m.getParameterTypes());
+ } catch (Exception e) {
+ }
+ return res;
+ }
+
+ public static void main(String[] args) {
+ String classToComposeAroundName = args[0];
+ Class<?> classPrologOpt, classDownstream;
+ Class<?> classToComposeAround = getClass(classToComposeAroundName);
+
+ String outputDir = args[1];
+ String outputPackage, outputName;
+ int mode;
+
+ if (args.length > 2) {
+ String outputClazzName = args[2];
+ outputPackage = getPackageName(outputClazzName);
+ outputName = getBaseClassName(outputClazzName);
+ classPrologOpt = getClass(args[3]);
+ classDownstream = getClass(args[4]);
+ mode = GEN_CUSTOM;
+ if (args.length > 5) {
+ if (args[5].equals("prolog_xor_downstream")) {
+ mode |= GEN_PROLOG_XOR_DOWNSTREAM;
+ }
+ }
+ } else {
+ outputPackage = getPackageName(classToComposeAroundName);
+ outputName = null; // TBD ..
+ classPrologOpt = null;
+ classDownstream = classToComposeAround;
+ mode = GEN_DEBUG | GEN_TRACE;
+ }
+
+ BuildComposablePipeline composer =
+ new BuildComposablePipeline(mode, outputDir, outputPackage, outputName, classToComposeAround, classPrologOpt, classDownstream);
+
+ try {
+ composer.emit();
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Error generating composable pipeline source files", e);
+ }
+ }
+
+ protected BuildComposablePipeline(int mode, String outputDir, String outputPackage, String outputName,
+ Class<?> classToComposeAround, Class<?> classPrologOpt, Class<?> classDownstream) {
+ this.mode = mode;
+ this.outputDir = outputDir;
+ this.outputPackage = outputPackage;
+ this.outputName = outputName;
+ this.classToComposeAround = classToComposeAround;
+ this.classPrologOpt = classPrologOpt;
+ this.classDownstream = classDownstream;
+
+ if (!classToComposeAround.isInterface()) {
+ throw new IllegalArgumentException(
+ classToComposeAround.getName() + " is not an interface class");
+ }
+
+ try {
+ hasImmediateMode =
+ (classToComposeAround.getMethod("glBegin", new Class<?>[]{Integer.TYPE}) != null);
+ } catch (Exception e) {
+ }
+
+ try {
+ hasStackOverflow =
+ (classToComposeAround.getField("GL_STACK_OVERFLOW") != null);
+ } catch (Exception e) {
+ }
+ }
+
+ /**
+ * Emit the java source code for the classes that comprise the composable
+ * pipeline.
+ */
+ public void emit() throws IOException {
+
+ List<Method> publicMethodsRaw = Arrays.asList(classToComposeAround.getMethods());
+
+ Set<PlainMethod> publicMethodsPlain = new HashSet<PlainMethod>();
+ for (Iterator<Method> iter = publicMethodsRaw.iterator(); iter.hasNext();) {
+ Method method = iter.next();
+ // Don't hook methods which aren't real GL methods,
+ // such as the synthetic "isGL2ES2" "getGL2ES2"
+ String name = method.getName();
+ boolean runHooks = name.startsWith("gl");
+ if (!name.startsWith("getGL") && !name.startsWith("isGL") && !name.equals("toString")) {
+ publicMethodsPlain.add(new PlainMethod(method, runHooks));
+ }
+ }
+
+ if (0 != (mode & GEN_DEBUG)) {
+ (new DebugPipeline(outputDir, outputPackage, classToComposeAround, classDownstream)).emit(publicMethodsPlain.iterator());
+ }
+ if (0 != (mode & GEN_TRACE)) {
+ (new TracePipeline(outputDir, outputPackage, classToComposeAround, classDownstream)).emit(publicMethodsPlain.iterator());
+ }
+ if (0 != (mode & GEN_CUSTOM)) {
+ (new CustomPipeline(mode, outputDir, outputPackage, outputName, classToComposeAround, classPrologOpt, classDownstream)).emit(publicMethodsPlain.iterator());
+ }
+ }
+
+ public static String getPackageName(String clazzName) {
+ int lastDot = clazzName.lastIndexOf('.');
+ if (lastDot == -1) {
+ // no package, class is at root level
+ return null;
+ }
+ return clazzName.substring(0, lastDot);
+ }
+
+ public static String getBaseClassName(String clazzName) {
+ int lastDot = clazzName.lastIndexOf('.');
+ if (lastDot == -1) {
+ // no package, class is at root level
+ return clazzName;
+ }
+ return clazzName.substring(lastDot + 1);
+ }
+
+ //-------------------------------------------------------
+ protected class PlainMethod {
+
+ Method m;
+ boolean runHooks;
+
+ PlainMethod(Method m, boolean runHooks) {
+ this.m = m;
+ this.runHooks = runHooks;
+ }
+
+ public Method getWrappedMethod() {
+ return m;
+ }
+
+ public boolean runHooks() {
+ return runHooks;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PlainMethod) {
+ PlainMethod b = (PlainMethod) obj;
+ boolean res =
+ m.getName().equals(b.m.getName())
+ && m.getModifiers() == b.m.getModifiers()
+ && m.getReturnType().equals(b.m.getReturnType())
+ && Arrays.equals(m.getParameterTypes(), b.m.getParameterTypes());
+ return res;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = m.getName().hashCode() ^ m.getModifiers() ^ m.getReturnType().hashCode();
+ Class<?>[] args = m.getParameterTypes();
+ for (int i = 0; i < args.length; i++) {
+ hash ^= args[i].hashCode();
+ }
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ Class<?>[] args = m.getParameterTypes();
+ StringBuilder argsString = new StringBuilder();
+ argsString.append("(");
+ for (int i = 0; i < args.length; i++) {
+ if (i > 0) {
+ argsString.append(", ");
+ }
+ argsString.append(args[i].getName());
+ }
+ argsString.append(")");
+ return m.toString()
+ + "\n\tname: " + m.getName()
+ + "\n\tmods: " + m.getModifiers()
+ + "\n\tretu: " + m.getReturnType()
+ + "\n\targs[" + args.length + "]: " + argsString.toString();
+ }
+ }
+
+ /**
+ * Emits a Java source file that represents one element of the composable
+ * pipeline.
+ */
+ protected abstract class PipelineEmitter {
+
+ private File file;
+ protected String basePackage;
+ protected String baseName; // does not include package!
+ protected String downstreamPackage;
+ protected String downstreamName; // does not include package!
+ protected String prologPackageOpt = null;
+ protected String prologNameOpt = null; // does not include package!
+ protected String outputDir;
+ protected String outputPackage;
+ protected Class<?> baseInterfaceClass;
+ protected Class<?> prologClassOpt = null;
+ protected Class<?> downstreamClass;
+
+ /**
+ * @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.
+ */
+ PipelineEmitter(String outputDir, String outputPackage, Class<?> baseInterfaceClass, Class<?> prologClassOpt, Class<?> downstreamClass) {
+ this.outputDir = outputDir;
+ this.outputPackage = outputPackage;
+ this.baseInterfaceClass = baseInterfaceClass;
+ this.prologClassOpt = prologClassOpt;
+ this.downstreamClass = downstreamClass;
+
+ basePackage = getPackageName(baseInterfaceClass.getName());
+ baseName = getBaseClassName(baseInterfaceClass.getName());
+ downstreamPackage = getPackageName(downstreamClass.getName());
+ downstreamName = getBaseClassName(downstreamClass.getName());
+ if (null != prologClassOpt) {
+ prologPackageOpt = getPackageName(prologClassOpt.getName());
+ prologNameOpt = getBaseClassName(prologClassOpt.getName());
+ }
+ }
+
+ public void emit(Iterator<PlainMethod> methodsToWrap) throws IOException {
+ String outputClassName = getOutputName();
+ this.file = new File(outputDir + File.separatorChar + outputClassName + ".java");
+ String parentDir = file.getParent();
+ if (parentDir != null) {
+ File pDirFile = new File(parentDir);
+ pDirFile.mkdirs();
+ }
+
+ PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(file)));
+
+ List<Class<?>> baseInterfaces = Arrays.asList(baseInterfaceClass.getInterfaces());
+ HashSet<Class<?>> clazzList = new HashSet<Class<?>>();
+ clazzList.add(baseInterfaceClass);
+ clazzList.addAll(baseInterfaces);
+ int ifNamesNumber = clazzList.size();
+
+ // keep original order ..
+ clazzList.clear();
+ String[] ifNames = new String[ifNamesNumber];
+ {
+ int i = 0;
+
+ for (Iterator<Class<?>> iter = baseInterfaces.iterator(); iter.hasNext();) {
+ Class<?> ifClass = iter.next();
+ if (!clazzList.contains(ifClass)) {
+ ifNames[i++] = ifClass.getName();
+ clazzList.add(ifClass);
+ }
+ }
+
+ if (null != baseInterfaceClass && !clazzList.contains(baseInterfaceClass)) {
+ ifNames[i++] = baseInterfaceClass.getName();
+ clazzList.add(baseInterfaceClass);
+ }
+ }
+
+ clazzList.add(downstreamClass);
+ if (null != prologClassOpt) {
+ clazzList.add(prologClassOpt);
+ }
+
+ ArrayList<String> imports = new ArrayList<String>();
+ imports.add("java.io.*");
+ imports.add("javax.media.opengl.*");
+ imports.add("com.jogamp.gluegen.runtime.*");
+ imports.add(Buffer.class.getPackage().getName()+".*");
+ for (Class<?> clasS : clazzList) {
+ imports.add(clasS.getName());
+ }
+
+ CodeGenUtils.emitJavaHeaders(output,
+ outputPackage,
+ outputClassName,
+ true,
+ imports,
+ new String[]{"public"},
+ ifNames,
+ null,
+ new CodeGenUtils.EmissionCallback() {
+ public void emit(PrintWriter w) {
+ emitClassDocComment(w);
+ }
+ });
+
+ preMethodEmissionHook(output);
+
+ constructorHook(output);
+
+ emitGLIsMethods(output);
+ emitGLGetMethods(output);
+
+ while (methodsToWrap.hasNext()) {
+ PlainMethod pm = methodsToWrap.next();
+ Method m = pm.getWrappedMethod();
+ emitMethodDocComment(output, m);
+ emitSignature(output, m);
+ emitBody(output, m, pm.runHooks());
+ }
+
+ postMethodEmissionHook(output);
+
+ output.println();
+ output.print(" private " + downstreamName + " " + getDownstreamObjectName() + ";");
+
+ // end the class
+ output.println();
+ output.print("} // end class ");
+ output.println(outputClassName);
+
+ output.flush();
+ output.close();
+
+ System.out.println("wrote to file: " + file); // JAU
+ }
+
+ /** Get the name of the object through which API calls should be routed. */
+ protected String getDownstreamObjectName() {
+ return "downstream" + downstreamName;
+ }
+
+ /** Get the name of the object which shall be called as a prolog. */
+ protected String getPrologObjectNameOpt() {
+ if (null != prologNameOpt) {
+ return "prolog" + prologNameOpt;
+ }
+ return null;
+ }
+
+ protected void emitMethodDocComment(PrintWriter output, Method m) {
+ }
+
+ protected void emitSignature(PrintWriter output, Method m) {
+ output.print(" public ");
+ output.print(' ');
+ output.print(JavaType.createForClass(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, boolean runHooks) {
+ output.println(" {");
+ output.print(" ");
+ Class<?> retType = m.getReturnType();
+
+ boolean callPreDownstreamHook = runHooks && hasPreDownstreamCallHook(m);
+ boolean callPostDownstreamHook = runHooks && hasPostDownstreamCallHook(m);
+ boolean callDownstream = (null != getMethod(downstreamClass, m))
+ && !(0 != (GEN_PROLOG_XOR_DOWNSTREAM & getMode()) && callPreDownstreamHook);
+ boolean hasResult = (retType != Void.TYPE);
+
+ if (!callDownstream) {
+ if (!emptyDownstreamAllowed()) {
+ throw new RuntimeException("Method " + m + " has no downstream (" + downstreamName + ")");
+ }
+ }
+
+ if (!callPreDownstreamHook && !callPostDownstreamHook && !callDownstream) {
+ if (!emptyMethodAllowed()) {
+ throw new RuntimeException("Method " + m + " is empty, no downstream (" + downstreamName + ") nor prolog (" + prologNameOpt + ").");
+ } else {
+ output.print(" if(DEBUG) { System.out.println(\"WARNING: No prolog, no downstream, empty: \"+");
+ printFunctionCallString(output, m);
+ output.println("); } ");
+ }
+ }
+
+ if (callPreDownstreamHook) {
+ if (hasResult && !callDownstream) {
+ if (callPostDownstreamHook) {
+ output.print(" " + JavaType.createForClass(retType).getName());
+ output.print(" _res = ");
+ } else {
+ output.print(" return ");
+ }
+ }
+ preDownstreamCallHook(output, m);
+ }
+
+ if (callDownstream) {
+ if (hasResult) {
+ if (callPostDownstreamHook) {
+ output.print(" " + JavaType.createForClass(retType).getName());
+ output.print(" _res = ");
+ } else {
+ output.print(" return ");
+ }
+ }
+ output.print(getDownstreamObjectName());
+ output.print('.');
+ output.print(m.getName());
+ output.print('(');
+ output.print(getArgListAsString(m, false, true));
+ output.println(");");
+ }
+
+ if (callPostDownstreamHook) {
+ postDownstreamCallHook(output, m);
+ }
+
+ if (hasResult && callDownstream && callPostDownstreamHook) {
+ output.println(" return _res;");
+ }
+ output.println(" }");
+
+ }
+
+ protected String getArgListAsString(Method m, boolean includeArgTypes, boolean includeArgNames) {
+ StringBuilder buf = new StringBuilder(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 output name for this pipeline class. */
+ protected abstract String getOutputName();
+
+ /**
+ * Called after the class headers have been generated, but before any
+ * method wrappers have been generated.
+ */
+ protected void preMethodEmissionHook(PrintWriter output) {
+ output.println(" public static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug(\"" + getOutputName() + "\");");
+ }
+
+ /**
+ * Emits the constructor for the pipeline; called after the preMethodEmissionHook.
+ */
+ protected abstract void constructorHook(PrintWriter output);
+
+ /**
+ * Called after the method wrappers have been generated, but before the
+ * closing parenthesis of the class is emitted.
+ */
+ protected void postMethodEmissionHook(PrintWriter output) {
+ output.println(" public String toString() {");
+ output.println(" StringBuffer sb = new StringBuffer();");
+ output.println(" sb.append(\"" + getOutputName() + " [ implementing " + baseInterfaceClass.getName() + ",\\n\\t\");");
+ if (null != prologClassOpt) {
+ output.println(" sb.append(\" prolog: \"+" + getPrologObjectNameOpt() + ".toString()+\",\\n\\t\");");
+ }
+ output.println(" sb.append(\" downstream: \"+" + getDownstreamObjectName() + ".toString()+\"\\n\\t]\");");
+ output.println(" return sb.toString();");
+ output.println(" }");
+ }
+
+ /**
+ * Called before the pipeline routes the call to the downstream object.
+ */
+ protected abstract void preDownstreamCallHook(PrintWriter output, Method m);
+
+ protected abstract boolean hasPreDownstreamCallHook(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);
+
+ protected abstract boolean hasPostDownstreamCallHook(Method m);
+
+ protected abstract int getMode();
+
+ protected abstract boolean emptyMethodAllowed();
+
+ protected abstract boolean emptyDownstreamAllowed();
+
+ /** Emit a Javadoc comment for this pipeline class. */
+ protected abstract void emitClassDocComment(PrintWriter output);
+
+ /**
+ * Emits one of the isGL* methods.
+ */
+ protected void emitGLIsMethod(PrintWriter output, String type) {
+ output.println(" public boolean is" + type + "() {");
+ Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
+ if (clazz.isAssignableFrom(baseInterfaceClass)) {
+ output.println(" return true;");
+ } else {
+ output.println(" return false;");
+ }
+ output.println(" }");
+ }
+
+ /**
+ * Emits all of the isGL* methods.
+ */
+ protected void emitGLIsMethods(PrintWriter output) {
+ emitGLIsMethod(output, "GL");
+ emitGLIsMethod(output, "GL4bc");
+ emitGLIsMethod(output, "GL4");
+ emitGLIsMethod(output, "GL3bc");
+ emitGLIsMethod(output, "GL3");
+ emitGLIsMethod(output, "GL2");
+ emitGLIsMethod(output, "GLES1");
+ emitGLIsMethod(output, "GLES2");
+ emitGLIsMethod(output, "GL2ES1");
+ emitGLIsMethod(output, "GL2ES2");
+ emitGLIsMethod(output, "GL2GL3");
+ output.println(" public boolean isGLES() {");
+ output.println(" return isGLES2() || isGLES1();");
+ output.println(" }");
+ }
+
+ /**
+ * Emits one of the getGL* methods.
+ */
+ protected void emitGLGetMethod(PrintWriter output, String type) {
+ output.println(" public javax.media.opengl." + type + " get" + type + "() {");
+ Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
+ if (clazz.isAssignableFrom(baseInterfaceClass)) {
+ output.println(" return this;");
+ } else {
+ output.println(" throw new GLException(\"Not a " + type + " implementation\");");
+ }
+ output.println(" }");
+ }
+
+ /**
+ * Emits all of the getGL* methods.
+ */
+ protected void emitGLGetMethods(PrintWriter output) {
+ emitGLGetMethod(output, "GL");
+ emitGLGetMethod(output, "GL4bc");
+ emitGLGetMethod(output, "GL4");
+ emitGLGetMethod(output, "GL3bc");
+ emitGLGetMethod(output, "GL3");
+ emitGLGetMethod(output, "GL2");
+ emitGLGetMethod(output, "GLES1");
+ emitGLGetMethod(output, "GLES2");
+ emitGLGetMethod(output, "GL2ES1");
+ emitGLGetMethod(output, "GL2ES2");
+ emitGLGetMethod(output, "GL2GL3");
+ output.println(" public GLProfile getGLProfile() {");
+ output.println(" return " + getDownstreamObjectName() + ".getGLProfile();");
+ output.println(" }");
+ }
+ } // end class PipelineEmitter
+
+ //-------------------------------------------------------
+ protected class CustomPipeline extends PipelineEmitter {
+
+ String className;
+ int mode;
+
+ CustomPipeline(int mode, String outputDir, String outputPackage, String outputName, Class<?> baseInterfaceClass, Class<?> prologClassOpt, Class<?> downstreamClass) {
+ super(outputDir, outputPackage, baseInterfaceClass, prologClassOpt, downstreamClass);
+ className = outputName;
+ this.mode = mode;
+ }
+
+ protected String getOutputName() {
+ return className;
+ }
+
+ protected int getMode() {
+ return mode;
+ }
+
+ protected boolean emptyMethodAllowed() {
+ return true;
+ }
+
+ protected boolean emptyDownstreamAllowed() {
+ return true;
+ }
+
+ @Override
+ protected void preMethodEmissionHook(PrintWriter output) {
+ super.preMethodEmissionHook(output);
+ }
+
+ protected void constructorHook(PrintWriter output) {
+ output.print(" public " + getOutputName() + "(");
+ output.print(downstreamName + " " + getDownstreamObjectName());
+ if (null != prologNameOpt) {
+ output.println(", " + prologNameOpt + " " + getPrologObjectNameOpt() + ")");
+ } else {
+ output.println(")");
+ }
+ output.println(" {");
+ output.println(" if (" + getDownstreamObjectName() + " == null) {");
+ output.println(" throw new IllegalArgumentException(\"null " + getDownstreamObjectName() + "\");");
+ output.println(" }");
+ output.print(" this." + getDownstreamObjectName());
+ output.println(" = " + getDownstreamObjectName() + ";");
+ if (null != prologNameOpt) {
+ output.print(" this." + getPrologObjectNameOpt());
+ output.println(" = " + getPrologObjectNameOpt() + ";");
+ }
+ output.println(" }");
+ output.println();
+ }
+
+ @Override
+ protected void postMethodEmissionHook(PrintWriter output) {
+ super.postMethodEmissionHook(output);
+ if (null != prologNameOpt) {
+ output.print(" private " + prologNameOpt + " " + getPrologObjectNameOpt() + ";");
+ }
+ }
+
+ protected void emitClassDocComment(PrintWriter output) {
+ output.println("/**");
+ output.println(" * Composable pipeline {@link " + outputPackage + "." + outputName + "}, implementing the interface");
+ output.println(" * {@link " + baseInterfaceClass.getName() + "}");
+ output.println(" * <p>");
+ output.println(" * Each method follows the call graph <ul>");
+ if (null != prologClassOpt) {
+ output.println(" * <li> call <em>prolog</em> {@link " + prologClassOpt.getName() + "} if available");
+ }
+ output.println(" * <li> call <em>downstream</em> {@link " + downstreamClass.getName() + "} if available");
+ if (null != prologClassOpt && 0 != (GEN_PROLOG_XOR_DOWNSTREAM & getMode())) {
+ output.println(" * <strong>and</strong> if no call to {@link " + prologClassOpt.getName() + "} is made");
+ }
+ output.println(" * </ul><p>");
+ output.println(" * ");
+ output.println(" * <ul>");
+ output.println(" * <li> <em>Interface</em> {@link " + baseInterfaceClass.getName() + "}");
+ if (null != prologClassOpt) {
+ output.println(" * <li> <em>Prolog</em> {@link " + prologClassOpt.getName() + "}");
+ }
+ output.println(" * <li> <em>Downstream</em> {@link " + downstreamClass.getName() + "}");
+ output.println(" * </ul><p>");
+ output.println(" * Sample code which installs this pipeline: </P>");
+ output.println(" * ");
+ output.println("<PRE>");
+ if (null != prologNameOpt) {
+ output.println(" GL gl = drawable.setGL( new " + className + "( drawable.getGL().getGL2ES2(), new " + prologNameOpt + "( drawable.getGL().getGL2ES2() ) ) );");
+ } else {
+ output.println(" GL gl = drawable.setGL( new " + className + "( drawable.getGL().getGL2ES2() ) );");
+ }
+ output.println("</PRE>");
+ output.println("*/");
+ }
+
+ protected boolean hasPreDownstreamCallHook(Method m) {
+ return null != getMethod(prologClassOpt, m);
+ }
+
+ protected void preDownstreamCallHook(PrintWriter output, Method m) {
+ if (null != prologNameOpt) {
+ output.print(getPrologObjectNameOpt());
+ output.print('.');
+ output.print(m.getName());
+ output.print('(');
+ output.print(getArgListAsString(m, false, true));
+ output.println(");");
+ }
+ }
+
+ protected boolean hasPostDownstreamCallHook(Method m) {
+ return false;
+ }
+
+ protected void postDownstreamCallHook(PrintWriter output, Method m) {
+ }
+ } // end class CustomPipeline
+
+ protected class DebugPipeline extends PipelineEmitter {
+
+ String className;
+
+ DebugPipeline(String outputDir, String outputPackage, Class<?> baseInterfaceClass, Class<?> downstreamClass) {
+ super(outputDir, outputPackage, baseInterfaceClass, null, downstreamClass);
+ className = "Debug" + getBaseInterfaceName();
+ }
+
+ protected String getOutputName() {
+ return className;
+ }
+
+ protected int getMode() {
+ return 0;
+ }
+
+ protected boolean emptyMethodAllowed() {
+ return false;
+ }
+
+ protected boolean emptyDownstreamAllowed() {
+ return false;
+ }
+
+ @Override
+ protected void preMethodEmissionHook(PrintWriter output) {
+ super.preMethodEmissionHook(output);
+ }
+
+ protected void constructorHook(PrintWriter output) {
+ output.print(" public " + getOutputName() + "(");
+ output.println(downstreamName + " " + getDownstreamObjectName() + ")");
+ output.println(" {");
+ output.println(" if (" + getDownstreamObjectName() + " == null) {");
+ output.println(" throw new IllegalArgumentException(\"null " + getDownstreamObjectName() + "\");");
+ output.println(" }");
+ output.print(" this." + getDownstreamObjectName());
+ output.println(" = " + getDownstreamObjectName() + ";");
+ if (null != prologNameOpt) {
+ output.print(" this." + getPrologObjectNameOpt());
+ output.println(" = " + getPrologObjectNameOpt() + ";");
+ }
+ output.println(" // Fetch GLContext object for better error checking (if possible)");
+ output.println(" _context = " + getDownstreamObjectName() + ".getContext();");
+ output.println(" }");
+ output.println();
+ }
+
+ @Override
+ protected void postMethodEmissionHook(PrintWriter output) {
+ super.postMethodEmissionHook(output);
+ output.println(" private void checkGLGetError(String caller)");
+ output.println(" {");
+ if (hasImmediateMode) {
+ output.println(" if (insideBeginEndPair) {");
+ output.println(" return;");
+ output.println(" }");
+ 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(Thread.currentThread()+");
+ 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(" int recursionDepth = 10;");
+ 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;");
+ if (hasStackOverflow) {
+ 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: buf.append(\"Unknown glGetError() return value: \");");
+ output.println(" }");
+ output.println(" buf.append(\"( \" + err + \" 0x\"+Integer.toHexString(err).toUpperCase() + \"), \");");
+ output.println(" } while ((--recursionDepth >= 0) && (err = "
+ + getDownstreamObjectName()
+ + ".glGetError()) != GL_NO_ERROR);");
+ output.println(" throw new GLException(buf.toString());");
+ output.println(" }");
+ if (hasImmediateMode) {
+ output.println(" /** True if the pipeline is inside a glBegin/glEnd pair.*/");
+ output.println(" private boolean insideBeginEndPair = false;");
+ output.println();
+ }
+ output.println(" private void checkContext() {");
+ output.println(" GLContext currentContext = GLContext.getCurrent();");
+ output.println(" if (currentContext == null) {");
+ output.println(" throw new GLException(\"No OpenGL context is current on this thread\");");
+ output.println(" }");
+ output.println(" if ((_context != null) && (_context != currentContext)) {");
+ output.println(" throw new GLException(\"This GL object is being incorrectly used with a different GLContext than that which created it\");");
+ output.println(" }");
+ output.println(" }");
+ output.println(" private GLContext _context;");
+ }
+
+ protected void emitClassDocComment(PrintWriter output) {
+ output.println("/** <P> Composable pipeline 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(" GL gl = drawable.setGL(new DebugGL(drawable.getGL()));");
+ output.println("</PRE>");
+ output.println("*/");
+ }
+
+ protected boolean hasPreDownstreamCallHook(Method m) {
+ return true;
+ }
+
+ protected void preDownstreamCallHook(PrintWriter output, Method m) {
+ output.println(" checkContext();");
+ }
+
+ protected boolean hasPostDownstreamCallHook(Method m) {
+ return true;
+ }
+
+ 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;");
+ }
+
+ output.println(" String txt = new String(\"" + m.getName() + "(\" +");
+ Class<?>[] params = m.getParameterTypes();
+ for (int i = 0; params != null && i < params.length; i++) {
+ if (params[i].equals(int.class)) {
+ output.println(" \"<" + params[i].getName() + "> 0x\"+Integer.toHexString(arg" + i + ").toUpperCase() +");
+ } else {
+ output.println(" \"<" + params[i].getName() + ">\" +");
+ }
+ if (i < params.length - 1) {
+ output.println(" \", \" +");
+ }
+ }
+ output.println(" \")\");");
+ // calls to glGetError() are only allowed outside of glBegin/glEnd pairs
+ output.println(" checkGLGetError( txt );");
+ }
+ }
+ } // end class DebugPipeline
+
+ //-------------------------------------------------------
+ protected class TracePipeline extends PipelineEmitter {
+
+ String className;
+
+ TracePipeline(String outputDir, String outputPackage, Class<?> baseInterfaceClass, Class<?> downstreamClass) {
+ super(outputDir, outputPackage, baseInterfaceClass, null, downstreamClass);
+ className = "Trace" + getBaseInterfaceName();
+ }
+
+ protected String getOutputName() {
+ return className;
+ }
+
+ protected int getMode() {
+ return 0;
+ }
+
+ protected boolean emptyMethodAllowed() {
+ return false;
+ }
+
+ protected boolean emptyDownstreamAllowed() {
+ return false;
+ }
+
+ @Override
+ protected void preMethodEmissionHook(PrintWriter output) {
+ super.preMethodEmissionHook(output);
+ }
+
+ protected void constructorHook(PrintWriter output) {
+ output.print(" public " + getOutputName() + "(");
+ output.println(downstreamName + " " + getDownstreamObjectName() + ", PrintStream " + getOutputStreamName() + ")");
+ output.println(" {");
+ output.println(" if (" + getDownstreamObjectName() + " == null) {");
+ output.println(" throw new IllegalArgumentException(\"null " + getDownstreamObjectName() + "\");");
+ output.println(" }");
+ output.print(" this." + getDownstreamObjectName());
+ output.println(" = " + getDownstreamObjectName() + ";");
+ output.print(" this." + getOutputStreamName());
+ output.println(" = " + getOutputStreamName() + ";");
+ output.println(" }");
+ output.println();
+ }
+
+ @Override
+ protected void postMethodEmissionHook(PrintWriter output) {
+ super.postMethodEmissionHook(output);
+ output.println("private PrintStream " + getOutputStreamName() + ";");
+ output.println("private int indent = 0;");
+ output.println("protected String dumpArray(Object obj)");
+ output.println("{");
+ output.println(" if (obj == null) return \"[null]\";");
+ output.println(" StringBuffer sb = new StringBuffer(\"[\");");
+ output.println(" int len = java.lang.reflect.Array.getLength(obj);");
+ output.println(" int count = Math.min(len,16);");
+ output.println(" for ( int i =0; i < count; i++ ) {");
+ output.println(" sb.append(java.lang.reflect.Array.get(obj,i));");
+ output.println(" if (i < count-1)");
+ output.println(" sb.append(',');");
+ output.println(" }");
+ output.println(" if ( len > 16 )");
+ output.println(" sb.append(\"...\").append(len);");
+ output.println(" sb.append(']');");
+ output.println(" return sb.toString();");
+ output.println("}");
+ output.println("protected void print(String str)");
+ output.println("{");
+ output.println(" " + getOutputStreamName() + ".print(str);");
+ output.println("}");
+ output.println("protected void println(String str)");
+ output.println("{");
+ output.println(" " + getOutputStreamName() + ".println(str);");
+ output.println("}");
+ output.println("protected void printIndent()");
+ output.println("{");
+ output.println(" for( int i =0; i < indent; i++) {" + getOutputStreamName() + ".print(' ');}");
+ output.println("}");
+ }
+
+ protected void emitClassDocComment(PrintWriter output) {
+ output.println("/** <P> Composable pipeline which wraps an underlying {@link GL} implementation,");
+ output.println(" providing tracing information to a user-specified {@link java.io.PrintStream}");
+ output.println(" before and after each OpenGL method call. Sample code which installs this pipeline: </P>");
+ output.println();
+ output.println("<PRE>");
+ output.println(" GL gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));");
+ output.println("</PRE>");
+ output.println("*/");
+ }
+
+ protected boolean hasPreDownstreamCallHook(Method m) {
+ return true;
+ }
+
+ protected void preDownstreamCallHook(PrintWriter output, Method m) {
+ if (m.getName().equals("glEnd") || m.getName().equals("glEndList")) {
+ output.println("indent-=2;");
+ output.println(" printIndent();");
+ } else {
+ output.println("printIndent();");
+ }
+
+ output.print(" print(");
+ printFunctionCallString(output, m);
+ output.println(");");
+ }
+
+ protected boolean hasPostDownstreamCallHook(Method m) {
+ return true;
+ }
+
+ protected void postDownstreamCallHook(PrintWriter output, Method m) {
+ Class<?> ret = m.getReturnType();
+ if (ret != Void.TYPE) {
+ output.println(" println(\" = \"+_res);");
+ } else {
+ output.println(" println(\"\");");
+ }
+ }
+
+ private String getOutputStreamName() {
+ return "stream";
+ }
+ } // end class TracePipeline
+
+ public static final void printFunctionCallString(PrintWriter output, Method m) {
+ Class<?>[] params = m.getParameterTypes();
+ output.print(" \"" + m.getName() + "(\"");
+ for (int i = 0; i < params.length; i++) {
+ if (params[i].isArray()) {
+ output.print("+\"<" + params[i].getName() + ">\"");
+ } else if (params[i].equals(int.class)) {
+ output.print("+\"<" + params[i].getName() + "> 0x\"+Integer.toHexString(arg" + i + ").toUpperCase()");
+ } else {
+ output.print("+\"<" + params[i].getName() + "> \"+arg" + i);
+ }
+ if (i < params.length - 1) {
+ output.print("+\", \"");
+ }
+ }
+ output.print("+\")\"");
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
new file mode 100644
index 000000000..9946c9df1
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. 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 com.jogamp.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 {
+
+ // Handles function pointer
+ protected static int funcIdentifierGroup = 10;
+ protected static Pattern funcPattern =
+ Pattern.compile("^(GLAPI|GL_API|GL_APICALL|EGLAPI|extern)?(\\s*)((unsigned|const)\\s+)?(\\w+)(\\s*\\*)?(\\s+)(GLAPIENTRY|GL_APIENTRY|APIENTRY|EGLAPIENTRY|WINAPI)?(\\s*)([ew]?gl\\w+)\\s?(\\(.*)");
+
+ protected static Pattern associationPattern =
+ Pattern.compile("\\#ifndef ([CEW]?GL[XU]?_[A-Za-z0-9_]+)(.*)");
+
+ protected static int defineIdentifierGroup = 1;
+ protected static Pattern definePattern =
+ Pattern.compile("\\#define ([CEW]?GL[XU]?_[A-Za-z0-9_]+)\\s*([A-Za-z0-9_]+)(.*)");
+
+ // Maps function / #define names to the names of the extensions they're declared in
+ protected Map<String, String> declarationToExtensionMap = new HashMap<String, String>();
+
+ // Maps extension names to Set of identifiers (both #defines and
+ // function names) this extension declares
+ protected Map<String, Set<String>> extensionToDeclarationMap = new HashMap<String, Set<String>>();
+ protected boolean debug = false;
+
+ /**
+ * 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) throws IOException {
+ if (args.length > 0 && args[0].equals("-test")) {
+ BuildStaticGLInfo builder = new BuildStaticGLInfo();
+ builder.setDebug(true);
+ String[] newArgs = new String[args.length - 1];
+ System.arraycopy(args, 1, newArgs, 0, args.length - 1);
+ builder.parse(newArgs);
+ builder.dump();
+ System.exit(0);
+ }
+
+ 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 {
+ builder.parse(cHeaderFilePaths);
+
+ 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.emitJavaCode(writer, packageName);
+
+ writer.flush();
+ writer.close();
+ } catch (Exception e) {
+ StringBuilder buf = new StringBuilder("{ ");
+ 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);
+ }
+ }
+
+ public void setDebug(boolean v) {
+ debug = v;
+ }
+
+ /** Parses the supplied C header files and adds the function
+ associations contained therein to the internal map. */
+ public void parse(String[] cHeaderFilePaths) throws IOException {
+ for (int i = 0; i < cHeaderFilePaths.length; i++) {
+ parse(cHeaderFilePaths[i]);
+ }
+ }
+
+ /** Parses the supplied C header file and adds the function
+ associations contained therein to the internal map. */
+ public void parse(String cHeaderFilePath) throws IOException {
+ BufferedReader reader = new BufferedReader(new FileReader(cHeaderFilePath));
+ String line, activeAssociation = null;
+ Matcher m = null;
+ while ((line = reader.readLine()) != null) {
+ int type = 0; // 1-define, 2-function
+ // see if we're inside a #ifndef GL_XXX block and matching a function
+ if (activeAssociation != null) {
+ String identifier = null;
+ if ((m = funcPattern.matcher(line)).matches()) {
+ identifier = m.group(funcIdentifierGroup).trim();
+ type = 2;
+ } else if ((m = definePattern.matcher(line)).matches()) {
+ identifier = m.group(defineIdentifierGroup).trim();
+ type = 1;
+ } else if (line.startsWith("#endif")) {
+ if (debug) {
+ System.err.println("END ASSOCIATION BLOCK: <" + activeAssociation + ">");
+ }
+ activeAssociation = null;
+ }
+ if ((identifier != null)
+ && (activeAssociation != null)
+ && // Handles #ifndef GL_... #define GL_...
+ !identifier.equals(activeAssociation)) {
+ addAssociation(identifier, activeAssociation);
+ if (debug) {
+ System.err.println(" ADDING ASSOCIATION: <" + identifier + "> <" + activeAssociation + "> ; type " + type);
+ }
+ }
+ } else if ((m = associationPattern.matcher(line)).matches()) {
+ // found a new #ifndef GL_XXX block
+ activeAssociation = m.group(1).trim();
+
+ if (debug) {
+ System.err.println("BEGIN ASSOCIATION BLOCK: <" + activeAssociation + ">");
+ }
+ }
+ }
+ reader.close();
+ }
+
+ public void dump() {
+ for (String name : extensionToDeclarationMap.keySet()) {
+ Set<String> decls = extensionToDeclarationMap.get(name);
+ System.out.println("<" + name + "> :");
+ List<String> l = new ArrayList<String>();
+ l.addAll(decls);
+ Collections.sort(l);
+ for (String str : l) {
+ System.out.println(" <" + str + ">");
+ }
+ }
+ }
+
+ public String getExtension(String identifier) {
+ return declarationToExtensionMap.get(identifier);
+ }
+
+ public Set<String> getDeclarations(String extension) {
+ return extensionToDeclarationMap.get(extension);
+ }
+
+ public Set<String> getExtensions() {
+ return extensionToDeclarationMap.keySet();
+ }
+
+ public void emitJavaCode(PrintWriter output, String packageName) {
+ 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;");
+ 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(" String mappedName = null;");
+ output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutationNumber(glFunctionName);");
+ output.println(" for(int i = 0; null==mappedName && i < funcNamePermNum; i++) {");
+ output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutation(glFunctionName, i);");
+ output.println(" try {");
+ output.println(" mappedName = (String)funcToAssocMap.get(tmp);");
+ output.println(" } catch (Exception e) { }");
+ output.println(" }");
+ output.println(" return mappedName;");
+ output.println(" }");
+ output.println();
+
+ output.println(" static");
+ output.println(" {");
+
+ // Compute max capacity
+ int maxCapacity = 0;
+ for (String name : declarationToExtensionMap.keySet()) {
+ if (!name.startsWith("GL")) {
+ ++maxCapacity;
+ }
+ }
+
+ output.println(" funcToAssocMap = new HashMap(" + maxCapacity + "); // approximate max capacity");
+ output.println(" String group;");
+ ArrayList<String> sets = new ArrayList<String>(extensionToDeclarationMap.keySet());
+ Collections.sort(sets);
+ for (String groupName : sets) {
+ Set<String> funcs = extensionToDeclarationMap.get(groupName);
+ List<String> l = new ArrayList<String>();
+ l.addAll(funcs);
+ Collections.sort(l);
+ Iterator<String> funcIter = l.iterator();
+ boolean printedHeader = false;
+ while (funcIter.hasNext()) {
+ String funcName = funcIter.next();
+ if (!funcName.startsWith("GL")) {
+ if (!printedHeader) {
+ output.println();
+ output.println(" //----------------------------------------------------------------");
+ output.println(" // " + groupName);
+ output.println(" //----------------------------------------------------------------");
+ output.println(" group = \"" + groupName + "\";");
+ printedHeader = true;
+ }
+
+ output.println(" funcToAssocMap.put(\"" + funcName + "\", group);");
+ }
+ }
+ }
+ output.println(" }");
+ output.println("} // end class StaticGLInfo");
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+ protected void addAssociation(String identifier, String association) {
+ declarationToExtensionMap.put(identifier, association);
+ Set<String> identifiers = extensionToDeclarationMap.get(association);
+ if (identifiers == null) {
+ identifiers = new HashSet<String>();
+ extensionToDeclarationMap.put(association, identifiers);
+ }
+ identifiers.add(identifier);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
new file mode 100755
index 000000000..010ca1069
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. 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 com.jogamp.gluegen.opengl;
+
+import java.io.*;
+import java.util.*;
+
+import com.jogamp.gluegen.*;
+import com.jogamp.gluegen.procaddress.*;
+import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+
+public class GLConfiguration extends ProcAddressConfiguration {
+
+ // The following data members support ignoring an entire extension at a time
+ private List<String> glHeaders = new ArrayList<String>();
+ private Set<String> ignoredExtensions = new HashSet<String>();
+ private Set<String> extensionsRenamedIntoCore = new HashSet<String>();
+ private BuildStaticGLInfo glInfo;
+
+ // Maps function names to the kind of buffer object it deals with
+ private Map<String, GLEmitter.BufferObjectKind> bufferObjectKinds = new HashMap<String, GLEmitter.BufferObjectKind>();
+ private GLEmitter emitter;
+ private Set<String> dropUniqVendorExtensions = new HashSet<String>();
+
+ // This directive is off by default but can help automatically
+ // indicate which extensions have been folded into the core OpenGL
+ // namespace, and if not, then why not
+ private boolean autoUnifyExtensions = false;
+ private boolean allowNonGLExtensions = false;
+
+ public GLConfiguration(GLEmitter emitter) {
+ super();
+ this.emitter = emitter;
+ try {
+ setProcAddressNameExpr("PFN $UPPERCASE({0}) PROC");
+ } catch (NoSuchElementException e) {
+ throw new RuntimeException("Error configuring ProcAddressNameExpr", e);
+ }
+ }
+
+ @Override
+ protected void dispatch(String cmd, StringTokenizer tok, File file, String filename, int lineNo) throws IOException {
+ if (cmd.equalsIgnoreCase("IgnoreExtension")) {
+ String sym = readString("IgnoreExtension", tok, filename, lineNo);
+ ignoredExtensions.add(sym);
+ } else if (cmd.equalsIgnoreCase("RenameExtensionIntoCore")) {
+ String sym = readString("RenameExtensionIntoCore", tok, filename, lineNo);
+ extensionsRenamedIntoCore.add(sym);
+ } else if (cmd.equalsIgnoreCase("AllowNonGLExtensions")) {
+ allowNonGLExtensions = readBoolean("AllowNonGLExtensions", tok, filename, lineNo).booleanValue();
+ } else if (cmd.equalsIgnoreCase("AutoUnifyExtensions")) {
+ autoUnifyExtensions = readBoolean("AutoUnifyExtensions", tok, filename, lineNo).booleanValue();
+ } else if (cmd.equalsIgnoreCase("GLHeader")) {
+ String sym = readString("GLHeader", tok, filename, lineNo);
+ glHeaders.add(sym);
+ } else if (cmd.equalsIgnoreCase("BufferObjectKind")) {
+ readBufferObjectKind(tok, filename, lineNo);
+ } else if (cmd.equalsIgnoreCase("DropUniqVendorExtensions")) {
+ String sym = readString("DropUniqVendorExtensions", tok, filename, lineNo);
+ dropUniqVendorExtensions.add(sym);
+ } else {
+ super.dispatch(cmd, tok, file, filename, lineNo);
+ }
+ }
+
+ protected void readBufferObjectKind(StringTokenizer tok, String filename, int lineNo) {
+ try {
+ String kindString = tok.nextToken();
+ GLEmitter.BufferObjectKind kind = null;
+ String target = tok.nextToken();
+ if (kindString.equalsIgnoreCase("UnpackPixel")) {
+ kind = GLEmitter.BufferObjectKind.UNPACK_PIXEL;
+ } else if (kindString.equalsIgnoreCase("PackPixel")) {
+ kind = GLEmitter.BufferObjectKind.PACK_PIXEL;
+ } else if (kindString.equalsIgnoreCase("Array")) {
+ kind = GLEmitter.BufferObjectKind.ARRAY;
+ } else if (kindString.equalsIgnoreCase("Element")) {
+ kind = GLEmitter.BufferObjectKind.ELEMENT;
+ } else {
+ throw new RuntimeException("Error parsing \"BufferObjectKind\" command at line " + lineNo
+ + " in file \"" + filename + "\": illegal BufferObjectKind \""
+ + kindString + "\", expected one of UnpackPixel, PackPixel, Array, or Element");
+ }
+
+ bufferObjectKinds.put(target, kind);
+ } catch (NoSuchElementException e) {
+ throw new RuntimeException("Error parsing \"BufferObjectKind\" command at line " + lineNo
+ + " in file \"" + filename + "\"", e);
+ }
+ }
+
+ /** Overrides javaPrologueForMethod in superclass and
+ automatically generates prologue code for functions associated
+ with buffer objects. */
+ @Override
+ public List<String> javaPrologueForMethod(MethodBinding binding, boolean forImplementingMethodCall, boolean eraseBufferAndArrayTypes) {
+
+ List<String> res = super.javaPrologueForMethod(binding, forImplementingMethodCall, eraseBufferAndArrayTypes);
+ GLEmitter.BufferObjectKind kind = getBufferObjectKind(binding.getName());
+ if (kind != null) {
+ // Need to generate appropriate prologue based on both buffer
+ // object kind and whether this variant of the MethodBinding
+ // is the one accepting a "long" as argument
+ //
+ // NOTE we MUST NOT mutate the array returned from the super
+ // call!
+ ArrayList<String> res2 = new ArrayList<String>();
+ if (res != null) {
+ res2.addAll(res);
+ }
+ res = res2;
+
+ String prologue = "check";
+
+ if (kind == GLEmitter.BufferObjectKind.UNPACK_PIXEL) {
+ prologue = prologue + "UnpackPBO";
+ } else if (kind == GLEmitter.BufferObjectKind.PACK_PIXEL) {
+ prologue = prologue + "PackPBO";
+ } else if (kind == GLEmitter.BufferObjectKind.ARRAY) {
+ prologue = prologue + "ArrayVBO";
+ } else if (kind == GLEmitter.BufferObjectKind.ELEMENT) {
+ prologue = prologue + "ElementVBO";
+ } else {
+ throw new RuntimeException("Unknown BufferObjectKind " + kind);
+ }
+
+ if (emitter.isBufferObjectMethodBinding(binding)) {
+ prologue = prologue + "Enabled";
+ } else {
+ prologue = prologue + "Disabled";
+ }
+
+ prologue = prologue + "(true);";
+
+ res.add(0, prologue);
+
+ // Must also filter out bogus rangeCheck directives for VBO/PBO
+ // variants
+ if (emitter.isBufferObjectMethodBinding(binding)) {
+ for (Iterator<String> iter = res.iterator(); iter.hasNext();) {
+ String line = iter.next();
+ if (line.indexOf("Buffers.rangeCheck") >= 0) {
+ iter.remove();
+ }
+ }
+ }
+ }
+
+ return res;
+ }
+
+ @Override
+ public void dumpIgnores() {
+ System.err.println("GL Ignored extensions: ");
+ for (String str : ignoredExtensions) {
+ System.err.println("\t" + str);
+ }
+ super.dumpIgnores();
+ }
+
+ protected boolean shouldIgnoreExtension(String symbol, boolean criteria) {
+ if (criteria && glInfo != null) {
+ String extension = glInfo.getExtension(symbol);
+ if (extension != null
+ && ignoredExtensions.contains(extension)) {
+ return true;
+ }
+ boolean isGLEnum = GLExtensionNames.isGLEnumeration(symbol);
+ boolean isGLFunc = GLExtensionNames.isGLFunction(symbol);
+ if (isGLFunc || isGLEnum) {
+ if (GLExtensionNames.isExtensionVEN(symbol, isGLFunc)) {
+ String extSuffix = GLExtensionNames.getExtensionSuffix(symbol, isGLFunc);
+ if (getDropUniqVendorExtensions(extSuffix)) {
+ if (DEBUG_IGNORES) {
+ System.err.println("Ignore UniqVendorEXT: " + symbol + ", vendor " + extSuffix);
+ }
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean shouldIgnoreInInterface(String symbol) {
+ return shouldIgnoreInInterface(symbol, true);
+ }
+
+ public boolean shouldIgnoreInInterface(String symbol, boolean checkEXT) {
+ return shouldIgnoreExtension(symbol, checkEXT) || super.shouldIgnoreInInterface(symbol);
+ }
+
+ @Override
+ public boolean shouldIgnoreInImpl(String symbol) {
+ return shouldIgnoreInImpl(symbol, true);
+ }
+
+ public boolean shouldIgnoreInImpl(String symbol, boolean checkEXT) {
+ return shouldIgnoreExtension(symbol, checkEXT) || super.shouldIgnoreInImpl(symbol);
+ }
+
+ /** Should we automatically ignore extensions that have already been
+ fully subsumed into the OpenGL core namespace, and if they have
+ not been, indicate which definition is not already in the core? */
+ public boolean getAutoUnifyExtensions() {
+ return autoUnifyExtensions;
+ }
+
+ /** If true, accept all non encapsulated defines and functions,
+ * as it is mandatory for GL declarations. */
+ public boolean getAllowNonGLExtensions() {
+ return allowNonGLExtensions;
+ }
+
+ /** shall the non unified (uniq) vendor extensions be dropped ? */
+ public boolean getDropUniqVendorExtensions(String extName) {
+ return dropUniqVendorExtensions.contains(extName);
+ }
+
+ /** Returns the kind of buffer object this function deals with, or
+ null if none. */
+ GLEmitter.BufferObjectKind getBufferObjectKind(String name) {
+ return bufferObjectKinds.get(name);
+ }
+
+ public boolean isBufferObjectFunction(String name) {
+ return (getBufferObjectKind(name) != null);
+ }
+
+ /** Parses any GL headers specified in the configuration file for
+ the purpose of being able to ignore an extension at a time. */
+ public void parseGLHeaders(GlueEmitterControls controls) throws IOException {
+ if (!glHeaders.isEmpty()) {
+ glInfo = new BuildStaticGLInfo();
+ for (String file : glHeaders) {
+ String fullPath = controls.findHeaderFile(file);
+ if (fullPath == null) {
+ throw new IOException("Unable to locate header file \"" + file + "\"");
+ }
+ glInfo.parse(fullPath);
+ }
+ }
+ }
+
+ /** Returns the information about the association between #defines,
+ function symbols and the OpenGL extensions they are defined
+ in. */
+ public BuildStaticGLInfo getGLInfo() {
+ return glInfo;
+ }
+
+ /** Returns the OpenGL extensions that should have all of their
+ constant definitions and functions renamed into the core
+ namespace; for example, glGenFramebuffersEXT to
+ glGenFramebuffers and GL_FRAMEBUFFER_EXT to GL_FRAMEBUFFER. */
+ public Set<String> getExtensionsRenamedIntoCore() {
+ return extensionsRenamedIntoCore;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
new file mode 100644
index 000000000..ad9e47011
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. 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 com.jogamp.gluegen.opengl;
+
+import java.io.*;
+import java.util.*;
+import com.jogamp.gluegen.*;
+import com.jogamp.gluegen.cgram.types.*;
+import com.jogamp.gluegen.procaddress.*;
+import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+
+/**
+ * A subclass of ProcAddressEmitter with special OpenGL-specific
+ * configuration abilities.
+ */
+public class GLEmitter extends ProcAddressEmitter {
+
+ // Keeps track of which MethodBindings were created for handling
+ // Buffer Object variants. Used as a Set rather than a Map.
+ private Map<MethodBinding, MethodBinding> bufferObjectMethodBindings = new IdentityHashMap<MethodBinding, MethodBinding>();
+
+ enum BufferObjectKind { UNPACK_PIXEL, PACK_PIXEL, ARRAY, ELEMENT}
+
+ @Override
+ public void beginEmission(GlueEmitterControls controls) throws IOException {
+ getGLConfig().parseGLHeaders(controls);
+ renameExtensionsIntoCore();
+ if (getGLConfig().getAutoUnifyExtensions()) {
+ unifyExtensions(controls);
+ }
+ super.beginEmission(controls);
+ }
+
+ protected void renameExtensionsIntoCore() {
+ // This method handles renaming of entire extensions into the
+ // OpenGL core namespace. For example, it is used to move certain
+ // OpenGL ES (OES) extensions into the core namespace which are
+ // already in the core namespace in desktop OpenGL. It builds upon
+ // renaming mechanisms that are built elsewhere.
+
+ GLConfiguration config = getGLConfig();
+ Set<String> extensionsRenamedIntoCore = config.getExtensionsRenamedIntoCore();
+ BuildStaticGLInfo glInfo = config.getGLInfo();
+ if (null == glInfo) {
+ if (extensionsRenamedIntoCore.size() > 0) {
+ throw new RuntimeException("ExtensionRenamedIntoCore (num: " + extensionsRenamedIntoCore.size() + "), but no GLHeader");
+ }
+ return;
+ }
+ for (String extension : extensionsRenamedIntoCore) {
+ Set<String> declarations = glInfo.getDeclarations(extension);
+ if (declarations != null) {
+ for (Iterator<String> iterator = declarations.iterator(); iterator.hasNext();) {
+ String decl = iterator.next();
+ boolean isGLFunction = GLExtensionNames.isGLFunction(decl);
+ boolean isGLEnumeration = false;
+ if (!isGLFunction) {
+ isGLEnumeration = GLExtensionNames.isGLEnumeration(decl);
+ }
+ if (isGLFunction || isGLEnumeration) {
+ String renamed = GLExtensionNames.normalize(decl, isGLFunction);
+ if (!renamed.equals(decl)) {
+ config.addJavaSymbolRename(decl, renamed);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ class ExtensionUnifier implements SymbolFilter {
+
+ private List<ConstantDefinition> constants;
+ private List<FunctionSymbol> functions;
+
+ public void filterSymbols(List<ConstantDefinition> constants,
+ List<FunctionSymbol> functions) {
+ this.constants = constants;
+ this.functions = functions;
+ doWork();
+ }
+
+ public List<ConstantDefinition> getConstants() {
+ return constants;
+ }
+
+ public List<FunctionSymbol> getFunctions() {
+ return functions;
+ }
+
+ private void doWork() {
+ BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
+ if (glInfo == null) {
+ return;
+ }
+ // Try to retain a "good" ordering for these symbols
+ Map<String, ConstantDefinition> constantMap = new LinkedHashMap<String, ConstantDefinition>();
+ for (ConstantDefinition def : constants) {
+ constantMap.put(def.getName(), def);
+ }
+ Map<String, FunctionSymbol> functionMap = new LinkedHashMap<String, FunctionSymbol>();
+ for (FunctionSymbol sym : functions) {
+ functionMap.put(sym.getName(), sym);
+ }
+
+ // Go through all of the declared extensions.
+ // For each extension, look at its #define and function symbols.
+ // If we find all of the extension's symbols in the core API under
+ // non-ARB (or whatever is the suffix) names, then remove this extension
+ // from the public API. If it turns out that we are running on hardware
+ // that doesn't support the core version of these APIs, the runtime
+ // will take care of looking up the extension version of these entry
+ // points.
+ Set<String> extensionNames = glInfo.getExtensions();
+
+ for (String extension : extensionNames) {
+ Set<String> declarations = glInfo.getDeclarations(extension);
+ boolean isExtension = true;
+ boolean shouldUnify = true;
+ String cause = null;
+ for (String decl : declarations) {
+ boolean isFunc = !decl.startsWith("GL_");
+ if (!GLExtensionNames.isExtension(decl, isFunc)) {
+ isExtension = false;
+ break;
+ }
+ // See whether we're emitting glue code for this
+ // entry point or definition at all
+ if (isFunc) {
+ if (!functionMap.containsKey(decl)) {
+ isExtension = false;
+ break;
+ }
+ } else {
+ if (!constantMap.containsKey(decl)) {
+ isExtension = false;
+ break;
+ }
+ }
+ cause = decl;
+ String unifiedName = GLExtensionNames.normalize(decl, isFunc);
+ // NOTE that we look up the unified name in the
+ // BuildStaticGLInfo's notion of the APIs -- since
+ // we might not be emitting glue code for the
+ // headers that actually contain the core entry
+ // point. Think of the case where we are parsing the
+ // GLES2 gl2.h, which contains certain desktop
+ // OpenGL extensions that have been moved into the
+ // core, but later generating the implementing glue
+ // code (not the interface) for the desktop gl.h /
+ // glext.h.
+ shouldUnify = (glInfo.getExtension(unifiedName) != null);
+ // if (isFunc) {
+ // shouldUnify = functionMap.containsKey(unifiedName);
+ // } else {
+ // shouldUnify = constantMap.containsKey(unifiedName);
+ // }
+ if (!shouldUnify) {
+ break;
+ }
+ }
+ if (isExtension) {
+ if (shouldUnify) {
+ for (String decl : declarations) {
+ boolean isFunc = !decl.startsWith("GL_");
+ if (isFunc) {
+ functionMap.remove(decl);
+ } else {
+ constantMap.remove(decl);
+ }
+ }
+ System.err.println("INFO: unified extension " + extension + " into core API");
+ } else {
+ System.err.println("INFO: didn't unify extension " + extension + " into core API because of " + cause);
+ }
+ }
+ }
+ constants = new ArrayList<ConstantDefinition>(constantMap.values());
+ functions = new ArrayList<FunctionSymbol>(functionMap.values());
+ }
+ }
+
+ private void unifyExtensions(GlueEmitterControls controls) {
+ controls.runSymbolFilter(new ExtensionUnifier());
+ }
+
+ @Override
+ protected JavaConfiguration createConfig() {
+ return new GLConfiguration(this);
+ }
+
+ /** In order to implement Buffer Object variants of certain
+ functions we generate another MethodBinding which maps the void*
+ argument to a Java long. The generation of emitters then takes
+ place as usual. We do however need to keep track of the modified
+ MethodBinding object so that we can also modify the emitters
+ later to inform them that their argument has changed. We might
+ want to push this functionality down into the MethodBinding
+ (i.e., mutators for argument names). We also would need to
+ inform the CMethodBindingEmitter that it is overloaded in this
+ case (though we default to true currently). */
+ @Override
+ protected List<MethodBinding> expandMethodBinding(MethodBinding binding) {
+ List<MethodBinding> bindings = super.expandMethodBinding(binding);
+
+ if (!getGLConfig().isBufferObjectFunction(binding.getName())) {
+ return bindings;
+ }
+
+ List<MethodBinding> newBindings = new ArrayList<MethodBinding>(bindings);
+
+ // Need to expand each one of the generated bindings to take a
+ // Java long instead of a Buffer for each void* argument
+
+ for (MethodBinding cur : bindings) {
+
+ // Some of these routines (glBitmap) take strongly-typed
+ // primitive pointers as arguments which are expanded into
+ // non-void* arguments
+ // This test (rather than !signatureUsesNIO) is used to catch
+ // more unexpected situations
+ if (cur.signatureUsesJavaPrimitiveArrays()) {
+ continue;
+ }
+
+ MethodBinding result = cur;
+ for (int i = 0; i < cur.getNumArguments(); i++) {
+ if (cur.getJavaArgumentType(i).isNIOBuffer()) {
+ result = result.replaceJavaArgumentType(i, JavaType.createForClass(Long.TYPE));
+ }
+ }
+
+ if (result == cur) {
+ throw new RuntimeException("Error: didn't find any void* arguments for BufferObject function "
+ + binding.getName());
+ }
+
+ newBindings.add(result);
+ // Now need to flag this MethodBinding so that we generate the
+ // correct flags in the emitters later
+ bufferObjectMethodBindings.put(result, result);
+ }
+
+ return newBindings;
+ }
+
+ @Override
+ protected boolean needsModifiedEmitters(FunctionSymbol sym) {
+ if ((!needsProcAddressWrapper(sym) && !needsBufferObjectVariant(sym))
+ || getConfig().isUnimplemented(sym.getName())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean isBufferObjectMethodBinding(MethodBinding binding) {
+ return bufferObjectMethodBindings.containsKey(binding);
+ }
+
+ @Override
+ public void emitDefine(ConstantDefinition def, String optionalComment) throws Exception {
+ BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
+ if (null == glInfo) {
+ throw new Exception("No GLInfo for: " + def);
+ }
+ String symbolRenamed = def.getName();
+ StringBuilder newComment = new StringBuilder();
+ newComment.append("Part of <code>");
+ if (0 == addExtensionsOfSymbols2Buffer(newComment, ", ", symbolRenamed, def.getAliasedNames())) {
+ if (def.isEnum()) {
+ String enumName = def.getEnumName();
+ if (null != enumName) {
+ newComment.append(enumName);
+ } else {
+ newComment.append("CORE ENUM");
+ }
+ } else {
+ if (getGLConfig().getAllowNonGLExtensions()) {
+ newComment.append("CORE DEF");
+ } else {
+ // Note: All GL defines must be contained within an extension marker !
+ // #ifndef GL_EXT_lala
+ // #define GL_EXT_lala 1
+ // ...
+ // #endif
+ if (JavaConfiguration.DEBUG_IGNORES) {
+ StringBuilder sb = new StringBuilder();
+ JavaEmitter.addStrings2Buffer(sb, ", ", symbolRenamed, def.getAliasedNames());
+ System.err.println("Dropping marker: " + sb.toString());
+ }
+ return;
+ }
+ }
+ }
+ newComment.append("</code>");
+
+ if (null != optionalComment) {
+ newComment.append("<br>");
+ newComment.append(optionalComment);
+ }
+
+ super.emitDefine(def, newComment.toString());
+ }
+
+ public int addExtensionsOfSymbols2Buffer(StringBuilder buf, String sep, String first, Collection<String> col) {
+ BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
+ if (null == glInfo) {
+ throw new RuntimeException("No GLInfo for: " + first);
+ }
+ int num = 0;
+ if (null == buf) {
+ buf = new StringBuilder();
+ }
+ String extensionName;
+
+ Iterator<String> iter = col.iterator();
+ if (null != first) {
+ extensionName = glInfo.getExtension(first);
+ if (null != extensionName) {
+ buf.append(extensionName);
+ if (iter.hasNext()) {
+ buf.append(sep);
+ }
+ num++;
+ }
+ }
+ while (iter.hasNext()) {
+ extensionName = glInfo.getExtension(iter.next());
+ if (null != extensionName) {
+ buf.append(extensionName);
+ if (iter.hasNext()) {
+ buf.append(sep);
+ }
+ num++;
+ }
+ }
+ return num;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+ @Override
+ protected void generateModifiedEmitters(JavaMethodBindingEmitter baseJavaEmitter, List<FunctionEmitter> emitters) {
+ List<FunctionEmitter> superEmitters = new ArrayList<FunctionEmitter>();
+ super.generateModifiedEmitters(baseJavaEmitter, superEmitters);
+
+ // See whether this is one of the Buffer Object variants
+ boolean bufferObjectVariant = bufferObjectMethodBindings.containsKey(baseJavaEmitter.getBinding());
+
+ for (FunctionEmitter emitter : superEmitters) {
+ if (emitter instanceof ProcAddressJavaMethodBindingEmitter) {
+ emitter = new GLJavaMethodBindingEmitter((ProcAddressJavaMethodBindingEmitter) emitter, this, bufferObjectVariant);
+ }
+ emitters.add(emitter);
+ }
+ }
+
+ protected boolean needsBufferObjectVariant(FunctionSymbol sym) {
+ return getGLConfig().isBufferObjectFunction(sym.getName());
+ }
+
+ protected GLConfiguration getGLConfig() {
+ return (GLConfiguration) getConfig();
+ }
+
+ @Override
+ protected void endProcAddressTable() throws Exception {
+ PrintWriter w = tableWriter;
+
+ w.println(" /**");
+ w.println(" * This is a convenience method to get (by name) the native function");
+ w.println(" * pointer for a given function. It lets you avoid having to");
+ w.println(" * manually compute the &quot;" + PROCADDRESS_VAR_PREFIX + " + ");
+ w.println(" * &lt;functionName&gt;&quot; member variable name and look it up via");
+ w.println(" * reflection; it also will throw an exception if you try to get the");
+ w.println(" * address of an unknown function, or one that is statically linked");
+ w.println(" * and therefore does not have a function pointer in this table.");
+ w.println(" *");
+ w.println(" * @throws RuntimeException if the function pointer was not found in");
+ w.println(" * this table, either because the function was unknown or because");
+ w.println(" * it was statically linked.");
+ w.println(" */");
+ w.println(" public long getAddressFor(String functionNameUsr) {");
+ w.println(" String functionNameBase = "+GLExtensionNames.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLExtensionNames.normalizeARB(functionNameUsr, true), true);");
+ w.println(" String addressFieldNameBase = PROCADDRESS_VAR_PREFIX + functionNameBase;");
+ w.println(" java.lang.reflect.Field addressField = null;");
+ w.println(" int funcNamePermNum = "+GLExtensionNames.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
+ w.println(" for(int i = 0; null==addressField && i < funcNamePermNum; i++) {");
+ w.println(" String addressFieldName = "+GLExtensionNames.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+ w.println(" try {");
+ w.println(" addressField = getClass().getField(addressFieldName);");
+ w.println(" } catch (Exception e) { }");
+ w.println(" }");
+ w.println();
+ w.println(" if(null==addressField) {");
+ w.println(" // The user is calling a bogus function or one which is not");
+ w.println(" // runtime linked");
+ w.println(" throw new RuntimeException(");
+ w.println(" \"WARNING: Address field query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
+ w.println(" \"\\\"; it's either statically linked or address field is not a known \" +");
+ w.println(" \"function\");");
+ w.println(" } ");
+ w.println(" try {");
+ w.println(" return addressField.getLong(this);");
+ w.println(" } catch (Exception e) {");
+ w.println(" throw new RuntimeException(");
+ w.println(" \"WARNING: Address query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
+ w.println(" \"\\\"; it's either statically linked or is not a known \" +");
+ w.println(" \"function\", e);");
+ w.println(" }");
+ w.println(" }");
+
+ w.println("} // end of class " + tableClassName);
+ w.flush();
+ w.close();
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
new file mode 100755
index 000000000..be9b7b442
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. 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 com.jogamp.gluegen.opengl;
+
+import java.io.*;
+import com.jogamp.gluegen.*;
+import com.jogamp.gluegen.cgram.types.*;
+import com.jogamp.gluegen.procaddress.*;
+
+/** A specialization of the proc address emitter which knows how to
+change argument names to take into account Vertex Buffer Object /
+Pixel Buffer Object variants. */
+public class GLJavaMethodBindingEmitter extends ProcAddressJavaMethodBindingEmitter {
+
+ protected boolean bufferObjectVariant;
+ protected GLEmitter glEmitter;
+ protected CommentEmitter glCommentEmitter = new GLCommentEmitter();
+
+ public GLJavaMethodBindingEmitter(JavaMethodBindingEmitter methodToWrap, boolean callThroughProcAddress,
+ String getProcAddressTableExpr, boolean changeNameAndArguments, boolean bufferObjectVariant, GLEmitter emitter) {
+
+ super(methodToWrap, callThroughProcAddress, getProcAddressTableExpr, changeNameAndArguments, emitter);
+ this.bufferObjectVariant = bufferObjectVariant;
+ this.glEmitter = emitter;
+ setCommentEmitter(glCommentEmitter);
+ }
+
+ public GLJavaMethodBindingEmitter(ProcAddressJavaMethodBindingEmitter methodToWrap, GLEmitter emitter, boolean bufferObjectVariant) {
+ super(methodToWrap);
+ this.bufferObjectVariant = bufferObjectVariant;
+ this.glEmitter = emitter;
+ setCommentEmitter(glCommentEmitter);
+ }
+
+ public GLJavaMethodBindingEmitter(GLJavaMethodBindingEmitter methodToWrap) {
+ this(methodToWrap, methodToWrap.glEmitter, methodToWrap.bufferObjectVariant);
+ }
+
+ @Override
+ protected String getArgumentName(int i) {
+ String name = super.getArgumentName(i);
+
+ if (!bufferObjectVariant) {
+ return name;
+ }
+
+ // Emitters for VBO/PBO-related routines change the outgoing
+ // argument name for the buffer
+ if (binding.getJavaArgumentType(i).isLong()) {
+ Type cType = binding.getCArgumentType(i);
+ Type targetType = cType.asPointer().getTargetType();
+ if (cType.isPointer() && (targetType.isVoid() || targetType.isPrimitive())) {
+ return name + "_buffer_offset";
+ }
+ }
+
+ return name;
+ }
+
+ protected class GLCommentEmitter extends JavaMethodBindingEmitter.DefaultCommentEmitter {
+
+ @Override
+ protected void emitBindingCSignature(MethodBinding binding, PrintWriter writer) {
+
+ super.emitBindingCSignature(binding, writer);
+
+ String symbolRenamed = binding.getName();
+ StringBuilder newComment = new StringBuilder();
+
+ newComment.append("<br>Part of <code>");
+ if (0 == glEmitter.addExtensionsOfSymbols2Buffer(newComment, ", ", symbolRenamed, binding.getAliasedNames())) {
+ if (glEmitter.getGLConfig().getAllowNonGLExtensions()) {
+ newComment.append("CORE FUNC");
+ } else {
+ StringBuilder sb = new StringBuilder();
+ JavaEmitter.addStrings2Buffer(sb, ", ", symbolRenamed, binding.getAliasedNames());
+ RuntimeException ex = new RuntimeException("Couldn't find extension to: " + binding + " ; " + sb.toString());
+ glEmitter.getGLConfig().getGLInfo().dump();
+ // glEmitter.getGLConfig().dumpRenames();
+ throw ex;
+ }
+ }
+ newComment.append("</code>");
+ writer.print(newComment.toString());
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java b/src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java
new file mode 100644
index 000000000..e7a7e1d1c
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java
@@ -0,0 +1,305 @@
+package com.jogamp.gluegen.opengl.ant;
+
+/*
+ * StaticGLGenTask.java
+ * Copyright (C) 2003 Rob Grzywinski ([email protected])
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Copying, distribution and use of this software in source and binary
+ * forms, with or without modification, is permitted provided that the
+ * following conditions are met:
+ *
+ * Distributions of source code must reproduce the copyright notice,
+ * this list of conditions and the following disclaimer in the source
+ * code header files; and Distributions of binary code must reproduce
+ * the copyright notice, this list of conditions and the following
+ * disclaimer in the documentation, Read me file, license file and/or
+ * other materials provided with the software distribution.
+ *
+ * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright
+ * holder may not 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, NON-INTERFERENCE, ACCURACY OF
+ * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE
+ * COPYRIGHT HOLDER, SUN AND SUN'S 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 THE
+ * COPYRIGHT HOLDER, SUN OR SUN'S 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 ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT
+ * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION,
+ * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT
+ * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED
+ * WARRANTY OF FITNESS FOR SUCH USES.
+ */
+
+import java.io.IOException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Execute;
+import org.apache.tools.ant.taskdefs.LogStreamHandler;
+import org.apache.tools.ant.types.CommandlineJava;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.PatternSet;
+import org.apache.tools.ant.util.JavaEnvUtils;
+
+/**
+ * <p>An <a href="http://ant.apache.org">ANT</a> {@link org.apache.tools.ant.Task}
+ * for using {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo}.</p>
+ *
+ * <p>Usage:</p>
+ * <pre>
+ &lt;staticglgen package="[generated files package]"
+ headers="[file pattern of GL headers]"
+ outputdir="[directory to output the generated files]" /&gt;
+ * </pre>
+ *
+ * @author Rob Grzywinski <a href="mailto:[email protected]">[email protected]</a>
+ */
+// FIXME: blow out javadoc
+public class StaticGLGenTask extends Task
+{
+ /**
+ * <p>The {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo} classname.</p>
+ */
+ private static final String GL_GEN = "com.jogamp.gluegen.opengl.BuildStaticGLInfo";
+
+ // =========================================================================
+ /**
+ * <p>The {@link org.apache.tools.ant.types.CommandlineJava} that is used
+ * to execute {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo}.</p>
+ */
+ private CommandlineJava glgenCommandline;
+
+ // =========================================================================
+ /**
+ * <p>The package name for the generated files.</p>
+ */
+ private String packageName;
+
+ /**
+ * <p>The output directory.</p>
+ */
+ private String outputDirectory;
+
+ /**
+ * <p>The {@link org.apache.tools.ant.types.FileSet} of GL headers.</p>
+ */
+ private FileSet headerSet = new FileSet();
+
+ // =========================================================================
+ /**
+ * <p>Create and add the VM and classname to {@link org.apache.tools.ant.types.CommandlineJava}.</p>
+ */
+ public StaticGLGenTask()
+ {
+ // create the CommandlineJava that will be used to call BuildStaticGLInfo
+ glgenCommandline = new CommandlineJava();
+
+ // set the VM and classname in the commandline
+ glgenCommandline.setVm(JavaEnvUtils.getJreExecutable("java"));
+ glgenCommandline.setClassname(GL_GEN);
+ }
+
+ // =========================================================================
+ // ANT getters and setters
+ /**
+ * <p>Set the package name for the generated files. This is called by ANT.</p>
+ *
+ * @param packageName the name of the package for the generated files
+ */
+ public void setPackage(String packageName)
+ {
+ log( ("Setting package name to: " + packageName), Project.MSG_VERBOSE);
+ this.packageName = packageName;
+ }
+
+ /**
+ * <p>Set the output directory. This is called by ANT.</p>
+ *
+ * @param directory the output directory
+ */
+ public void setOutputDir(String directory)
+ {
+ log( ("Setting output directory to: " + directory),
+ Project.MSG_VERBOSE);
+ this.outputDirectory = directory;
+ }
+
+ /**
+ * <p>Add a header file to the list. This is called by ANT for a nested
+ * element.</p>
+ *
+ * @return {@link org.apache.tools.ant.types.PatternSet.NameEntry}
+ */
+ public PatternSet.NameEntry createHeader()
+ {
+ return headerSet.createInclude();
+ }
+
+ /**
+ * <p>Add a header file to the list. This is called by ANT for a nested
+ * element.</p>
+ *
+ * @return {@link org.apache.tools.ant.types.PatternSet.NameEntry}
+ */
+ public PatternSet.NameEntry createHeadersFile()
+ {
+ return headerSet.createIncludesFile();
+ }
+
+ /**
+ * <p>Set the set of header patterns. Patterns may be separated by a comma
+ * or a space. This is called by ANT.</p>
+ *
+ * @param headers the string containing the header patterns
+ */
+ public void setHeaders(String headers)
+ {
+ headerSet.setIncludes(headers);
+ }
+
+ /**
+ * <p>Add an optional classpath that defines the location of {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo}
+ * and <code>BuildStaticGLInfo</code>'s dependencies.</p>
+ *
+ * @returns {@link org.apache.tools.ant.types.Path}
+ */
+ public Path createClasspath()
+ {
+ return glgenCommandline.createClasspath(project).createPath();
+ }
+
+ // =========================================================================
+ /**
+ * <p>Run the task. This involves validating the set attributes, creating
+ * the command line to be executed and finally executing the command.</p>
+ *
+ * @see org.apache.tools.ant.Task#execute()
+ */
+ public void execute()
+ throws BuildException
+ {
+ // validate that all of the required attributes have been set
+ validateAttributes();
+
+ // TODO: add logic to determine if the generated file needs to be
+ // regenerated
+
+ // add the attributes to the CommandlineJava
+ addAttributes();
+
+ log(glgenCommandline.describeCommand(), Project.MSG_VERBOSE);
+
+ // execute the command and throw on error
+ final int error = execute(glgenCommandline.getCommandline());
+ if(error == 1)
+ throw new BuildException( ("BuildStaticGLInfo returned: " + error), location);
+ }
+
+ /**
+ * <p>Ensure that the user specified all required arguments.</p>
+ *
+ * @throws BuildException if there are required arguments that are not
+ * present or not valid
+ */
+ private void validateAttributes()
+ throws BuildException
+ {
+ // validate that the package name is set
+ if(!isValid(packageName))
+ throw new BuildException("Invalid package name: " + packageName);
+
+ // validate that the output directory is set
+ // TODO: switch to file and ensure that it exists
+ if(!isValid(outputDirectory))
+ throw new BuildException("Invalid output directory name: " + outputDirectory);
+
+ // TODO: validate that there are headers set
+ }
+
+ /**
+ * <p>Is the specified string valid? A valid string is non-<code>null</code>
+ * and has a non-zero length.</p>
+ *
+ * @param string the string to be tested for validity
+ * @return <code>true</code> if the string is valid. <code>false</code>
+ * otherwise.
+ */
+ private boolean isValid(String string)
+ {
+ // check for null
+ if(string == null)
+ return false;
+
+ // ensure that the string has a non-zero length
+ // NOTE: must trim() to remove leading and trailing whitespace
+ if(string.trim().length() < 1)
+ return false;
+
+ // the string is valid
+ return true;
+ }
+
+ /**
+ * <p>Add all of the attributes to the command line. They have already
+ * been validated.</p>
+ */
+ private void addAttributes()
+ {
+ // add the package name
+ glgenCommandline.createArgument().setValue(packageName);
+
+ // add the output directory name
+ glgenCommandline.createArgument().setValue(outputDirectory);
+
+ // add the header -files- from the FileSet
+ headerSet.setDir(getProject().getBaseDir());
+ DirectoryScanner directoryScanner = headerSet.getDirectoryScanner(getProject());
+ String[] directoryFiles = directoryScanner.getIncludedFiles();
+ for(int i=0; i<directoryFiles.length; i++)
+ {
+ glgenCommandline.createArgument().setValue(directoryFiles[i]);
+ }
+ }
+
+ /**
+ * <p>Execute {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo} in a
+ * forked JVM.</p>
+ *
+ * @throws BuildException
+ */
+ private int execute(String[] command)
+ throws BuildException
+ {
+ // create the object that will perform the command execution
+ Execute execute = new Execute(new LogStreamHandler(this, Project.MSG_INFO,
+ Project.MSG_WARN),
+ null);
+
+ // set the project and command line
+ execute.setAntRun(project);
+ execute.setCommandline(command);
+ execute.setWorkingDirectory( project.getBaseDir() );
+
+ // execute the command
+ try
+ {
+ return execute.execute();
+ } catch(IOException ioe)
+ {
+ throw new BuildException(ioe, location);
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java
new file mode 100755
index 000000000..6f9f9b3bf
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. 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 com.jogamp.gluegen.opengl.nativesig;
+
+import java.io.*;
+import java.util.*;
+
+import com.jogamp.gluegen.MethodBinding;
+import com.jogamp.gluegen.FunctionEmitter;
+import com.jogamp.gluegen.JavaMethodBindingEmitter;
+import com.jogamp.gluegen.JavaType;
+
+import com.jogamp.gluegen.*;
+import com.jogamp.gluegen.cgram.types.*;
+import com.jogamp.gluegen.opengl.*;
+import com.jogamp.gluegen.procaddress.*;
+
+/**
+ * Emitter producing NativeSignature attributes.
+ */
+public class NativeSignatureEmitter extends GLEmitter {
+
+ @Override
+ protected List<? extends FunctionEmitter> generateMethodBindingEmitters(Set<MethodBinding> methodBindingSet, FunctionSymbol sym) throws Exception {
+
+ // Allow superclass to do most of the work for us
+ List<? extends FunctionEmitter> res = super.generateMethodBindingEmitters(methodBindingSet, sym);
+
+ // Filter out all non-JavaMethodBindingEmitters
+ for (Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
+ FunctionEmitter emitter = iter.next();
+ if (!(emitter instanceof JavaMethodBindingEmitter)) {
+ iter.remove();
+ }
+ }
+
+ if (res.isEmpty()) {
+ return res;
+ }
+
+ PrintWriter writer = (getConfig().allStatic() ? javaWriter() : javaImplWriter());
+
+ List<FunctionEmitter> processed = new ArrayList<FunctionEmitter>();
+
+ // First, filter out all emitters going to the "other" (public) writer
+ for (Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
+ FunctionEmitter emitter = iter.next();
+ if (emitter.getDefaultOutput() != writer) {
+ processed.add(emitter);
+ iter.remove();
+ }
+ }
+
+ // Now process all of the remaining emitters sorted by MethodBinding
+ while (!res.isEmpty()) {
+ List<JavaMethodBindingEmitter> emittersForBinding = new ArrayList<JavaMethodBindingEmitter>();
+ JavaMethodBindingEmitter emitter = (JavaMethodBindingEmitter) res.remove(0);
+ emittersForBinding.add(emitter);
+ MethodBinding binding = emitter.getBinding();
+ for (Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
+ JavaMethodBindingEmitter emitter2 = (JavaMethodBindingEmitter) iter.next();
+ if (emitter2.getBinding() == binding) {
+ emittersForBinding.add(emitter2);
+ iter.remove();
+ }
+ }
+ generateNativeSignatureEmitters(binding, emittersForBinding);
+ processed.addAll(emittersForBinding);
+ }
+
+ return processed;
+ }
+
+ protected void generateNativeSignatureEmitters(MethodBinding binding, List<JavaMethodBindingEmitter> allEmitters) {
+
+ if (allEmitters.isEmpty()) {
+ return;
+ }
+
+ PrintWriter writer = (getConfig().allStatic() ? javaWriter() : javaImplWriter());
+
+ // Give ourselves the chance to interpose on the generation of all code to keep things simple
+ List<JavaMethodBindingEmitter> newEmitters = new ArrayList<JavaMethodBindingEmitter>();
+ for (JavaMethodBindingEmitter javaEmitter : allEmitters) {
+ NativeSignatureJavaMethodBindingEmitter newEmitter = null;
+ if (javaEmitter instanceof GLJavaMethodBindingEmitter) {
+ newEmitter = new NativeSignatureJavaMethodBindingEmitter((GLJavaMethodBindingEmitter) javaEmitter);
+ } else if (javaEmitter instanceof ProcAddressJavaMethodBindingEmitter) {
+ newEmitter = new NativeSignatureJavaMethodBindingEmitter((ProcAddressJavaMethodBindingEmitter) javaEmitter);
+ } else {
+ newEmitter = new NativeSignatureJavaMethodBindingEmitter(javaEmitter, this);
+ }
+ newEmitters.add(newEmitter);
+ }
+ allEmitters.clear();
+ allEmitters.addAll(newEmitters);
+
+ // Detect whether we need to produce more or modify some of these emitters.
+ // Note that at this point we are assuming that generatePublicEmitters has
+ // been called with signatureOnly both true and false.
+ if (signatureContainsStrings(binding) && !haveEmitterWithBody(allEmitters)) {
+ // This basically handles glGetString but also any similar methods
+ NativeSignatureJavaMethodBindingEmitter javaEmitter = findEmitterWithWriter(allEmitters, writer);
+
+ // First, we need to clone this emitter to produce the native
+ // entry point
+ NativeSignatureJavaMethodBindingEmitter emitter = new NativeSignatureJavaMethodBindingEmitter(javaEmitter);
+ emitter.removeModifier(JavaMethodBindingEmitter.PUBLIC);
+ emitter.addModifier(JavaMethodBindingEmitter.PRIVATE);
+ emitter.setForImplementingMethodCall(true);
+ // Note: this is chosen so we don't have to change the logic in
+ // emitReturnVariableSetupAndCall which decides which variant
+ // (direct / indirect) to call
+ emitter.setForDirectBufferImplementation(true);
+ allEmitters.add(emitter);
+
+ // Now make the original emitter non-native and cause it to emit a body
+ javaEmitter.removeModifier(JavaMethodBindingEmitter.NATIVE);
+ javaEmitter.setEmitBody(true);
+ }
+ }
+
+ protected boolean signatureContainsStrings(MethodBinding binding) {
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ JavaType type = binding.getJavaArgumentType(i);
+ if (type.isString() || type.isStringArray()) {
+ return true;
+ }
+ }
+ JavaType retType = binding.getJavaReturnType();
+ if (retType.isString() || retType.isStringArray()) {
+ return true;
+ }
+ return false;
+ }
+
+ protected boolean haveEmitterWithBody(List<JavaMethodBindingEmitter> allEmitters) {
+ for (JavaMethodBindingEmitter emitter : allEmitters) {
+ if (!emitter.signatureOnly()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected NativeSignatureJavaMethodBindingEmitter findEmitterWithWriter(List<JavaMethodBindingEmitter> allEmitters, PrintWriter writer) {
+ for (JavaMethodBindingEmitter jemitter : allEmitters) {
+ NativeSignatureJavaMethodBindingEmitter emitter = (NativeSignatureJavaMethodBindingEmitter)jemitter;
+ if (emitter.getDefaultOutput() == writer) {
+ return emitter;
+ }
+ }
+ throw new RuntimeException("Unexpectedly failed to find an emitter with the given writer");
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java
new file mode 100755
index 000000000..a39145739
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. 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 com.jogamp.gluegen.opengl.nativesig;
+
+import java.io.*;
+
+import com.jogamp.gluegen.*;
+import com.jogamp.gluegen.cgram.types.*;
+import com.jogamp.gluegen.opengl.*;
+import com.jogamp.gluegen.procaddress.*;
+
+public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBindingEmitter {
+
+ public NativeSignatureJavaMethodBindingEmitter(GLJavaMethodBindingEmitter methodToWrap) {
+ super(methodToWrap);
+ }
+
+ public NativeSignatureJavaMethodBindingEmitter(ProcAddressJavaMethodBindingEmitter methodToWrap, GLEmitter emitter, boolean bufferObjectVariant) {
+ super(methodToWrap, emitter, bufferObjectVariant);
+ }
+
+ public NativeSignatureJavaMethodBindingEmitter(JavaMethodBindingEmitter methodToWrap, NativeSignatureEmitter emitter) {
+ super(methodToWrap, false, null, false, false, emitter);
+ }
+
+ @Override
+ protected void emitSignature(PrintWriter writer) {
+ writer.print(getBaseIndentString());
+ emitNativeSignatureAnnotation(writer);
+ super.emitSignature(writer);
+ }
+
+ protected void emitNativeSignatureAnnotation(PrintWriter writer) {
+ if (hasModifier(JavaMethodBindingEmitter.NATIVE)) {
+ // Emit everything as a leaf for now
+ // FIXME: make this configurable
+ writer.print("@NativeSignature(\"l");
+ MethodBinding binding = getBinding();
+ if (callThroughProcAddress) {
+ writer.print("p");
+ }
+ writer.print("(");
+ if (callThroughProcAddress) {
+ writer.print("P");
+ }
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ emitNativeSignatureElement(writer, binding.getJavaArgumentType(i), binding.getCArgumentType(i), i);
+ }
+ writer.print(")");
+ emitNativeSignatureElement(writer, binding.getJavaReturnType(), binding.getCReturnType(), -1);
+ writer.println("\")");
+ }
+ }
+
+ protected void emitNativeSignatureElement(PrintWriter writer, JavaType type, Type cType, int index) {
+ if (type.isVoid()) {
+ if (index > 0) {
+ throw new InternalError("Error parsing arguments -- void should not be seen aside from argument 0");
+ }
+ return;
+ }
+
+ if (type.isNIOBuffer()) {
+ writer.print("A");
+ } else if (type.isPrimitiveArray()) {
+ writer.print("MO");
+ } else if (type.isPrimitive()) {
+ Class clazz = type.getJavaClass();
+ if (clazz == Byte.TYPE) { writer.print("B"); }
+ else if (clazz == Character.TYPE) { writer.print("C"); }
+ else if (clazz == Double.TYPE) { writer.print("D"); }
+ else if (clazz == Float.TYPE) { writer.print("F"); }
+ else if (clazz == Integer.TYPE) { writer.print("I"); }
+ else if (clazz == Long.TYPE) {
+ // See if this is intended to be a pointer at the C level
+ if (cType.isPointer()) {
+ writer.print("A");
+ } else {
+ writer.print("J");
+ }
+ }
+ else if (clazz == Short.TYPE) { writer.print("S"); }
+ else if (clazz == Boolean.TYPE) { writer.print("Z"); }
+ else throw new InternalError("Unhandled primitive type " + clazz);
+ } else if (type.isString()) {
+ writer.print("A");
+ } else {
+ throw new RuntimeException("Type not yet handled: " + type);
+ }
+ }
+
+ protected String getReturnTypeString(boolean skipArray) {
+ if (isForImplementingMethodCall()) {
+ JavaType returnType = getBinding().getJavaReturnType();
+ if (returnType.isString() || returnType.isNIOByteBuffer()) {
+ // Treat these as addresses
+ return "long";
+ }
+ }
+ return super.getReturnTypeString(skipArray);
+ }
+
+ protected void emitPreCallSetup(MethodBinding binding, PrintWriter writer) {
+ super.emitPreCallSetup(binding, writer);
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ JavaType type = binding.getJavaArgumentType(i);
+ if (type.isNIOBuffer() && !directNIOOnly) {
+ // Emit declarations for variables holding primitive arrays as type Object
+ // We don't know 100% sure we're going to use these at this point in the code, though
+ writer.println(" Object " + getNIOBufferArrayName(i) + " = (_direct ? null : Buffers.getArray(" +
+ getArgumentName(i) + "));");
+ } else if (type.isString()) {
+ writer.println(" long " + binding.getArgumentName(i) + "_c_str = BuffersInternal.newCString(" + binding.getArgumentName(i) + ");");
+ }
+ // FIXME: going to need more of these for Buffer[] and String[], at least
+ }
+ }
+
+ protected String getNIOBufferArrayName(int argNumber) {
+ return "__buffer_array_" + argNumber;
+ }
+
+ protected int emitArguments(PrintWriter writer)
+ {
+ boolean needComma = false;
+ int numEmitted = 0;
+
+ if (callThroughProcAddress) {
+ if (changeNameAndArguments) {
+ writer.print("long procAddress");
+ ++numEmitted;
+ needComma = true;
+ }
+ }
+
+ if (forImplementingMethodCall && binding.hasContainingType()) {
+ if (needComma) {
+ writer.print(", ");
+ }
+
+ // Always emit outgoing "this" argument
+ writer.print("long ");
+ writer.print(javaThisArgumentName());
+ ++numEmitted;
+ needComma = true;
+ }
+
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ JavaType type = binding.getJavaArgumentType(i);
+ 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.
+ if (binding.getNumArguments() != 1) {
+ throw new InternalError(
+ "\"void\" argument type found in " +
+ "multi-argument function \"" + binding + "\"");
+ }
+ continue;
+ }
+
+ if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) {
+ // Don't need to expose these at the Java level
+ continue;
+ }
+
+ if (needComma) {
+ writer.print(", ");
+ }
+
+ if (forImplementingMethodCall &&
+ (forDirectBufferImplementation && type.isNIOBuffer() ||
+ type.isString())) {
+ // Direct Buffers and Strings go out as longs
+ writer.print("long");
+ // FIXME: will need more tests here to handle other constructs like String and direct Buffer arrays
+ } else {
+ writer.print(erasedTypeString(type, false));
+ }
+ writer.print(" ");
+ writer.print(getArgumentName(i));
+
+ ++numEmitted;
+ needComma = true;
+
+ // Add Buffer and array index offset arguments after each associated argument
+ if (forIndirectBufferAndArrayImplementation) {
+ if (type.isNIOBuffer()) {
+ writer.print(", int " + byteOffsetArgName(i));
+ } else if (type.isNIOBufferArray()) {
+ writer.print(", int[] " +
+ byteOffsetArrayArgName(i));
+ }
+ }
+
+ // Add offset argument after each primitive array
+ if (type.isPrimitiveArray()) {
+ writer.print(", int " + offsetArgName(i));
+ }
+ }
+ return numEmitted;
+ }
+
+ 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("java.nio.ByteBuffer _res;");
+ needsResultAssignment = true;
+ } else if (returnType.isArrayOfCompoundTypeWrappers()) {
+ writer.println("java.nio.ByteBuffer[] _res;");
+ needsResultAssignment = true;
+ } else if (returnType.isString() || returnType.isNIOByteBuffer()) {
+ writer.print(returnType);
+ writer.println(" _res;");
+ needsResultAssignment = true;
+ } else {
+ // Always assign to "_res" variable so we can clean up
+ // outgoing String arguments, for example
+ emitReturnType(writer);
+ writer.println(" _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 = ");
+ if (returnType.isString()) {
+ writer.print("BuffersInternal.newJavaString(");
+ } else if (returnType.isNIOByteBuffer()) {
+ writer.print("BuffersInternal.newDirectByteBuffer(");
+ }
+ } 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);
+ if (returnType.isString() || returnType.isNIOByteBuffer()) {
+ writer.print(")");
+ }
+ writer.print(";");
+ writer.println();
+ } else {
+ emitCall(binding, writer);
+ if (returnType.isString() || returnType.isNIOByteBuffer()) {
+ writer.print(")");
+ }
+ writer.print(";");
+ }
+
+ 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);
+ writer.print(";");
+ writer.println();
+ writer.println(" }");
+ } else {
+ writer.println();
+ }
+ emitPrologueOrEpilogue(epilogue, writer);
+ if (needsResultAssignment) {
+ emitCallResultReturn(binding, writer);
+ }
+ }
+
+ protected int emitCallArguments(MethodBinding binding, PrintWriter writer, boolean direct) {
+ // Note that we override this completely because we both need to
+ // move the potential location of the outgoing proc address as
+ // well as change the way we pass out Buffers, arrays, Strings, etc.
+
+ boolean needComma = false;
+ int numArgsEmitted = 0;
+
+ if (callThroughProcAddress) {
+ writer.print("__addr_");
+ needComma = true;
+ ++numArgsEmitted;
+ }
+
+ if (binding.hasContainingType()) {
+ // Emit this pointer
+ assert(binding.getContainingType().isCompoundTypeWrapper());
+ writer.print("BuffersInternal.getDirectBufferAddress(");
+ writer.print("getBuffer()");
+ writer.print(")");
+ 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("BuffersInternal.getDirectBufferAddress(");
+ writer.print("((");
+ }
+
+ if (type.isNIOBuffer()) {
+ if (!direct) {
+ writer.print(getNIOBufferArrayName(i));
+ } else {
+ writer.print("BuffersInternal.getDirectBufferAddress(");
+ writer.print(getArgumentName(i));
+ writer.print(")");
+ }
+ } else {
+ writer.print(getArgumentName(i));
+ }
+
+ if (type.isCompoundTypeWrapper()) {
+ writer.print(" == null) ? null : ");
+ writer.print(getArgumentName(i));
+ writer.print(".getBuffer())");
+ writer.print(")");
+ }
+
+ if (type.isNIOBuffer()) {
+ if (direct) {
+ writer.print("+ Buffers.getDirectBufferByteOffset(" + getArgumentName(i) + ")");
+ } else {
+ writer.print(", BuffersInternal.arrayBaseOffset(" +
+ getNIOBufferArrayName(i) +
+ ") + Buffers.getIndirectBufferByteOffset(" + getArgumentName(i) + ")");
+ }
+ } else if (type.isNIOBufferArray()) {
+ writer.print(", " + byteOffsetArrayArgName(i));
+ }
+
+ // Add Array offset parameter for primitive arrays
+ if (type.isPrimitiveArray()) {
+ writer.print(", ");
+ writer.print("BuffersInternal.arrayBaseOffset(" + getArgumentName(i) + ") + ");
+ if(type.isFloatArray()) {
+ writer.print("Buffers.SIZEOF_FLOAT * ");
+ } else if(type.isDoubleArray()) {
+ writer.print("Buffers.SIZEOF_DOUBLE * ");
+ } else if(type.isByteArray()) {
+ writer.print("1 * ");
+ } else if(type.isLongArray()) {
+ writer.print("Buffers.SIZEOF_LONG * ");
+ } else if(type.isShortArray()) {
+ writer.print("Buffers.SIZEOF_SHORT * ");
+ } else if(type.isIntArray()) {
+ writer.print("Buffers.SIZEOF_INT * ");
+ } else {
+ throw new RuntimeException("Unsupported type for calculating array offset argument for " +
+ getArgumentName(i) +
+ "-- error occurred while processing Java glue code for " + getName());
+ }
+ writer.print(offsetArgName(i));
+ }
+
+ if (type.isString()) {
+ writer.print("_c_str");
+ }
+
+ if (type.isCompoundTypeWrapper()) {
+ writer.print(")");
+ }
+
+ needComma = true;
+ ++numArgsEmitted;
+ }
+ return numArgsEmitted;
+ }
+
+ protected void emitCallResultReturn(MethodBinding binding, PrintWriter writer) {
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ JavaType type = binding.getJavaArgumentType(i);
+ if (type.isString()) {
+ writer.println(";");
+ writer.println(" BuffersInternal.freeCString(" + binding.getArgumentName(i) + "_c_str);");
+ }
+ // FIXME: will need more of these cleanups for things like Buffer[] and String[] (see above)
+ }
+
+ super.emitCallResultReturn(binding, writer);
+ }
+
+ public String getName() {
+ String res = super.getName();
+ if (forImplementingMethodCall && bufferObjectVariant) {
+ return res + "BufObj";
+ }
+ return res;
+ }
+
+ protected String getImplMethodName(boolean direct) {
+ String name = null;
+ if (direct) {
+ name = binding.getName() + "$0";
+ } else {
+ name = binding.getName() + "$1";
+ }
+ if (bufferObjectVariant) {
+ return name + "BufObj";
+ }
+ return name;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java
new file mode 100644
index 000000000..914036312
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2003-2005 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.
+ *
+ */
+
+package com.jogamp.gluegen.runtime.opengl;
+
+import java.util.*;
+import com.jogamp.gluegen.runtime.*;
+
+public class GLExtensionNames {
+ //GL_XYZ : GL_XYZ, GL_XYZ_GL2, GL_XYZ_ARB, GL_XYZ_OES, GL_XYZ_OML
+ //GL_XYZ : GL_XYZ, GL_GL2_XYZ, GL_ARB_XYZ, GL_OES_XYZ, GL_OML_XYZ
+ //
+ // Pass-1 Unify ARB extensions with the same value
+ // Pass-2 Unify vendor extensions,
+ // if exist as an ARB extension with the same value.
+ // Pass-3 Emit
+
+ public static final String[] extensionsARB = { "ARB", "GL2", "OES", "KHR", "OML" };
+ public static final String[] extensionsVEN = { "3DFX",
+ "AMD",
+ "ANGLE",
+ "ARM",
+ "APPLE",
+ "ATI",
+ "EXT",
+ "HI",
+ "HP",
+ "IBM",
+ "IMG",
+ "MESA",
+ "MESAX",
+ "NV",
+ "QCOM",
+ "SGI",
+ "SGIS",
+ "SGIX",
+ "SUN",
+ "VIV",
+ "WIN"
+ };
+
+
+ public static final boolean isGLFunction(String str) {
+ return str.startsWith("gl") || /* str.startsWith("glu") || str.startsWith("glX") || */
+ str.startsWith("egl") || str.startsWith("wgl") || str.startsWith("agl") ||
+ str.startsWith("cgl") ;
+ }
+
+ public static final boolean isGLEnumeration(String str) {
+ return str.startsWith("GL_") || str.startsWith("GLU_") || str.startsWith("GLX_") ||
+ str.startsWith("EGL_") || str.startsWith("WGL_") || str.startsWith("AGL_") ||
+ str.startsWith("CGL_") ;
+ }
+
+ public static final int getExtensionIdx(String[] extensions, String str, boolean isGLFunc) {
+ if(isGLFunc) {
+ for(int i = extensions.length - 1 ; i>=0 ; i--) {
+ if( str.endsWith(extensions[i]) ) {
+ return i;
+ }
+ }
+ } else {
+ for(int i = extensions.length - 1 ; i>=0 ; i--) {
+ if( str.endsWith("_"+extensions[i]) ) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static final boolean isExtension(String[] extensions, String str, boolean isGLFunc) {
+ return getExtensionIdx(extensions, str, isGLFunc)>=0;
+ }
+
+ public static final String getExtensionSuffix(String str, boolean isGLFunc) {
+ int idx = getExtensionIdx(extensionsARB, str, isGLFunc);
+ if(idx>=0) {
+ return extensionsARB[idx];
+ }
+ idx = getExtensionIdx(extensionsVEN, str, isGLFunc);
+ if(idx>=0) {
+ return extensionsVEN[idx];
+ }
+ return null;
+ }
+
+ public static final String normalize(String[] extensions, String str, boolean isGLFunc) {
+ boolean touched = false;
+ for(int i = extensions.length - 1 ; !touched && i>=0 ; i--) {
+ if(isGLFunc) {
+ if(str.endsWith(extensions[i])) {
+ // functions
+ str = str.substring(0, str.length()-extensions[i].length());
+ touched=true;
+ }
+ } else {
+ if(str.endsWith("_"+extensions[i])) {
+ // enums
+ str = str.substring(0, str.length()-1-extensions[i].length());
+ touched=true;
+ }
+ }
+ }
+ return str;
+ }
+ public static final String normalizeARB(String str, boolean isGLFunc) {
+ return normalize(extensionsARB, str, isGLFunc);
+ }
+ public static final boolean isExtensionARB(String str, boolean isGLFunc) {
+ return isExtension(extensionsARB, str, isGLFunc);
+ }
+ public static final String normalizeVEN(String str, boolean isGLFunc) {
+ return normalize(extensionsVEN, str, isGLFunc);
+ }
+ public static final boolean isExtensionVEN(String str, boolean isGLFunc) {
+ return isExtension(extensionsVEN, str, isGLFunc);
+ }
+ public static final String normalize(String str, boolean isGLFunc) {
+ if (isExtensionARB(str, isGLFunc)) {
+ return normalizeARB(str, isGLFunc);
+ }
+ if (isExtensionVEN(str, isGLFunc)) {
+ return normalizeVEN(str, isGLFunc);
+ }
+ return str;
+ }
+ public static final boolean isExtension(String str, boolean isGLFunc) {
+ return isExtension(extensionsARB, str, isGLFunc) ||
+ isExtension(extensionsVEN, str, isGLFunc);
+ }
+
+ public static final int getFuncNamePermutationNumber(String name) {
+ if(isExtensionARB(name, true) || isExtensionVEN(name, true)) {
+ // no name permutation, if it's already a known extension
+ return 1;
+ }
+ return 1 + extensionsARB.length + extensionsVEN.length;
+ }
+
+ public static final String getFuncNamePermutation(String name, int i) {
+ // identity
+ if(i==0) {
+ return name;
+ }
+ if(0>i || i>=(1+extensionsARB.length + extensionsVEN.length)) {
+ throw new RuntimeException("Index out of range [0.."+(1+extensionsARB.length+extensionsVEN.length-1)+"]: "+i);
+ }
+ // ARB
+ i-=1;
+ if(i<extensionsARB.length) {
+ return name+extensionsARB[i];
+ }
+ // VEN
+ i-=extensionsARB.length;
+ return name+extensionsVEN[i];
+ }
+}
+
diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
new file mode 100644
index 000000000..fe9efebc7
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+/*
+ * Created on Saturday, April 24 2010 16:44
+ */
+package com.jogamp.gluegen.runtime.opengl;
+
+import com.jogamp.common.os.DynamicLookupHelper;
+import com.jogamp.gluegen.runtime.FunctionAddressResolver;
+
+/**
+ * @author Sven Gothel
+ * @author Michael Bien
+ */
+public class GLProcAddressResolver implements FunctionAddressResolver {
+
+ public static final boolean DEBUG = false;
+
+ public long resolve(String name, DynamicLookupHelper lookup) {
+
+ long newProcAddress = 0;
+ int permutations = GLExtensionNames.getFuncNamePermutationNumber(name);
+
+ for (int i = 0; 0 == newProcAddress && i < permutations; i++) {
+ String funcName = GLExtensionNames.getFuncNamePermutation(name, i);
+ try {
+ newProcAddress = lookup.dynamicLookupFunction(funcName);
+ } catch (Exception e) {
+ if (DEBUG) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return newProcAddress;
+ }
+}