diff options
Diffstat (limited to 'src/java/com/jogamp')
-rw-r--r-- | src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java | 177 |
1 files changed, 147 insertions, 30 deletions
diff --git a/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java b/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java index f0be20f..6a73c0a 100644 --- a/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java +++ b/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java @@ -44,12 +44,35 @@ import java.io.PrintStream; import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; /** * Superclass for all generated ProcAddressTables. + * + * A ProcAddressTable is a cache of pointers to the dynamically-linkable C + * functions this autogenerated Java binding has exposed. Some + * libraries such as OpenGL, OpenAL and others define function pointer + * signatures rather than statically linkable entry points for the + * purposes of being able to query at run-time whether a particular + * extension is available. This table acts as a cache of these + * function pointers. Each function pointer is typically looked up at + * run-time by a platform-dependent mechanism such as dlsym(), + * wgl/glXGetProcAddress(), or alGetProcAddress(). If the field containing the function + * pointer is 0, the function is considered to be unavailable and can + * not be called. + * * @author Kenneth Russel * @author Michael Bien * @author Sven Gothel + * + * @see FunctionAddressResolver + * @see DynamicLookupHelper */ public abstract class ProcAddressTable { @@ -82,50 +105,31 @@ public abstract class ProcAddressTable { this.resolver = resolver; } + /** - * Returns the address for the given function name. - * @throws RuntimeException if the Table has not been initialized yet. + * Resets the complete table. */ - public abstract long getAddressFor(String functionName); - - public void reset(DynamicLookupHelper lookup) throws RuntimeException { + if(null==lookup) { throw new RuntimeException("Passed null DynamicLookupHelper"); } - Class tableClass = getClass(); - Field[] fields = tableClass.getFields(); PrintStream dout = getDebugOutStream(); if (DEBUG) { - dout.println("ProcAddressTable.reset(" + getClass().getName() + ")"); + dout.println(getClass().getName()+".reset()"); } - for (int i = 0; i < fields.length; ++i) { - String addressFieldName = fields[i].getName(); - if (!addressFieldName.startsWith(PROCADDRESS_VAR_PREFIX)) { - // not a proc address variable - continue; - } - int startOfMethodName = PROCADDRESS_VAR_PREFIX.length(); - String funcName = addressFieldName.substring(startOfMethodName); - try { - Field addressField = fields[i]; - assert (addressField.getType() == Long.TYPE); - - long newProcAddress = resolver.resolve(funcName, lookup); - // set the current value of the proc address variable in the table object - addressField.setLong(this, newProcAddress); - if (DEBUG) { - dout.println(" " + addressField.getName() + " -> 0x" + Long.toHexString(newProcAddress)); - } - } catch (Exception e) { - throw new RuntimeException("Can not get proc address for method \"" - + funcName + "\": Couldn't set value of field \"" + addressFieldName - + "\" in class " + tableClass.getName(), e); + Field[] fields = getClass().getFields(); + for (int i = 0; i < fields.length; ++i) { + String fieldName = fields[i].getName(); + if (isAddressField(fieldName)) { + String funcName = fieldToFunctionName(fieldName); + setEntry(fields[i], funcName, lookup); } } + if (DEBUG) { dout.flush(); if (DEBUG_PREFIX != null) { @@ -134,6 +138,46 @@ public abstract class ProcAddressTable { } } + /** + * Initializes the mapping for a single function. + * @throws IllegalArgumentException if this function is not in this table. + */ + public void initEntry(String name, DynamicLookupHelper lookup) { + Field field = fieldForFunction(name); + setEntry(field, name, lookup); + } + + protected void setEntry(Field addressField, String funcName, DynamicLookupHelper lookup) { + try { + assert (addressField.getType() == Long.TYPE); + long newProcAddress = resolver.resolve(funcName, lookup); + // set the current value of the proc address variable in the table object + addressField.setLong(this, newProcAddress); + if (DEBUG) { + getDebugOutStream().println(" " + addressField.getName() + " -> 0x" + Long.toHexString(newProcAddress)); + } + } catch (Exception e) { + throw new RuntimeException("Can not get proc address for method \"" + + funcName + "\": Couldn't set value of field \"" + addressField, e); + } + } + + protected String fieldToFunctionName(String addressFieldName) { + return addressFieldName.substring(PROCADDRESS_VAR_PREFIX.length()); + } + + protected Field fieldForFunction(String name) { + try { + return getClass().getField(PROCADDRESS_VAR_PREFIX + name); + } catch (NoSuchFieldException ex) { + throw new IllegalArgumentException(getClass().getName() +" has no entry for the function '"+name+"'.", ex); + } + } + + protected boolean isAddressField(String fieldName) { + return fieldName.startsWith(PROCADDRESS_VAR_PREFIX); + } + protected static PrintStream getDebugOutStream() { PrintStream out = null; if (DEBUG) { @@ -152,6 +196,79 @@ public abstract class ProcAddressTable { return out; } + /** + * Returns this table as map with the function name as key and the address as value. + */ + public Map/*<String, Long>*/ toMap() { + + SortedMap map = new TreeMap(); + + Field[] fields = getClass().getFields(); + try { + for (int i = 0; i < fields.length; ++i) { + String addressFieldName = fields[i].getName(); + if (isAddressField(addressFieldName)) { + map.put(fieldToFunctionName(addressFieldName), fields[i].get(this)); + } + } + } catch (IllegalArgumentException ex) { + throw new RuntimeException(ex); + } catch (IllegalAccessException ex) { + throw new RuntimeException(ex); + } + + return map; + } + + /** + * Returns true only if non null function pointer to this function exists. + */ + public boolean isFunctionAvailable(String functionName) { + try{ + return getAddressFor(functionName) != 0; + }catch (IllegalArgumentException ex) { + return false; + } + } + + /** + * This is a convenience method to get (by name) the native function + * pointer for a given function. It lets you avoid having to + * manually compute the "{@link #PROCADDRESS_VAR_PREFIX} + <functionName>" + * member variable name and look it up via reflection. + * + * @throws IllegalArgumentException if this function is not in this table. + */ + public long getAddressFor(String functionName) { + Field addressField = fieldForFunction(functionName); + try { + return addressField.getLong(this); + } catch (IllegalAccessException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Returns all functions pointing to null. + */ + public Set/*<String>*/ getNullPointerFunctions() { + Map table = toMap(); + Set nullPointers = new LinkedHashSet(); + for (Iterator it = table.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = (Entry) it.next(); + long address = ((Long)entry.getValue()).longValue(); + if(address == 0) { + nullPointers.add(entry.getKey()); + } + } + return nullPointers; + } + +// @Override + public String toString() { + return getClass().getName()+""+toMap(); + } + private static class One2OneResolver implements FunctionAddressResolver { public long resolve(String name, DynamicLookupHelper lookup) { |