aboutsummaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes/javax
diff options
context:
space:
mode:
Diffstat (limited to 'src/nativewindow/classes/javax')
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java226
1 files changed, 184 insertions, 42 deletions
diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
index 2610f2cfa..c3fdc6798 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
@@ -36,9 +36,15 @@ package javax.media.nativewindow;
import com.jogamp.common.util.ReflectionUtil;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.DefaultGraphicsConfigurationFactoryImpl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Provides the mechanism by which the graphics configuration for a
@@ -59,8 +65,43 @@ import java.util.Map;
public abstract class GraphicsConfigurationFactory {
protected static final boolean DEBUG;
- private static Map<Class<?>, GraphicsConfigurationFactory> registeredFactories;
- private static Class<?> abstractGraphicsDeviceClass;
+ private static class DeviceCapsType {
+ public final Class<?> deviceType;
+ public final Class<?> capsType;
+ private final int hash32;
+
+ public DeviceCapsType(Class<?> deviceType, Class<?> capsType) {
+ this.deviceType = deviceType;
+ this.capsType = capsType;
+
+ // 31 * x == (x << 5) - x
+ int hash32 = 31 + deviceType.hashCode();
+ hash32 = ((hash32 << 5) - hash32) + capsType.hashCode();
+ this.hash32 = hash32;
+ }
+
+ public final int hashCode() {
+ return hash32;
+ }
+
+ public final boolean equals(Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof DeviceCapsType) {
+ DeviceCapsType dct = (DeviceCapsType)obj;
+ return deviceType == dct.deviceType && capsType == dct.capsType;
+ }
+ return false;
+ }
+
+ @Override
+ public final String toString() {
+ return "DeviceCapsType["+deviceType.getName()+", "+capsType.getName()+"]";
+ }
+
+ }
+
+ private static final Map<DeviceCapsType, GraphicsConfigurationFactory> registeredFactories;
+ private static final DeviceCapsType defaultDeviceCapsType;
static boolean initialized = false;
static {
@@ -69,7 +110,8 @@ public abstract class GraphicsConfigurationFactory {
System.err.println(Thread.currentThread().getName()+" - Info: GraphicsConfigurationFactory.<init>");
// Thread.dumpStack();
}
- abstractGraphicsDeviceClass = javax.media.nativewindow.AbstractGraphicsDevice.class;
+ registeredFactories = Collections.synchronizedMap(new HashMap<DeviceCapsType, GraphicsConfigurationFactory>());
+ defaultDeviceCapsType = new DeviceCapsType(AbstractGraphicsDevice.class, CapabilitiesImmutable.class);
}
public static synchronized void initSingleton() {
@@ -79,14 +121,13 @@ public abstract class GraphicsConfigurationFactory {
if(DEBUG) {
System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.initSingleton()");
}
- registeredFactories = Collections.synchronizedMap(new HashMap<Class<?>, GraphicsConfigurationFactory>());
// Register the default no-op factory for arbitrary
// AbstractGraphicsDevice implementations, including
// AWTGraphicsDevice instances -- the OpenGL binding will take
// care of handling AWTGraphicsDevices on X11 platforms (as
// well as X11GraphicsDevices in non-AWT situations)
- registerFactory(abstractGraphicsDeviceClass, new DefaultGraphicsConfigurationFactoryImpl());
+ registerFactory(defaultDeviceCapsType.deviceType, defaultDeviceCapsType.capsType, new DefaultGraphicsConfigurationFactoryImpl());
if (NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) {
try {
@@ -112,7 +153,6 @@ public abstract class GraphicsConfigurationFactory {
System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.shutdown()");
}
registeredFactories.clear();
- registeredFactories = null;
}
}
@@ -133,74 +173,175 @@ public abstract class GraphicsConfigurationFactory {
protected GraphicsConfigurationFactory() {
}
- /** Returns the factory for use with the given type of
- AbstractGraphicsDevice. */
- public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device) {
+ /**
+ * Returns the graphics configuration factory for use with the
+ * given device and capability.
+ *
+ * @see #getFactory(Class, Class)
+ */
+ public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device, CapabilitiesImmutable caps) {
if (device == null) {
- return getFactory(AbstractGraphicsDevice.class);
+ throw new IllegalArgumentException("null device");
+ }
+ if (caps == null) {
+ throw new IllegalArgumentException("null caps");
}
- return getFactory(device.getClass());
+ return getFactory(device.getClass(), caps.getClass());
}
/**
* Returns the graphics configuration factory for use with the
- * given class, which must implement the {@link
- * AbstractGraphicsDevice} interface.
+ * given device and capability class.
+ * <p>
+ * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
+ * </p>
+ *
+ * <p>
+ * Pseudo code for finding a suitable factory is:
+ * <pre>
+ For-All devT := getTopDownDeviceTypes(deviceType)
+ For-All capsT := getTopDownCapabilitiesTypes(capabilitiesType)
+ f = factory.get(devT, capsT);
+ if(f) { return f; }
+ end
+ end
+ * </pre>
+ * </p>
*
- * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice
+ * @param deviceType the minimum capabilities class type accepted, must implement or extend {@link AbstractGraphicsDevice}
+ * @param capabilitiesType the minimum capabilities class type accepted, must implement or extend {@link CapabilitiesImmutable}
+ *
+ * @throws IllegalArgumentException if the deviceType does not implement {@link AbstractGraphicsDevice} or
+ * capabilitiesType does not implement {@link CapabilitiesImmutable}
*/
- public static GraphicsConfigurationFactory getFactory(Class<?> abstractGraphicsDeviceImplementor)
+ public static GraphicsConfigurationFactory getFactory(Class<?> deviceType, Class<?> capabilitiesType)
throws IllegalArgumentException, NativeWindowException
{
- if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) {
+ if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(deviceType))) {
throw new IllegalArgumentException("Given class must implement AbstractGraphicsDevice");
}
-
- GraphicsConfigurationFactory factory = null;
- Class<?> clazz = abstractGraphicsDeviceImplementor;
- while (clazz != null) {
- factory = registeredFactories.get(clazz);
- if (factory != null) {
- if(DEBUG) {
- System.err.println("GraphicsConfigurationFactory.getFactory() "+abstractGraphicsDeviceImplementor+" -> "+factory);
+ if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) {
+ throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable");
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ System.err.println("GraphicsConfigurationFactory.getFactory: "+deviceType.getName()+", "+capabilitiesType.getName());
+ dumpFactories();
+ }
+
+ final List<Class<?>> deviceTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.deviceType, deviceType, false);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() deviceTypes: " + deviceTypes);
+ }
+ final List<Class<?>> capabilitiesTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.capsType, capabilitiesType, true);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() capabilitiesTypes: " + capabilitiesTypes);
+ }
+ for(int j=0; j<deviceTypes.size(); j++) {
+ final Class<?> interfaceDevice = deviceTypes.get(j);
+ for(int i=0; i<capabilitiesTypes.size(); i++) {
+ Class<?> interfaceCaps = capabilitiesTypes.get(i);
+ final DeviceCapsType dct = new DeviceCapsType(interfaceDevice, interfaceCaps);
+ final GraphicsConfigurationFactory factory = registeredFactories.get(dct);
+ if (factory != null) {
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() found "+dct+" -> "+factory);
+ }
+ return factory;
}
- return factory;
}
- clazz = clazz.getSuperclass();
}
// Return the default
- factory = registeredFactories.get(abstractGraphicsDeviceClass);
+ final GraphicsConfigurationFactory factory = registeredFactories.get(defaultDeviceCapsType);
if(DEBUG) {
- System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+abstractGraphicsDeviceClass+" -> "+factory);
+ System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+defaultDeviceCapsType+" -> "+factory);
}
return factory;
}
+ private static ArrayList<Class<?>> getAllAssignableClassesFrom(Class<?> superClassOrInterface, Class<?> fromClass, boolean interfacesOnly) {
+ // Using a todo list avoiding a recursive loop!
+ final ArrayList<Class<?>> inspectClasses = new ArrayList<Class<?>>();
+ final ArrayList<Class<?>> resolvedInterfaces = new ArrayList<Class<?>>();
+ inspectClasses.add(fromClass);
+ for(int j=0; j<inspectClasses.size(); j++) {
+ final Class<?> clazz = inspectClasses.get(j);
+ getAllAssignableClassesFrom(superClassOrInterface, clazz, interfacesOnly, resolvedInterfaces, inspectClasses);
+ }
+ return resolvedInterfaces;
+ }
+ private static void getAllAssignableClassesFrom(Class<?> superClassOrInterface, Class<?> fromClass, boolean interfacesOnly, List<Class<?>> resolvedInterfaces, List<Class<?>> inspectClasses) {
+ final ArrayList<Class<?>> types = new ArrayList<Class<?>>();
+ if( superClassOrInterface.isAssignableFrom(fromClass) && !resolvedInterfaces.contains(fromClass)) {
+ if( !interfacesOnly || fromClass.isInterface() ) {
+ types.add(fromClass);
+ }
+ }
+ types.addAll(Arrays.asList(fromClass.getInterfaces()));
+
+ for(int i=0; i<types.size(); i++) {
+ final Class<?> iface = types.get(i);
+ if( superClassOrInterface.isAssignableFrom(iface) && !resolvedInterfaces.contains(iface) ) {
+ resolvedInterfaces.add(iface);
+ if( !superClassOrInterface.equals(iface) && !inspectClasses.contains(iface) ) {
+ inspectClasses.add(iface); // safe add to todo list, avoiding a recursive nature
+ }
+ }
+ }
+ final Class<?> parentClass = fromClass.getSuperclass();
+ if( null != parentClass && superClassOrInterface.isAssignableFrom(parentClass) && !inspectClasses.contains(parentClass) ) {
+ inspectClasses.add(parentClass); // safe add to todo list, avoiding a recursive nature
+ }
+ }
+ private static void dumpFactories() {
+ Set<DeviceCapsType> dcts = registeredFactories.keySet();
+ int i=0;
+ for(Iterator<DeviceCapsType> iter = dcts.iterator(); iter.hasNext(); ) {
+ DeviceCapsType dct = iter.next();
+ System.err.println("Factory #"+i+": "+dct+" -> "+registeredFactories.get(dct));
+ i++;
+ }
+ }
- /** Registers a GraphicsConfigurationFactory handling graphics
- * device objects of the given class. This does not need to be
- * called by end users, only implementors of new
+ /**
+ * Registers a GraphicsConfigurationFactory handling
+ * the given graphics device and capability class.
+ * <p>
+ * This does not need to be called by end users, only implementors of new
* GraphicsConfigurationFactory subclasses.
- *
+ * </p>
+ *
+ * <p>
+ * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
+ * </p>
+ *
+ * <p>See {@link #getFactory(Class, Class)} for a description of the find algorithm.</p>
+ *
+ * @param deviceType the minimum capabilities class type accepted, must implement or extend interface {@link AbstractGraphicsDevice}
+ * @param capabilitiesType the minimum capabilities class type accepted, must extend interface {@link CapabilitiesImmutable}
* @return the previous registered factory, or null if none
* @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice
*/
- protected static GraphicsConfigurationFactory registerFactory(Class<?> abstractGraphicsDeviceImplementor, GraphicsConfigurationFactory factory)
+ protected static GraphicsConfigurationFactory registerFactory(Class<?> abstractGraphicsDeviceImplementor, Class<?> capabilitiesType, GraphicsConfigurationFactory factory)
throws IllegalArgumentException
{
- if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) {
- throw new IllegalArgumentException("Given class must implement AbstractGraphicsDevice");
+ if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(abstractGraphicsDeviceImplementor))) {
+ throw new IllegalArgumentException("Given device class must implement AbstractGraphicsDevice");
}
+ if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) {
+ throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable");
+ }
+ final DeviceCapsType dct = new DeviceCapsType(abstractGraphicsDeviceImplementor, capabilitiesType);
final GraphicsConfigurationFactory prevFactory;
if(null == factory) {
- prevFactory = registeredFactories.remove(abstractGraphicsDeviceImplementor);
+ prevFactory = registeredFactories.remove(dct);
if(DEBUG) {
- System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+abstractGraphicsDeviceImplementor+
+ System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+dct+
", deleting: "+prevFactory);
}
} else {
- prevFactory = registeredFactories.put(abstractGraphicsDeviceImplementor, factory);
+ prevFactory = registeredFactories.put(dct, factory);
if(DEBUG) {
- System.err.println("GraphicsConfigurationFactory.registerFactory() put "+abstractGraphicsDeviceImplementor+" -> "+factory+
+ System.err.println("GraphicsConfigurationFactory.registerFactory() put "+dct+" -> "+factory+
", overridding: "+prevFactory);
}
}
@@ -244,6 +385,7 @@ public abstract class GraphicsConfigurationFactory {
* @param capsRequested the original requested capabilities
* @param chooser the choosing implementation
* @param screen the referring Screen
+ * @param nativeVisualID if not {@link VisualIDHolder#VID_UNDEFINED} it reflects a pre-chosen visualID of the native platform's windowing system.
* @return the complete GraphicsConfiguration
*
* @throws IllegalArgumentException if the data type of the passed
@@ -258,7 +400,7 @@ public abstract class GraphicsConfigurationFactory {
public final AbstractGraphicsConfiguration
chooseGraphicsConfiguration(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
CapabilitiesChooser chooser,
- AbstractGraphicsScreen screen)
+ AbstractGraphicsScreen screen, int nativeVisualID)
throws IllegalArgumentException, NativeWindowException {
if(null==capsChosen) {
throw new NativeWindowException("Chosen Capabilities are null");
@@ -275,7 +417,7 @@ public abstract class GraphicsConfigurationFactory {
}
device.lock();
try {
- return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen);
+ return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen, nativeVisualID);
} finally {
device.unlock();
}
@@ -283,7 +425,7 @@ public abstract class GraphicsConfigurationFactory {
protected abstract AbstractGraphicsConfiguration
chooseGraphicsConfigurationImpl(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen screen)
+ CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID)
throws IllegalArgumentException, NativeWindowException;
}