JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
GLPipelineFactory.java
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * - Redistribution of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistribution in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * Neither the name of Sun Microsystems, Inc. or the names of
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * This software is provided "AS IS," without a warranty of any kind. ALL
20 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
23 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
24 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
25 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
26 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
27 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
28 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
29 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
30 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 *
32 * You acknowledge that this software is not designed or intended for use
33 * in the design, construction, operation or maintenance of any nuclear
34 * facility.
35 */
36
37package com.jogamp.opengl;
38
39import java.lang.reflect.*;
40import java.util.StringTokenizer;
41
42import com.jogamp.common.util.ReflectionUtil;
43
44import jogamp.opengl.*;
45
46/**
47 * Factory for pipelining GL instances
48 */
49public class GLPipelineFactory {
50 public static final boolean DEBUG = Debug.debug("GLPipelineFactory");
51
52 /**
53 * Creates a pipelined GL instance using the given downstream <code>downstream</code>
54 * and optional arguments <code>additionalArgs</code> for the constructor.
55 *
56 * <p>
57 * Sample code which installs a Debug and Trace pipeline
58 * automatic w/ user defined interface, here: GL2ES2:
59 * <pre>
60 * gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", GL2ES2.class, gl, null) );
61 * gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", GL2ES2.class, gl, new Object[] { System.err } ) );
62 * </pre>
63 * or automatic w/ automatic defined class:
64 * <pre>
65 * gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) );
66 * gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) );
67 * </pre>
68 * </p>
69 *
70 * <p>
71 * The upstream GL instance is determined as follows:
72 * <ul>
73 * <li> Use <code>pipelineClazzBaseName</code> as the class name's full basename, incl. package name</li>
74 * <li> For the <code>downstream</code> class and it's superclasses, do:</li>
75 * <ul>
76 * <li> For all <code>downstream</code> class and superclass interfaces, do:</li>
77 * <ul>
78 * <li> If <code>reqInterface</code> is not null and the interface is unequal, continue loop.</li>
79 * <li> If <code>downstream</code> is not instance of interface, continue loop.</li>
80 * <li> If upstream class is available use it, end loop.</li>
81 * </ul>
82 * </ul>
83 * </ul>
84 * </p>
85 *
86 * @param pipelineClazzBaseName the basename of the pipline class name
87 * @param reqInterface optional requested interface to be used, may be null, in which case the first matching one is used
88 * @param downstream is always the 1st argument for the upstream constructor
89 * @param additionalArgs additional arguments for the upstream constructor
90 */
91 public static final GL create(final String pipelineClazzBaseName, final Class<?> reqInterface, final GL downstream, final Object[] additionalArgs) {
92 Class<?> downstreamClazz = downstream.getClass();
93 Class<?> upstreamClazz = null;
94 Class<?> interfaceClazz = null;
95
96 if(DEBUG) {
97 System.out.println("GLPipelineFactory: Start "+downstreamClazz.getName()+", req. Interface: "+reqInterface+" -> "+pipelineClazzBaseName);
98 }
99
100 // For all classes: child -> parent
101 do {
102 // For all interfaces: right -> left == child -> parent
103 // It is important that this matches with the gluegen cfg file's 'Implements' clause !
104 final Class<?>[] clazzes = downstreamClazz.getInterfaces();
105 for(int i=clazzes.length-1; null==upstreamClazz && i>=0; i--) {
106 if(DEBUG) {
107 System.out.println("GLPipelineFactory: Try "+downstreamClazz.getName()+" Interface["+i+"]: "+clazzes[i].getName());
108 }
109 if( reqInterface != null && !reqInterface.getName().equals(clazzes[i].getName()) ) {
110 if(DEBUG) {
111 System.out.println("GLPipelineFactory: requested Interface "+reqInterface+" is _not_ "+ clazzes[i].getName());
112 }
113 continue; // not the requested one ..
114 }
115 if( ! clazzes[i].isInstance(downstream) ) {
116 if(DEBUG) {
117 System.out.println("GLPipelineFactory: "+downstream.getClass().getName() + " is _not_ instance of "+ clazzes[i].getName());
118 }
119 continue; // not a compatible one
120 } else {
121 if(DEBUG) {
122 System.out.println("GLPipelineFactory: "+downstream.getClass().getName() + " _is_ instance of "+ clazzes[i].getName());
123 }
124 }
125 upstreamClazz = getUpstreamClazz(clazzes[i], pipelineClazzBaseName);
126 if( null != upstreamClazz ) {
127 interfaceClazz = clazzes[i];
128 }
129 }
130
131 if(null==upstreamClazz) {
132 downstreamClazz = downstreamClazz.getSuperclass();
133 }
134 } while (null!=downstreamClazz && null==upstreamClazz);
135
136
137 if(null==upstreamClazz) {
138 throw new GLException("No pipeline ("+pipelineClazzBaseName+"*) available for :"+downstream.getClass().getName());
139 }
140
141 if(DEBUG) {
142 System.out.println("GLPipelineFactory: Got : "+ upstreamClazz.getName()+", base interface: "+interfaceClazz.getName());
143 }
144
145 final Class<?>[] cstrArgTypes = new Class<?>[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
146 {
147 int i = 0;
148 cstrArgTypes[i++] = interfaceClazz;
149 for(int j=0; null!=additionalArgs && j<additionalArgs.length; j++) {
150 cstrArgTypes[i++] = additionalArgs[j].getClass();
151 }
152 }
153 // throws exception if cstr not found!
154 final Constructor<?> cstr = ReflectionUtil.getConstructor(upstreamClazz, cstrArgTypes);
155 Object instance = null;
156 try {
157 final Object[] cstrArgs = new Object[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
158 {
159 int i = 0;
160 cstrArgs[i++] = downstream;
161 for(int j=0; null!=additionalArgs && j<additionalArgs.length; j++) {
162 cstrArgs[i++] = additionalArgs[j];
163 }
164 }
165 instance = cstr.newInstance( cstrArgs ) ;
166 } catch (final Throwable t) { t.printStackTrace(); }
167 if(null==instance) {
168 throw new GLException("Error: Couldn't create instance of pipeline: "+upstreamClazz.getName()+
169 " ( "+getArgsClassNameList(downstreamClazz, additionalArgs) +" )");
170 }
171 if( ! (instance instanceof GL) ) {
172 throw new GLException("Error: "+upstreamClazz.getName()+" not an instance of GL");
173 }
174 return (GL) instance;
175 }
176
177 private static final String getArgsClassNameList(final Class<?> arg0, final Object[] args) {
178 final StringBuilder sb = new StringBuilder();
179 sb.append(arg0.getName());
180 if(args!=null) {
181 for(int j=0; j<args.length; j++) {
182 sb.append(", ");
183 sb.append(args[j].getClass().getName());
184 }
185 }
186 return sb.toString();
187 }
188
189 private static final Class<?> getUpstreamClazz(final Class<?> downstreamClazz, final String pipelineClazzBaseName) {
190 final String downstreamClazzName = downstreamClazz.getName();
191
192 final StringTokenizer st = new StringTokenizer(downstreamClazzName, ".");
193 String downstreamClazzBaseName = downstreamClazzName;
194 while(st.hasMoreTokens()) {
195 downstreamClazzBaseName = st.nextToken();
196 }
197 final String upstreamClazzName = pipelineClazzBaseName+downstreamClazzBaseName;
198
199 Class<?> upstreamClazz = null;
200 try {
201 upstreamClazz = Class.forName(upstreamClazzName, true, GLPipelineFactory.class.getClassLoader());
202 } catch (final Throwable e) { e.printStackTrace(); }
203
204 return upstreamClazz;
205 }
206}
207
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
Factory for pipelining GL instances.
static final GL create(final String pipelineClazzBaseName, final Class<?> reqInterface, final GL downstream, final Object[] additionalArgs)
Creates a pipelined GL instance using the given downstream downstream and optional arguments addition...