40package com.jogamp.gluegen.opengl;
42import static java.util.logging.Level.INFO;
44import com.jogamp.gluegen.ConstantDefinition;
45import com.jogamp.gluegen.FunctionEmitter;
46import com.jogamp.gluegen.GlueEmitterControls;
47import com.jogamp.gluegen.GlueGen;
48import com.jogamp.gluegen.JavaCodeUnit;
49import com.jogamp.gluegen.JavaConfiguration;
50import com.jogamp.gluegen.JavaEmitter;
51import com.jogamp.gluegen.JavaMethodBindingEmitter;
52import com.jogamp.gluegen.JavaType;
53import com.jogamp.gluegen.MethodBinding;
54import com.jogamp.gluegen.SymbolFilter;
55import com.jogamp.gluegen.cgram.types.FunctionSymbol;
56import com.jogamp.gluegen.cgram.types.Type;
57import com.jogamp.gluegen.procaddress.ProcAddressEmitter;
58import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter;
59import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
61import java.io.IOException;
62import java.util.ArrayList;
63import java.util.IdentityHashMap;
64import java.util.Iterator;
65import java.util.LinkedHashMap;
78 private final Map<MethodBinding, MethodBinding> bufferObjectMethodBindings =
new IdentityHashMap<MethodBinding, MethodBinding>();
80 enum BufferObjectKind { UNPACK_PIXEL, PACK_PIXEL, ARRAY, ELEMENT, INDIRECT}
83 public void beginEmission(
final GlueEmitterControls controls)
throws IOException {
86 throw new RuntimeException(
"No 'GLSemHeader' defined.");
90 throw new InternalError(
"XXX");
94 unifyExtensions(controls);
96 super.beginEmission(controls);
111 final String headerType = isSemHeader ?
"GLSemHeader" :
"GLDocHeader";
114 for (
final String extension : extensionSet) {
116 LOG.log(INFO,
"<RenameExtensionIntoCore: {0} IGNORED {1}>", extension, headerType);
118 LOG.log(INFO,
"<RenameExtensionIntoCore: {0} BEGIN {1}", extension, headerType);
120 if (declarations !=
null) {
121 for (
final Iterator<String> iterator = declarations.iterator(); iterator.hasNext();) {
122 final String decl = iterator.next();
124 boolean isGLEnumeration =
false;
128 if (isGLFunction || isGLEnumeration) {
130 if (!renamed.equals(decl)) {
142 LOG.log(INFO,
"RenameExtensionIntoCore: {0} END>", extension, headerType);
147 class ExtensionUnifier
implements SymbolFilter {
149 private List<ConstantDefinition> constants;
150 private List<FunctionSymbol> functions;
153 public List<ConstantDefinition> getConstants() {
157 public List<FunctionSymbol> getFunctions() {
162 public void filterSymbols(
final List<ConstantDefinition> inConstList,
163 final List<FunctionSymbol> inFuncList) {
165 if (glInfo ==
null) {
169 final Map<String, ConstantDefinition> constantMap =
new LinkedHashMap<String, ConstantDefinition>();
170 for (
final ConstantDefinition def : inConstList) {
171 constantMap.put(def.getName(), def);
173 final Map<String, FunctionSymbol> functionMap =
new LinkedHashMap<String, FunctionSymbol>();
174 for (
final FunctionSymbol sym : inFuncList) {
175 functionMap.put(sym.getName(), sym);
186 final Set<String> extensionNames = glInfo.getExtensions();
188 for (
final String extension : extensionNames) {
189 final Set<String> declarations = glInfo.getDeclarations(extension);
190 boolean isExtension =
true;
191 boolean shouldUnify =
true;
193 for (
final String decl : declarations) {
194 final boolean isFunc = !decl.startsWith(
"GL_");
195 if (!GLNameResolver.isExtension(decl, isFunc)) {
202 if (!functionMap.containsKey(decl)) {
207 if (!constantMap.containsKey(decl)) {
213 final String unifiedName = GLNameResolver.normalize(decl, isFunc);
224 shouldUnify = (glInfo.getExtension(unifiedName) !=
null);
236 for (
final String decl : declarations) {
237 final boolean isFunc = !decl.startsWith(
"GL_");
239 functionMap.remove(decl);
241 constantMap.remove(decl);
244 System.err.println(
"INFO: unified extension " + extension +
" into core API");
246 System.err.println(
"INFO: didn't unify extension " + extension +
" into core API because of " + cause);
250 constants =
new ArrayList<ConstantDefinition>(constantMap.values());
251 functions =
new ArrayList<FunctionSymbol>(functionMap.values());
255 private void unifyExtensions(
final GlueEmitterControls controls) {
256 controls.runSymbolFilter(
new ExtensionUnifier());
274 binding.setNativeName(binding.getInterfaceName());
275 super.mangleBinding(binding);
291 final List<MethodBinding> bindings = super.expandMethodBinding(binding);
298 final List<MethodBinding> newBindings =
new ArrayList<MethodBinding>();
302 if( GlueGen.debug() ) {
303 System.err.println(
"expandMethodBinding: j "+binding.toString());
304 System.err.println(
"expandMethodBinding: c "+binding.getCSymbol());
309 while( j < bindings.size() ) {
310 final MethodBinding cur = bindings.get(j);
317 if (cur.signatureUsesJavaPrimitiveArrays()) {
322 MethodBinding result = cur;
323 int replacedCount = 0;
324 for (
int i = 0; i < cur.getNumArguments(); i++) {
325 final JavaType jt = cur.getJavaArgumentType(i);
326 if( jt.isOpaqued() ) {
328 }
else if ( jt.isNIOBuffer() ) {
329 result = result.replaceJavaArgumentType(i, JavaType.createForClass(Long.TYPE));
332 if( GlueGen.debug() ) {
333 final Type ct = cur.getCArgumentType(i);
334 System.err.println(
" ["+i+
"]: #"+replacedCount+
", "+ct.getDebugString()+
", "+jt.getDebugString());
338 if ( 0 == replacedCount ) {
339 throw new RuntimeException(
"Error: didn't find any void* arguments for BufferObject function "
340 + binding.toString());
345 bufferObjectMethodBindings.put(result, result);
347 if( result != cur ) {
349 newBindings.add(result);
350 if( bufferObjectOnly ) {
359 bindings.addAll(newBindings);
367 getConfig().isUnimplemented(sym)
377 return bufferObjectMethodBindings.containsKey(binding);
381 public void emitDefine(
final ConstantDefinition def,
final String optionalComment)
throws Exception {
382 final String symbolRenamed = def.getName();
383 final StringBuilder newComment =
new StringBuilder();
386 final String enumName = def.getEnumName();
387 if (
null == enumName) {
388 newComment.append(
"Part of CORE ");
389 newComment.append(
"ENUM");
393 newComment.append(
"Part of CORE ");
394 newComment.append(
"DEF");
401 final StringBuilder sb =
new StringBuilder();
402 JavaEmitter.addStrings2Buffer(sb,
", ", symbolRenamed, def.getAliasedNames());
403 LOG.log(INFO, def.getASTLocusTag(),
"Dropping marker: {0}", sb.toString());
408 if (
null != optionalComment) {
409 if( newComment.length() > 0 ) {
410 newComment.append(
"<br>");
412 newComment.append(optionalComment);
415 super.emitDefine(def, newComment.toString());
418 private int addExtensionListOfSymbol2Doc(
final BuildStaticGLInfo glDocInfo,
final StringBuilder buf,
final String sep1,
final String name) {
420 final Set<String> extensionNames = glDocInfo.
getExtension(name);
421 if(
null!=extensionNames) {
422 for(
final Iterator<String> i=extensionNames.iterator(); i.hasNext(); ) {
423 final String extensionName = i.next();
424 if (
null != extensionName) {
425 buf.append(
"<code>");
426 buf.append(extensionName);
427 buf.append(
"</code>");
437 private int addExtensionListOfAliasedSymbols2Doc(
final BuildStaticGLInfo glDocInfo,
final StringBuilder buf,
final String sep1,
final String sep2,
final String name) {
440 num += addExtensionListOfSymbol2Doc(glDocInfo, buf, sep1, name);
441 boolean needsSep2 = num > 0;
442 final Set<String> aliases = ((GLConfiguration)cfg).getRenamedJavaDocSymbols(name);
443 if(
null != aliases) {
444 for(
final String alias : aliases) {
448 final int num2 = addExtensionListOfSymbol2Doc(glDocInfo, buf, sep1, alias);
449 needsSep2 = num2 > 0;
459 if (
null == glDocInfo) {
460 throw new RuntimeException(
"No GLDocInfo for: " + first);
463 buf =
new StringBuilder();
465 return addExtensionListOfAliasedSymbols2Doc(glDocInfo, buf, sep1, sep2, first);
473 final List<FunctionEmitter> superEmitters =
new ArrayList<FunctionEmitter>();
474 super.generateModifiedEmitters(baseJavaEmitter, superEmitters);
477 final boolean bufferObjectVariant = bufferObjectMethodBindings.containsKey(baseJavaEmitter.getBinding());
479 for (FunctionEmitter emitter : superEmitters) {
480 if (emitter instanceof ProcAddressJavaMethodBindingEmitter) {
483 emitters.add(emitter);
500 final JavaCodeUnit u = tableJavaUnit;
502 u.emitln(
" @Override");
503 u.emitln(
" protected boolean isFunctionAvailableImpl(String functionNameUsr) throws IllegalArgumentException {");
504 u.emitln(
" final String functionNameBase = "+
GLNameResolver.class.getName()+
".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
505 u.emitln(
" final String addressFieldNameBase = \"" + PROCADDRESS_VAR_PREFIX +
"\" + functionNameBase;");
506 u.emitln(
" final int funcNamePermNum = "+
GLNameResolver.class.getName()+
".getFuncNamePermutationNumber(functionNameBase);");
507 u.emitln(
" final java.lang.reflect.Field addressField = com.jogamp.common.util.SecurityUtil.doPrivileged(new java.security.PrivilegedAction<java.lang.reflect.Field>() {");
508 u.emitln(
" public final java.lang.reflect.Field run() {");
509 u.emitln(
" java.lang.reflect.Field addressField = null;");
510 u.emitln(
" for(int i = 0; i < funcNamePermNum; i++) {");
511 u.emitln(
" final String addressFieldName = "+
GLNameResolver.class.getName()+
".getFuncNamePermutation(addressFieldNameBase, i);");
513 u.emitln(
" addressField = "+tableClassName+
".class.getDeclaredField( addressFieldName );");
514 u.emitln(
" addressField.setAccessible(true); // we need to read the protected value!");
515 u.emitln(
" return addressField;");
516 u.emitln(
" } catch (NoSuchFieldException ex) { }");
518 u.emitln(
" return null;");
521 u.emitln(
" if(null==addressField) {");
522 u.emitln(
" // The user is calling a bogus function or one which is not");
523 u.emitln(
" // runtime linked");
524 u.emitln(
" throw new RuntimeException(");
525 u.emitln(
" \"WARNING: Address field query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
526 u.emitln(
" \"\\\"; it's either statically linked or address field is not a known \" +");
527 u.emitln(
" \"function\");");
530 u.emitln(
" return 0 != addressField.getLong(this);");
531 u.emitln(
" } catch (Exception e) {");
532 u.emitln(
" throw new RuntimeException(");
533 u.emitln(
" \"WARNING: Address query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
534 u.emitln(
" \"\\\"; it's either statically linked or is not a known \" +");
535 u.emitln(
" \"function\", e);");
539 u.emitln(
" @Override");
540 u.emitln(
" public long getAddressFor(String functionNameUsr) throws SecurityException, IllegalArgumentException {");
541 u.emitln(
" SecurityUtil.checkAllLinkPermission();");
542 u.emitln(
" final String functionNameBase = "+
GLNameResolver.class.getName()+
".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
543 u.emitln(
" final String addressFieldNameBase = \"" + PROCADDRESS_VAR_PREFIX +
"\" + functionNameBase;");
544 u.emitln(
" final int funcNamePermNum = "+
GLNameResolver.class.getName()+
".getFuncNamePermutationNumber(functionNameBase);");
545 u.emitln(
" final java.lang.reflect.Field addressField = com.jogamp.common.util.SecurityUtil.doPrivileged(new java.security.PrivilegedAction<java.lang.reflect.Field>() {");
546 u.emitln(
" public final java.lang.reflect.Field run() {");
547 u.emitln(
" java.lang.reflect.Field addressField = null;");
548 u.emitln(
" for(int i = 0; i < funcNamePermNum; i++) {");
549 u.emitln(
" final String addressFieldName = "+
GLNameResolver.class.getName()+
".getFuncNamePermutation(addressFieldNameBase, i);");
551 u.emitln(
" addressField = "+tableClassName+
".class.getDeclaredField( addressFieldName );");
552 u.emitln(
" addressField.setAccessible(true); // we need to read the protected value!");
553 u.emitln(
" return addressField;");
554 u.emitln(
" } catch (NoSuchFieldException ex) { }");
556 u.emitln(
" return null;");
559 u.emitln(
" if(null==addressField) {");
560 u.emitln(
" // The user is calling a bogus function or one which is not");
561 u.emitln(
" // runtime linked");
562 u.emitln(
" throw new RuntimeException(");
563 u.emitln(
" \"WARNING: Address field query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
564 u.emitln(
" \"\\\"; it's either statically linked or address field is not a known \" +");
565 u.emitln(
" \"function\");");
568 u.emitln(
" return addressField.getLong(this);");
569 u.emitln(
" } catch (Exception e) {");
570 u.emitln(
" throw new RuntimeException(");
571 u.emitln(
" \"WARNING: Address query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
572 u.emitln(
" \"\\\"; it's either statically linked or is not a known \" +");
573 u.emitln(
" \"function\", e);");
577 u.emitln(
"} // end of class " + tableClassName);
Builds the StaticGLInfo class from the OpenGL header files (i.e., gl.h and glext.h) whose paths were ...
Set< String > getExtensions()
Set< String > getDeclarations(final String extension)
Set< String > getExtension(final String identifier)
void parseGLDocHeaders(final GlueEmitterControls controls)
Parses any GL headers specified in the configuration file for the purpose of being able to ignore an ...
BuildStaticGLInfo getGLDocInfo()
Returns the information about the association between #defines, function symbols and the OpenGL exten...
boolean isIgnoredExtension(final String extensionName)
void parseGLSemHeaders(final GlueEmitterControls controls)
Parses any GL headers specified in the configuration file for the purpose of being able to ignore an ...
boolean isBufferObjectFunction(final AliasedSymbol symbol)
boolean isBufferObjectOnly(final String name)
void addJavaSymbolRename(final String origName, final String newName)
void addJavaDocSymbolRename(final String origName, final String newName)
Adds a javadoc rename directive for the given symbol.
Set< String > getExtensionsRenamedIntoCore()
Returns the OpenGL extensions that should have all of their constant definitions and functions rename...
BuildStaticGLInfo getGLSemInfo()
Returns the information about the association between #defines, function symbols and the OpenGL exten...
A subclass of ProcAddressEmitter with special OpenGL-specific configuration abilities.
void emitDefine(final ConstantDefinition def, final String optionalComment)
boolean needsBufferObjectVariant(final FunctionSymbol sym)
List< MethodBinding > expandMethodBinding(final MethodBinding binding)
In order to implement Buffer Object variants of certain functions we generate another MethodBinding w...
void renameExtensionsIntoCore()
GLConfiguration getGLConfig()
void beginEmission(final GlueEmitterControls controls)
JavaConfiguration createConfig()
void generateModifiedEmitters(final JavaMethodBindingEmitter baseJavaEmitter, final List< FunctionEmitter > emitters)
void renameExtensionsIntoCore(final GLConfiguration config, final BuildStaticGLInfo glInfo, final boolean isSemHeader)
void endProcAddressTable()
boolean isBufferObjectMethodBinding(final MethodBinding binding)
void mangleBinding(final MethodBinding binding)
int addExtensionsOfSymbols2Doc(StringBuilder buf, final String sep1, final String sep2, final String first)
boolean needsModifiedEmitters(final FunctionSymbol sym)
A specialization of the proc address emitter which knows how to change argument names to take into ac...
Runtime utility identify and resolve extension names, which may be subsumed to core.
static final boolean isGLFunction(final String str)
static final String normalize(final String[] extensions, String str, final boolean isGLFunc)
static final boolean isGLEnumeration(final String str)