/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* 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.opengl;
import java.lang.reflect.*;
import java.util.StringTokenizer;
import com.jogamp.common.util.ReflectionUtil;
import jogamp.opengl.*;
/**
* Factory for pipelining GL instances
*/
public class GLPipelineFactory {
public static final boolean DEBUG = Debug.debug("GLPipelineFactory");
/**
* Creates a pipelined GL instance using the given downstream downstream
* and optional arguments additionalArgs
for the constructor.
*
*
* Sample code which installs a Debug and Trace pipeline
* automatic w/ user defined interface, here: GL2ES2:
*
* gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", GL2ES2.class, gl, null) );
* gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", GL2ES2.class, gl, new Object[] { System.err } ) );
*
* or automatic w/ automatic defined class:
*
* gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) );
* gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) );
*
*
*
*
* The upstream GL instance is determined as follows:
*
* - Use
pipelineClazzBaseName
as the class name's full basename, incl. package name
* - For the
downstream
class and it's superclasses, do:
*
* - For all
downstream
class and superclass interfaces, do:
*
* - If
reqInterface
is not null and the interface is unequal, continue loop.
* - If
downstream
is not instance of interface, continue loop.
* - If upstream class is available use it, end loop.
*
*
*
*
*
* @param pipelineClazzBaseName the basename of the pipline class name
* @param reqInterface optional requested interface to be used, may be null, in which case the first matching one is used
* @param downstream is always the 1st argument for the upstream constructor
* @param additionalArgs additional arguments for the upstream constructor
*/
public static final GL create(final String pipelineClazzBaseName, final Class> reqInterface, final GL downstream, final Object[] additionalArgs) {
Class> downstreamClazz = downstream.getClass();
Class> upstreamClazz = null;
Class> interfaceClazz = null;
if(DEBUG) {
System.out.println("GLPipelineFactory: Start "+downstreamClazz.getName()+", req. Interface: "+reqInterface+" -> "+pipelineClazzBaseName);
}
// For all classes: child -> parent
do {
// For all interfaces: right -> left == child -> parent
// It is important that this matches with the gluegen cfg file's 'Implements' clause !
final Class>[] clazzes = downstreamClazz.getInterfaces();
for(int i=clazzes.length-1; null==upstreamClazz && i>=0; i--) {
if(DEBUG) {
System.out.println("GLPipelineFactory: Try "+downstreamClazz.getName()+" Interface["+i+"]: "+clazzes[i].getName());
}
if( reqInterface != null && !reqInterface.getName().equals(clazzes[i].getName()) ) {
if(DEBUG) {
System.out.println("GLPipelineFactory: requested Interface "+reqInterface+" is _not_ "+ clazzes[i].getName());
}
continue; // not the requested one ..
}
if( ! clazzes[i].isInstance(downstream) ) {
if(DEBUG) {
System.out.println("GLPipelineFactory: "+downstream.getClass().getName() + " is _not_ instance of "+ clazzes[i].getName());
}
continue; // not a compatible one
} else {
if(DEBUG) {
System.out.println("GLPipelineFactory: "+downstream.getClass().getName() + " _is_ instance of "+ clazzes[i].getName());
}
}
upstreamClazz = getUpstreamClazz(clazzes[i], pipelineClazzBaseName);
if( null != upstreamClazz ) {
interfaceClazz = clazzes[i];
}
}
if(null==upstreamClazz) {
downstreamClazz = downstreamClazz.getSuperclass();
}
} while (null!=downstreamClazz && null==upstreamClazz);
if(null==upstreamClazz) {
throw new GLException("No pipeline ("+pipelineClazzBaseName+"*) available for :"+downstream.getClass().getName());
}
if(DEBUG) {
System.out.println("GLPipelineFactory: Got : "+ upstreamClazz.getName()+", base interface: "+interfaceClazz.getName());
}
final Class>[] cstrArgTypes = new Class>[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
{
int i = 0;
cstrArgTypes[i++] = interfaceClazz;
for(int j=0; null!=additionalArgs && j cstr = ReflectionUtil.getConstructor(upstreamClazz, cstrArgTypes);
Object instance = null;
try {
final Object[] cstrArgs = new Object[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
{
int i = 0;
cstrArgs[i++] = downstream;
for(int j=0; null!=additionalArgs && j arg0, final Object[] args) {
final StringBuilder sb = new StringBuilder();
sb.append(arg0.getName());
if(args!=null) {
for(int j=0; j getUpstreamClazz(final Class> downstreamClazz, final String pipelineClazzBaseName) {
final String downstreamClazzName = downstreamClazz.getName();
final StringTokenizer st = new StringTokenizer(downstreamClazzName, ".");
String downstreamClazzBaseName = downstreamClazzName;
while(st.hasMoreTokens()) {
downstreamClazzBaseName = st.nextToken();
}
final String upstreamClazzName = pipelineClazzBaseName+downstreamClazzBaseName;
Class> upstreamClazz = null;
try {
upstreamClazz = Class.forName(upstreamClazzName, true, GLPipelineFactory.class.getClassLoader());
} catch (final Throwable e) { e.printStackTrace(); }
return upstreamClazz;
}
}