diff options
author | JOGAMP DEV TEAM <[email protected]> | 2010-04-22 21:12:36 -0400 |
---|---|---|
committer | JOGAMP DEV TEAM <[email protected]> | 2010-04-22 21:12:36 -0400 |
commit | 1d889ddc4728d1534e310b44fad74a2932d22d39 (patch) | |
tree | 4ad0c3eeb3ef728522ac9459eb12c667301a0c32 /src/jogl/classes/com/jogamp/opengl/impl | |
parent | 8790075f074013aa3c71b96993838cf1117275f1 (diff) | |
parent | a588326d206ff32e5ff5db97560851cb9b826022 (diff) |
Merge branch 'master' of github.com:sgothel/jogl
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/impl')
184 files changed, 44694 insertions, 0 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/DRIHack.java b/src/jogl/classes/com/jogamp/opengl/impl/DRIHack.java new file mode 100755 index 000000000..7e81d194b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/DRIHack.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2006 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import com.jogamp.common.os.NativeLibrary; +import com.jogamp.common.os.Platform; +import java.io.*; +import java.security.*; + +/** + * Helper class for working around problems with open-source DRI + * drivers. In the current DRI implementation it is required that the + * symbols in libGL.so.1.2 be globally visible to be accessible from + * other libraries that are dynamically loaded by the implementation. + * Applications may typically satisfy this need either by linking + * against libGL.so on the command line (-lGL) or by dlopen'ing + * libGL.so.1.2 with the RTLD_GLOBAL flag. The JOGL implementation + * links against libGL on all platforms rather than forcing all OpenGL + * entry points to be called through a function pointer. This allows + * the JOGL library to link directly to core 1.1 OpenGL entry points + * like glVertex3f, while calling through function pointers for entry + * points from later OpenGL versions as well as from + * extensions. However, because libjogl.so (which links against + * libGL.so) is loaded by the JVM, and because the JVM implicitly uses + * RTLD_LOCAL in the implementation of System.loadLibrary(), this + * means via transitivity that the symbols for libGL.so have only + * RTLD_LOCAL visibility to the rest of the application, so the DRI + * drivers can not find the symbols required. <P> + * + * There are at least two possible solutions. One would be to change + * the JOGL implementation to call through function pointers uniformly + * so that it does not need to link against libGL.so. This is + * possible, but requires changes to GlueGen and also is not really + * necessary in any other situation than with the DRI drivers. Another + * solution is to force the first load of libGL.so.1.2 to be done + * dynamically with RTLD_GLOBAL before libjogl.so is loaded and causes + * libGL.so.1.2 to be loaded again. The NativeLibrary class in the + * GlueGen runtime has this property, and we use it to implement this + * workaround. + */ + +public class DRIHack { + + private static final boolean DEBUG = Debug.debug("DRIHack"); + private static boolean driHackNeeded; + private static NativeLibrary oglLib; + + static { + // Allow manual overriding for now as a workaround for + // problems seen in some situations -- needs more investigation + if (Debug.getProperty("jogl.drihack.disable", true) != null) { + driHackNeeded = false; + } else { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String os = Platform.getOS().toLowerCase(); + // Do DRI hack on all Linux distributions for best robustness + driHackNeeded = os.startsWith("linux") + || new File("/usr/lib/dri").exists() + || new File("/usr/X11R6/lib/modules/dri").exists(); + return null; + } + }); + } + } + + public static void begin() { + + if (driHackNeeded) { + if (DEBUG) { + System.err.println("Beginning DRI hack"); + } + + // Try a few different variants for best robustness + // In theory probably only the first is necessary + oglLib = NativeLibrary.open("libGL.so.1", null); + if (DEBUG && oglLib != null) { + System.err.println(" Found libGL.so.1"); + } + if (oglLib == null) { + oglLib = NativeLibrary.open("/usr/lib/libGL.so.1", null); + if (DEBUG && oglLib != null) { + System.err.println(" Found /usr/lib/libGL.so.1"); + } + } + } + + } + + public static void end() { + if (oglLib != null) { + if (DEBUG) { + System.err.println("Ending DRI hack"); + } + + oglLib.close(); + oglLib = null; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/Debug.java b/src/jogl/classes/com/jogamp/opengl/impl/Debug.java new file mode 100644 index 000000000..82a5f2ff2 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/Debug.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2003-2005 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.security.*; + +/** Helper routines for logging and debugging. */ + +public class Debug { + // Some common properties + private static boolean verbose; + private static boolean debugAll; + private static AccessControlContext localACC; + + static { + localACC=AccessController.getContext(); + verbose = isPropertyDefined("jogl.verbose", true); + debugAll = isPropertyDefined("jogl.debug", true); + if (verbose) { + Package p = Package.getPackage("javax.media.opengl"); + System.err.println("JOGL specification version " + p.getSpecificationVersion()); + System.err.println("JOGL implementation version " + p.getImplementationVersion()); + System.err.println("JOGL implementation vendor " + p.getImplementationVendor()); + } + } + + static int getIntProperty(final String property, final boolean jnlpAlias) { + return getIntProperty(property, jnlpAlias, localACC); + } + + public static int getIntProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc) { + int i=0; + try { + Integer iv = Integer.valueOf(Debug.getProperty(property, jnlpAlias, acc)); + i = iv.intValue(); + } catch (NumberFormatException nfe) {} + return i; + } + + static boolean getBooleanProperty(final String property, final boolean jnlpAlias) { + return getBooleanProperty(property, jnlpAlias, localACC); + } + + public static boolean getBooleanProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc) { + Boolean b = Boolean.valueOf(Debug.getProperty(property, jnlpAlias, acc)); + return b.booleanValue(); + } + + static boolean isPropertyDefined(final String property, final boolean jnlpAlias) { + return isPropertyDefined(property, jnlpAlias, localACC); + } + + public static boolean isPropertyDefined(final String property, final boolean jnlpAlias, final AccessControlContext acc) { + return (Debug.getProperty(property, jnlpAlias, acc) != null) ? true : false; + } + + static String getProperty(final String property, final boolean jnlpAlias) { + return getProperty(property, jnlpAlias, localACC); + } + + public static String getProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc) { + String s=null; + if(null!=acc && acc.equals(localACC)) { + s = (String) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String val=null; + try { + val = System.getProperty(property); + } catch (Exception e) {} + if(null==val && jnlpAlias && !property.startsWith(jnlp_prefix)) { + try { + val = System.getProperty(jnlp_prefix + property); + } catch (Exception e) {} + } + return val; + } + }); + } else { + try { + s = System.getProperty(property); + } catch (Exception e) {} + if(null==s && jnlpAlias && !property.startsWith(jnlp_prefix)) { + try { + s = System.getProperty(jnlp_prefix + property); + } catch (Exception e) {} + } + } + return s; + } + public static final String jnlp_prefix = "jnlp." ; + + public static boolean verbose() { + return verbose; + } + + public static boolean debugAll() { + return debugAll; + } + + public static boolean debug(String subcomponent) { + return debugAll() || isPropertyDefined("jogl.debug." + subcomponent, true); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ExtensionAvailabilityCache.java b/src/jogl/classes/com/jogamp/opengl/impl/ExtensionAvailabilityCache.java new file mode 100644 index 000000000..9d1235e13 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/ExtensionAvailabilityCache.java @@ -0,0 +1,211 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import javax.media.opengl.*; +import java.util.*; +// FIXME: refactor Java SE dependencies +//import java.util.regex.*; +import java.lang.reflect.*; + +/** + * A utility object intended to be used by implementations to act as a cache + * of which OpenGL extensions are currently available on both the host machine + * and display. + */ +public final class ExtensionAvailabilityCache { + private static final boolean DEBUG = Debug.debug("ExtensionAvailabilityCache"); + private static final boolean DEBUG_AVAILABILITY = Debug.isPropertyDefined("ExtensionAvailabilityCache", true); + + ExtensionAvailabilityCache(GLContextImpl context) + { + this.context = context; + } + + /** + * Flush the cache. The cache will be rebuilt lazily as calls to {@link + * #isExtensionAvailable(String)} are received. + */ + public void flush() + { + if(DEBUG) { + System.out.println("ExtensionAvailabilityCache: Flush availability OpenGL "+context.getGLVersion()); + } + availableExtensionCache.clear(); + initialized = false; + } + + /** + * Flush the cache and rebuild the cache. + */ + public void reset() { + flush(); + initAvailableExtensions(); + } + + public boolean isInitialized() { + return initialized && !availableExtensionCache.isEmpty() ; + } + + public boolean isExtensionAvailable(String glExtensionName) { + initAvailableExtensions(); + return availableExtensionCache.contains(mapGLExtensionName(glExtensionName)); + } + + public String getPlatformExtensionsString() { + initAvailableExtensions(); + return glXExtensions; + } + + public String getGLExtensions() { + initAvailableExtensions(); + if(DEBUG) { + System.err.println("ExtensionAvailabilityCache: getGLExtensions() called"); + } + return glExtensions; + } + + private void initAvailableExtensions() { + GL gl = context.getGL(); + // if hash is empty (meaning it was flushed), pre-cache it with the list + // of extensions that are in the GL_EXTENSIONS string + if (availableExtensionCache.isEmpty() || !initialized) { + if (DEBUG) { + System.err.println("ExtensionAvailabilityCache: Pre-caching init "+gl+", OpenGL "+context.getGLVersion()); + } + + boolean useGetStringi = false; + + if ( gl.isGL2GL3() ) { + if ( ! gl.isFunctionAvailable("glGetStringi") ) { + if(DEBUG) { + System.err.println("GLContext: GL >= 3.1 usage, but no glGetStringi"); + } + } else { + useGetStringi = true; + } + } + + if (DEBUG) { + System.err.println("ExtensionAvailabilityCache: Pre-caching extension availability OpenGL "+context.getGLVersion()+ + ", use "+ ( useGetStringi ? "glGetStringi" : "glGetString" ) ); + } + + StringBuffer sb = new StringBuffer(); + if(useGetStringi) { + GL2GL3 gl2gl3 = gl.getGL2GL3(); + int[] numExtensions = { 0 } ; + gl2gl3.glGetIntegerv(gl2gl3.GL_NUM_EXTENSIONS, numExtensions, 0); + for (int i = 0; i < numExtensions[0]; i++) { + sb.append(gl2gl3.glGetStringi(gl2gl3.GL_EXTENSIONS, i)); + if(i < numExtensions[0]) { + sb.append(" "); + } + } + } else { + sb.append(gl.glGetString(GL.GL_EXTENSIONS)); + } + glExtensions = sb.toString(); + glXExtensions = context.getPlatformExtensionsString(); + + sb.append(" "); + sb.append(glXExtensions); + + String allAvailableExtensions = sb.toString(); + if (DEBUG_AVAILABILITY) { + System.err.println("ExtensionAvailabilityCache: Available extensions: " + allAvailableExtensions); + System.err.println("ExtensionAvailabilityCache: GL vendor: " + gl.glGetString(GL.GL_VENDOR)); + } + StringTokenizer tok = new StringTokenizer(allAvailableExtensions); + while (tok.hasMoreTokens()) { + String availableExt = tok.nextToken().trim(); + availableExt = availableExt.intern(); + availableExtensionCache.add(availableExt); + if (DEBUG_AVAILABILITY) { + System.err.println("ExtensionAvailabilityCache: Available: " + availableExt); + } + } + + int major[] = new int[] { context.getGLVersionMajor() }; + int minor[] = new int[] { context.getGLVersionMinor() }; + if( !gl.isGL3() && !gl.isGL4() && + ( major[0] > 3 || + ( major[0] == 3 && minor[0] >= 1 ) ) ) { + // downsize version to 3.0 in case we are not using GL3 (>=3.1) + major[0] = 3; + minor[0] = 0; + } + while (GLContext.isValidGLVersion(major[0], minor[0])) { + availableExtensionCache.add("GL_VERSION_" + major[0] + "_" + minor[0]); + if (DEBUG) { + System.err.println("ExtensionAvailabilityCache: Added GL_VERSION_" + major[0] + "_" + minor[0] + " to known extensions"); + } + if(!GLContext.decrementGLVersion(major, minor)) break; + } + + // put a dummy var in here so that the cache is no longer empty even if + // no extensions are in the GL_EXTENSIONS string + availableExtensionCache.add("<INTERNAL_DUMMY_PLACEHOLDER>"); + + initialized = true; + } + } + + // FIXME: hack to re-enable GL_NV_vertex_array_range extension after + // recent upgrade to new wglext.h and glxext.h headers + private static String mapGLExtensionName(String extensionName) { + if (extensionName != null && + (extensionName.equals("WGL_NV_vertex_array_range") || + extensionName.equals("GLX_NV_vertex_array_range"))) + return "GL_NV_vertex_array_range"; + return extensionName; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private boolean initialized = false; + private String glExtensions = null; + private String glXExtensions = null; + private HashSet availableExtensionCache = new HashSet(50); + private GLContextImpl context; + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java new file mode 100755 index 000000000..48affa534 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2006 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.util.*; +import javax.media.opengl.*; + +/** + * Tracks as closely as possible the sizes of allocated OpenGL buffer + * objects. When glMapBuffer or glMapBufferARB is called, in order to + * turn the resulting base address into a java.nio.ByteBuffer, we need + * to know the size in bytes of the allocated OpenGL buffer object. + * Previously we would compute this size by using + * glGetBufferParameterivARB with a pname of GL_BUFFER_SIZE, but + * it appears doing so each time glMapBuffer is called is too costly + * on at least Apple's new multithreaded OpenGL implementation. <P> + * + * Instead we now try to track the sizes of allocated buffer objects. + * We watch calls to glBindBuffer to see which buffer is bound to + * which target and to glBufferData to see how large the buffer's + * allocated size is. When glMapBuffer is called, we consult our table + * of buffer sizes to see if we can return an answer without a glGet + * call. <P> + * + * We share the GLBufferSizeTracker objects among all GLContexts for + * which sharing is enabled, because the namespace for buffer objects + * is the same for these contexts. <P> + * + * Tracking the state of which buffer objects are bound is done in the + * GLBufferStateTracker and is not completely trivial. In the face of + * calls to glPushClientAttrib / glPopClientAttrib we currently punt + * and re-fetch the bound buffer object for the state in question; + * see, for example, glVertexPointer and the calls down to + * GLBufferStateTracker.getBoundBufferObject(). Note that we currently + * ignore new binding targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV; + * the fact that new binding targets may be added in the future makes + * it impossible to cache state for these new targets. <P> + * + * Ignoring new binding targets, the primary situation in which we may + * not be able to return a cached answer is in the case of an error, + * where glBindBuffer may not have been called before trying to call + * glBufferData. Also, if external native code modifies a buffer + * object, we may return an incorrect answer. (FIXME: this case + * requires more thought, and perhaps stochastic and + * exponential-fallback checking. However, note that it can only occur + * in the face of external native code which requires that the + * application be signed anyway, so there is no security risk in this + * area.) + */ + +public class GLBufferSizeTracker { + // Map from buffer names to sizes. + // Note: should probably have some way of shrinking this map, but + // can't just make it a WeakHashMap because nobody holds on to the + // keys; would have to always track creation and deletion of buffer + // objects, which is probably sub-optimal. The expected usage + // pattern of buffer objects indicates that the fact that this map + // never shrinks is probably not that bad. + private Map/*<Integer,Integer>*/ bufferSizeMap = + Collections.synchronizedMap(new HashMap/*<Integer,Integer>*/()); + + private static final boolean DEBUG = Debug.debug("GLBufferSizeTracker"); + + public GLBufferSizeTracker() { + } + + public void setBufferSize(GLBufferStateTracker bufferStateTracker, + int target, + GL caller, + int size) { + // Need to do some similar queries to getBufferSize below + int buffer = bufferStateTracker.getBoundBufferObject(target, caller); + boolean valid = bufferStateTracker.isBoundBufferObjectKnown(target); + if (valid) { + if (buffer == 0) { + // FIXME: this really should not happen if we know what's + // going on. Very likely there is an OpenGL error in the + // application if we get here. Could silently return 0, but it + // seems better to get an early warning that something is + // wrong. + throw new GLException("Error: no OpenGL buffer object appears to be bound to target 0x" + + Integer.toHexString(target)); + } + bufferSizeMap.put(new Integer(buffer), new Integer(size)); + } + // We don't know the current buffer state. Note that the buffer + // state tracker will have made the appropriate OpenGL query if it + // didn't know what was going on, so at this point we have nothing + // left to do except drop this piece of information on the floor. + } + + public int getBufferSize(GLBufferStateTracker bufferStateTracker, + int target, + GL caller) { + // See whether we know what buffer is currently bound to the given + // state + int buffer = bufferStateTracker.getBoundBufferObject(target, caller); + boolean valid = bufferStateTracker.isBoundBufferObjectKnown(target); + if (valid) { + if (buffer == 0) { + // FIXME: this really should not happen if we know what's + // going on. Very likely there is an OpenGL error in the + // application if we get here. Could silently return 0, but it + // seems better to get an early warning that something is + // wrong. + throw new GLException("Error: no OpenGL buffer object appears to be bound to target 0x" + + Integer.toHexString(target)); + } + // See whether we know the size of this buffer object; at this + // point we almost certainly should if the application is + // written correctly + Integer key = new Integer(buffer); + Integer sz = (Integer) bufferSizeMap.get(key); + if (sz == null) { + // For robustness, try to query this value from the GL as we used to + int[] tmp = new int[1]; + caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0); + if (tmp[0] == 0) { + // Assume something is wrong rather than silently going along + throw new GLException("Error: buffer size returned by glGetBufferParameteriv was zero; probably application error"); + } + // Assume we just don't know what's happening + sz = new Integer(tmp[0]); + bufferSizeMap.put(key, sz); + if (DEBUG) { + System.err.println("GLBufferSizeTracker.getBufferSize(): made slow query to cache size " + + tmp[0] + + " for buffer " + + buffer); + } + } + return sz.intValue(); + } + // We don't know what's going on in this case; query the GL for an answer + int[] tmp = new int[1]; + caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0); + if (DEBUG) { + System.err.println("GLBufferSizeTracker.getBufferSize(): no cached buffer information"); + } + return tmp[0]; + } + + // This should be called on any major event where we might start + // producing wrong answers, such as OpenGL context creation and + // destruction if we don't know whether there are other currently- + // created contexts that might be keeping the buffer objects alive + // that we're dealing with + public void clearCachedBufferSizes() { + bufferSizeMap.clear(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLBufferStateTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferStateTracker.java new file mode 100755 index 000000000..df8d673a1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferStateTracker.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2006 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.util.*; +import javax.media.opengl.*; + +/** + * Tracks as closely as possible which OpenGL buffer object is bound + * to which binding target in the current OpenGL context. + * GLBufferStateTracker objects are allocated on a per-OpenGL-context basis. + * This class is used to verify that e.g. the vertex + * buffer object extension is in use when the glVertexPointer variant + * taking a long as argument is called. <P> + * + * Note that because the enumerated value used for the binding of a + * buffer object (e.g. GL_ARRAY_BUFFER) is different than that used to + * query the binding using glGetIntegerv (e.g. + * GL_ARRAY_BUFFER_BINDING), then in the face of new binding targets + * being added to the GL (e.g. GL_TRANSFORM_FEEDBACK_BUFFER_NV) it is + * impossible to set up a query of the buffer object currently bound + * to a particular state. It turns out that for some uses, such as + * finding the size of the currently bound buffer, this doesn't + * matter, though of course without knowing the buffer object we can't + * re-associate the queried size with the buffer object ID. <P> + * + * Because the namespace of buffer objects is the unsigned integers + * with 0 reserved by the GL, and because we have to be able to return + * both 0 and other integers as valid answers from + * getBoundBufferObject(), we need a second query, which is to ask + * whether we know the state of the binding for a given target. For + * "unknown" targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV we return + * false from this, but we also clear the valid bit and later refresh + * the binding state if glPushClientAttrib / glPopClientAttrib are + * called, since we don't want the complexity of tracking stacks of + * these attributes. + * + */ + +public class GLBufferStateTracker { + private static final boolean DEBUG = Debug.debug("GLBufferStateTracker"); + + private static final Integer arrayBufferEnum = new Integer(GL.GL_ARRAY_BUFFER); + private static final Integer elementArrayBufferEnum = new Integer(GL.GL_ELEMENT_ARRAY_BUFFER); + private static final Integer pixelPackBufferEnum = new Integer(GL2.GL_PIXEL_PACK_BUFFER); + private static final Integer pixelUnpackBufferEnum = new Integer(GL2.GL_PIXEL_UNPACK_BUFFER); + private static final Integer zero = new Integer(0); + + // Maps binding targets to buffer objects. A null value indicates + // that the binding is unknown. A zero value indicates that it is + // known that no buffer is bound to the target. + private Map/*<Integer,Integer>*/ bindingMap = new HashMap/*<Integer,Integer>*/(); + + private int[] bufTmp = new int[1]; + + public GLBufferStateTracker() { + // Start with known unbound targets for known keys + bindingMap.put(arrayBufferEnum, zero); + bindingMap.put(elementArrayBufferEnum, zero); + bindingMap.put(pixelPackBufferEnum, zero); + bindingMap.put(pixelUnpackBufferEnum, zero); + } + + public void setBoundBufferObject(int target, int buffer) { + bindingMap.put(box(target), box(buffer)); + } + + /** Note: returns an unspecified value if the binding for the + specified target (e.g. GL_ARRAY_BUFFER) is currently unknown. + You must use isBoundBufferObjectKnown() to see whether the + return value is valid. */ + public int getBoundBufferObject(int target, GL caller) { + Integer value = (Integer) bindingMap.get(box(target)); + if (value == null) { + // User probably either called glPushClientAttrib / + // glPopClientAttrib or is querying an unknown target. See + // whether we know how to fetch this state. + boolean gotQueryTarget = true; + int queryTarget = 0; + switch (target) { + case GL.GL_ARRAY_BUFFER: queryTarget = GL.GL_ARRAY_BUFFER_BINDING; break; + case GL.GL_ELEMENT_ARRAY_BUFFER: queryTarget = GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; break; + case GL2.GL_PIXEL_PACK_BUFFER: queryTarget = GL2.GL_PIXEL_PACK_BUFFER_BINDING; break; + case GL2.GL_PIXEL_UNPACK_BUFFER: queryTarget = GL2.GL_PIXEL_UNPACK_BUFFER_BINDING; break; + default: gotQueryTarget = false; break; + } + if (gotQueryTarget) { + caller.glGetIntegerv(queryTarget, bufTmp, 0); + if (DEBUG) { + System.err.println("GLBufferStateTracker.getBoundBufferObject(): queried bound buffer " + + bufTmp[0] + + " for query target 0x" + Integer.toHexString(queryTarget)); + } + setBoundBufferObject(target, bufTmp[0]); + // Try once more + return getBoundBufferObject(target, caller); + } + return 0; + } + return value.intValue(); + } + + /** Indicates whether the binding state for the specified target is + currently known. Should be called after getBoundBufferObject() + because that method may change the answer for a given target. */ + public boolean isBoundBufferObjectKnown(int target) { + return (bindingMap.get(box(target)) != null); + } + + /** Clears out the known/unknown state of the various buffer object + binding states. These will be refreshed later on an as-needed + basis. This is called by the implementations of + glPushClientAttrib / glPopClientAttrib. Might want to call this + from GLContext.makeCurrent() in the future to possibly increase + the robustness of these caches in the face of external native + code manipulating OpenGL state. */ + public void clearBufferObjectState() { + bindingMap.clear(); + } + + // FIXME: could largely remove this and use Integer.valueOf() in JDK 5 + private static Integer box(int key) { + switch (key) { + case 0: return zero; + case GL.GL_ARRAY_BUFFER: return arrayBufferEnum; + case GL.GL_ELEMENT_ARRAY_BUFFER: return elementArrayBufferEnum; + case GL2.GL_PIXEL_PACK_BUFFER: return pixelPackBufferEnum; + case GL2.GL_PIXEL_UNPACK_BUFFER: return pixelUnpackBufferEnum; + default: return new Integer(key); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java new file mode 100644 index 000000000..7143344bf --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java @@ -0,0 +1,1057 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import com.jogamp.common.os.DynamicLookupHelper; +import java.nio.*; +import java.util.*; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.gluegen.runtime.*; +import com.jogamp.gluegen.runtime.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.ReflectionUtil; + +public abstract class GLContextImpl extends GLContext { + protected GLContextLock lock = new GLContextLock(); + protected static final boolean DEBUG = Debug.debug("GLContext"); + protected static final boolean VERBOSE = Debug.verbose(); + // NOTE: default sense of GLContext optimization disabled in JSR-231 + // 1.0 beta 5 due to problems on X11 platforms (both Linux and + // Solaris) when moving and resizing windows. Apparently GLX tokens + // get sent to the X server under the hood (and out from under the + // cover of the AWT lock) in these situations. Users requiring + // multi-screen X11 applications can manually enable this flag. It + // basically had no tangible effect on the Windows or Mac OS X + // platforms anyway in particular with the disabling of the + // GLWorkerThread which we found to be necessary in 1.0 beta 4. + protected boolean optimizationEnabled = Debug.isPropertyDefined("jogl.GLContext.optimize", true); + + // Cache of the functions that are available to be called at the current + // moment in time + protected ExtensionAvailabilityCache extensionAvailability; + // Table that holds the addresses of the native C-language entry points for + // OpenGL functions. + private ProcAddressTable glProcAddressTable; + + // Tracks creation and initialization of buffer objects to avoid + // repeated glGet calls upon glMapBuffer operations + private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet + private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker(); + private GLStateTracker glStateTracker = new GLStateTracker(); + + protected GLDrawableImpl drawable; + protected GLDrawableImpl drawableRead; + + protected GL gl; + + public GLContextImpl(GLDrawableImpl drawable, GLDrawableImpl drawableRead, GLContext shareWith) { + extensionAvailability = new ExtensionAvailabilityCache(this); + if (shareWith != null) { + GLContextShareSet.registerSharing(this, shareWith); + } + GLContextShareSet.registerForBufferObjectSharing(shareWith, this); + // This must occur after the above calls into the + // GLContextShareSet, which set up state needed by the GL object + setGL(createGL(drawable.getGLProfile())); + + this.drawable = drawable; + setGLDrawableRead(drawableRead); + } + + public GLContextImpl(GLDrawableImpl drawable, GLContext shareWith) { + this(drawable, null, shareWith); + } + + public void setGLDrawableRead(GLDrawable read) { + boolean lockHeld = lock.isHeld(); + if(lockHeld) { + release(); + } + drawableRead = ( null != read ) ? (GLDrawableImpl) read : drawable; + if(lockHeld) { + makeCurrent(); + } + } + + public GLDrawable getGLDrawable() { + return drawable; + } + + public GLDrawable getGLDrawableRead() { + return drawableRead; + } + + public GLDrawableImpl getDrawableImpl() { + return (GLDrawableImpl) getGLDrawable(); + } + + public final GL getGL() { + return gl; + } + + public GL setGL(GL gl) { + if(DEBUG) { + String sgl1 = (null!=this.gl)?this.gl.getClass().toString()+", "+this.gl.toString():new String("<null>"); + String sgl2 = (null!=gl)?gl.getClass().toString()+", "+gl.toString():new String("<null>"); + Exception e = new Exception("setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread()+", "+sgl1+" -> "+sgl2); + e.printStackTrace(); + } + this.gl = gl; + return gl; + } + + // This is only needed for Mac OS X on-screen contexts + protected void update() throws GLException { } + + public boolean isSynchronized() { + return !lock.getFailFastMode(); + } + + public void setSynchronized(boolean isSynchronized) { + lock.setFailFastMode(!isSynchronized); + } + + public abstract Object getPlatformGLExtensions(); + + public void release() throws GLException { + if (!lock.isHeld()) { + throw new GLException("Context not current on current thread"); + } + setCurrent(null); + try { + releaseImpl(); + } finally { + lock.unlock(); + } + } + + protected abstract void releaseImpl() throws GLException; + + public void destroy() { + if (lock.isHeld()) { + // release current context + release(); + } + + // Must hold the lock around the destroy operation to make sure we + // don't destroy the context out from under another thread rendering to it + lock.lock(); + try { + /* FIXME: refactor dependence on Java 2D / JOGL bridge + if (tracker != null) { + // Don't need to do anything for contexts that haven't been + // created yet + if (isCreated()) { + // If we are tracking creation and destruction of server-side + // OpenGL objects, we must decrement the reference count of the + // GLObjectTracker upon context destruction. + // + // Note that we can only eagerly delete these server-side + // objects if there is another context currrent right now + // which shares textures and display lists with this one. + tracker.unref(deletedObjectTracker); + } + } + */ + + // Because we don't know how many other contexts we might be + // sharing with (and it seems too complicated to implement the + // GLObjectTracker's ref/unref scheme for the buffer-related + // optimizations), simply clear the cache of known buffers' sizes + // when we destroy contexts + if (bufferSizeTracker != null) { + bufferSizeTracker.clearCachedBufferSizes(); + } + + if (bufferStateTracker != null) { + bufferStateTracker.clearBufferObjectState(); + } + + if (glStateTracker != null) { + glStateTracker.clearStates(false); + } + + destroyImpl(); + } finally { + lock.unlock(); + } + } + + protected abstract void destroyImpl() throws GLException; + + //---------------------------------------------------------------------- + // + + /** + * MakeCurrent functionality, which also issues the creation of the actual OpenGL context.<br> + * The complete callgraph for general OpenGL context creation is:<br> + * <ul> + * <li> {@link #makeCurrent} <i>GLContextImpl</i> + * <li> {@link #makeCurrentImpl} <i>Platform Implementation</i> + * <li> {@link #create} <i>Platform Implementation</i> + * <li> If <code>ARB_create_context</code> is supported: + * <ul> + * <li> {@link #createContextARB} <i>GLContextImpl</i> + * <li> {@link #createContextARBImpl} <i>Platform Implementation</i> + * </ul> + * </ul><br> + * + * Once at startup, ie triggered by the singleton {@link GLDrawableImpl} constructor, + * calling {@link #createContextARB} will query all available OpenGL versions:<br> + * <ul> + * <li> <code>FOR ALL GL* DO</code>: + * <ul> + * <li> {@link #createContextARBMapVersionsAvailable} + * <ul> + * <li> {@link #createContextARBVersions} + * </ul> + * <li> {@link #mapVersionAvailable} + * </ul> + * </ul><br> + * + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #mapVersionAvailable + * @see #destroyContextARBImpl + */ + public int makeCurrent() throws GLException { + // Support calls to makeCurrent() over and over again with + // different contexts without releasing them + // Could implement this more efficiently without explicit + // releasing of the underlying context; would require more error + // checking during the makeCurrentImpl phase + GLContext current = getCurrent(); + if (current != null) { + if (current == this) { + // Assume we don't need to make this context current again + // For Mac OS X, however, we need to update the context to track resizes + update(); + return CONTEXT_CURRENT; + } else { + current.release(); + } + } + + if (GLWorkerThread.isStarted() && + !GLWorkerThread.isWorkerThread()) { + // Kick the GLWorkerThread off its current context + GLWorkerThread.invokeLater(new Runnable() { public void run() {} }); + } + + lock.lock(); + int res = 0; + try { + res = makeCurrentImpl(); + + /* FIXME: refactor dependence on Java 2D / JOGL bridge + if ((tracker != null) && + (res == CONTEXT_CURRENT_NEW)) { + // Increase reference count of GLObjectTracker + tracker.ref(); + } + */ + } catch (GLException e) { + lock.unlock(); + throw(e); + } + if (res == CONTEXT_NOT_CURRENT) { + lock.unlock(); + } else { + if(res == CONTEXT_CURRENT_NEW) { + // check if the drawable's and the GL's GLProfile are equal + // throws an GLException if not + getGLDrawable().getGLProfile().verifyEquality(gl.getGLProfile()); + } + setCurrent(this); + + /* FIXME: refactor dependence on Java 2D / JOGL bridge + + // Try cleaning up any stale server-side OpenGL objects + // FIXME: not sure what to do here if this throws + if (deletedObjectTracker != null) { + deletedObjectTracker.clean(getGL()); + } + */ + } + return res; + } + + /** + * @see #makeCurrent + */ + protected abstract int makeCurrentImpl() throws GLException; + + /** + * @see #makeCurrent + */ + protected abstract void create() throws GLException ; + + /** + * Platform dependent but harmonized implementation of the <code>ARB_create_context</code> + * mechanism to create a context.<br> + * + * This method is called from {@link #createContextARB}.<br> + * + * The implementation shall verify this context with a + * <code>MakeContextCurrent</code> call.<br> + * + * @param share the shared context or null + * @param direct flag if direct is requested + * @param ctxOptionFlags <code>ARB_create_context</code> related, see references below + * @param major major number + * @param minor minor number + * @return the valid context if successfull, or null + * + * @see #makeCurrent + * @see #CTX_PROFILE_COMPAT + * @see #CTX_OPTION_FORWARD + * @see #CTX_OPTION_DEBUG + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, + int major, int minor); + + /** + * Destroy the context created by {@link #createContextARBImpl}. + * + * @see #makeCurrent + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected abstract void destroyContextARBImpl(long context); + + /** + * Platform independent part of using the <code>ARB_create_context</code> + * mechanism to create a context.<br> + * + * The implementation of {@link #create} shall use this protocol in case the platform supports <code>ARB_create_context</code>.<br> + * + * This method may call {@link #createContextARBImpl} and {@link #destroyContextARBImpl}. <br> + * + * This method will also query all available native OpenGL context when first called,<br> + * usually the first call should happen with the shared GLContext of the DrawableFactory.<br> + * + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected long createContextARB(long share, boolean direct, + int major[], int minor[], int ctp[]) + { + AbstractGraphicsConfiguration config = drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); + GLProfile glp = glCaps.getGLProfile(); + long _context = 0; + + if( !mappedVersionsAvailableSet ) { + synchronized(mappedVersionsAvailableLock) { + if( !mappedVersionsAvailableSet ) { + createContextARBMapVersionsAvailable(4, false /* compat */); // GL4 + createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc + createContextARBMapVersionsAvailable(3, false /* compat */); // GL3 + createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc + createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 + mappedVersionsAvailableSet=true; + } + } + } + + int reqMajor; + if(glp.isGL4()) { + reqMajor=4; + } else if (glp.isGL3()) { + reqMajor=3; + } else /* if (glp.isGL2()) */ { + reqMajor=2; + } + boolean compat = glp.isGL2(); // incl GL3bc and GL4bc + + int key = compose8bit(reqMajor, compat?CTX_PROFILE_COMPAT:CTX_PROFILE_CORE, 0, 0); + int val = mappedVersionsAvailable.get( key ); + long _ctx = 0; + if(val>0) { + int _major = getComposed8bit(val, 1); + int _minor = getComposed8bit(val, 2); + int _ctp = getComposed8bit(val, 3); + + _ctx = createContextARBImpl(share, direct, _ctp, _major, _minor); + if(0!=_ctx) { + setGLFunctionAvailability(true, _major, _minor, _ctp); + } + } + return _ctx; + } + + private void createContextARBMapVersionsAvailable(int reqMajor, boolean compat) + { + long _context; + int ctp = CTX_IS_ARB_CREATED | CTX_PROFILE_CORE | CTX_OPTION_ANY; // default + if(compat) { + ctp &= ~CTX_PROFILE_CORE ; + ctp |= CTX_PROFILE_COMPAT ; + } + + // FIXME GL3GL4: + // To avoid OpenGL implementation bugs and raise compatibility + // within JOGL, we map to the proper GL version. + // This may change later when GL3 and GL4 drivers become more mature! + // Bug: To ensure GL profile compatibility within the JOGL application + // Bug: we always try to map against the highest GL version, + // Bug: so the use can always cast to a higher one + // Bug: int majorMax=GLContext.getMaxMajor(); + // Bug: int minorMax=GLContext.getMaxMinor(majorMax); + int majorMax, minorMax; + int majorMin, minorMin; + int major[] = new int[1]; + int minor[] = new int[1]; + if( 4 == reqMajor ) { + majorMax=4; minorMax=GLContext.getMaxMinor(majorMax); + majorMin=4; minorMin=0; + } else if( 3 == reqMajor ) { + majorMax=3; minorMax=GLContext.getMaxMinor(majorMax); + majorMin=3; minorMin=1; + } else /* if( glp.isGL2() ) */ { + majorMax=3; minorMax=0; + majorMin=1; minorMin=1; // our minimum desktop OpenGL runtime requirements + } + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + + if(0==_context && !compat) { + ctp &= ~CTX_PROFILE_COMPAT ; + ctp |= CTX_PROFILE_CORE ; + ctp &= ~CTX_OPTION_ANY ; + ctp |= CTX_OPTION_FORWARD ; + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + if(0==_context) { + // Try a compatible one .. even though not requested .. last resort + ctp &= ~CTX_PROFILE_CORE ; + ctp |= CTX_PROFILE_COMPAT ; + ctp &= ~CTX_OPTION_FORWARD ; + ctp |= CTX_OPTION_ANY ; + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + } + } + if(0!=_context) { + destroyContextARBImpl(_context); + mapVersionAvailable(reqMajor, compat, major[0], minor[0], ctp); + } + } + + private long createContextARBVersions(long share, boolean direct, int ctxOptionFlags, + int majorMax, int minorMax, + int majorMin, int minorMin, + int major[], int minor[]) { + major[0]=majorMax; + minor[0]=minorMax; + long _context=0; + + while ( 0==_context && + GLContext.isValidGLVersion(major[0], minor[0]) && + ( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) { + + _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); + + if(0==_context) { + if(!GLContext.decrementGLVersion(major, minor)) break; + } + } + return _context; + } + + //---------------------------------------------------------------------- + // Managing the actual OpenGL version, usually figured at creation time. + // As a last resort, the GL_VERSION string may be used .. + // + + /** + * If major > 0 || minor > 0 : Use passed values, determined at creation time + * If major==0 && minor == 0 : Use GL_VERSION + * Otherwise .. don't touch .. + */ + protected void setContextVersion(int major, int minor, int ctp) { + if (0==ctp) { + GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); + throw e; + } + if(major>0 || minor>0) { + if (!GLContext.isValidGLVersion(major, minor)) { + GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); + throw e; + } + ctxMajorVersion = major; + ctxMinorVersion = minor; + ctxOptions = ctp; + ctxVersionString = getGLVersion(gl, ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION)); + return; + } + + if(major==0 && minor==0) { + String versionStr = getGL().glGetString(GL.GL_VERSION); + if(null==versionStr) { + throw new GLException("GL_VERSION is NULL: "+this); + } + ctxOptions = ctp; + + // Set version + Version version = new Version(versionStr); + if (version.isValid()) { + ctxMajorVersion = version.getMajor(); + ctxMinorVersion = version.getMinor(); + + ctxVersionString = getGLVersion(gl, ctxMajorVersion, ctxMinorVersion, ctxOptions, versionStr); + return; + } + } + } + + private static boolean appendString(StringBuffer sb, String string, boolean needColon, boolean condition) { + if(condition) { + if(needColon) { + sb.append(", "); + } + sb.append(string); + needColon=true; + } + return needColon; + } + + protected static String getGLVersion(GL gl, int major, int minor, int ctp, String gl_version) { + boolean needColon = false; + StringBuffer sb = new StringBuffer(); + sb.append(major); + sb.append("."); + sb.append(minor); + sb.append(" ("); + needColon = appendString(sb, "ES", needColon, null!=gl && gl.isGLES()); + needColon = appendString(sb, "compatibility profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp )); + needColon = appendString(sb, "core profile", needColon, 0 != ( CTX_PROFILE_CORE & ctp )); + needColon = appendString(sb, "forward compatible", needColon, 0 != ( CTX_OPTION_FORWARD & ctp )); + needColon = appendString(sb, "any", needColon, 0 != ( CTX_OPTION_ANY & ctp )); + needColon = appendString(sb, "new", needColon, 0 != ( CTX_IS_ARB_CREATED & ctp )); + needColon = appendString(sb, "old", needColon, 0 == ( CTX_IS_ARB_CREATED & ctp )); + sb.append(") - "); + if(null!=gl_version) { + sb.append(gl_version); + } else { + sb.append("n/a"); + } + return sb.toString(); + } + + //---------------------------------------------------------------------- + // Helpers for various context implementations + // + + private Object createInstance(GLProfile glp, String suffix, Class[] cstrArgTypes, Object[] cstrArgs) { + return ReflectionUtil.createInstance(glp.getGLImplBaseClassName()+suffix, cstrArgTypes, cstrArgs); + } + + /** Create the GL for this context. */ + protected GL createGL(GLProfile glp) { + GL gl = (GL) createInstance(glp, "Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { glp, this } ); + + /* FIXME: refactor dependence on Java 2D / JOGL bridge + if (tracker != null) { + gl.setObjectTracker(tracker); + } + */ + return gl; + } + + public final ProcAddressTable getGLProcAddressTable() { + return glProcAddressTable; + } + + /** + * Shall return the platform extension ProcAddressTable, + * ie for GLXExt, EGLExt, .. + */ + public abstract ProcAddressTable getPlatformExtProcAddressTable(); + + /** + * Pbuffer support; given that this is a GLContext associated with a + * pbuffer, binds this pbuffer to its texture target. + */ + public abstract void bindPbufferToTexture(); + + /** + * Pbuffer support; given that this is a GLContext associated with a + * pbuffer, releases this pbuffer from its texture target. + */ + public abstract void releasePbufferFromTexture(); + + public abstract ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3); + + public void setSwapInterval(final int interval) { + GLContext current = getCurrent(); + if (current != this) { + throw new GLException("This context is not current. Current context: "+current+ + ", this context "+this); + } + setSwapIntervalImpl(interval); + } + + protected int currentSwapInterval = -1; // default: not set yet .. + + public int getSwapInterval() { + return currentSwapInterval; + } + + protected void setSwapIntervalImpl(final int interval) { + // nop per default .. + } + + /** Maps the given "platform-independent" function name to a real function + name. Currently this is only used to map "glAllocateMemoryNV" and + associated routines to wglAllocateMemoryNV / glXAllocateMemoryNV. */ + protected String mapToRealGLFunctionName(String glFunctionName) { + Map/*<String, String>*/ map = getFunctionNameMap(); + String lookup = ( null != map ) ? (String) map.get(glFunctionName) : null; + if (lookup != null) { + return lookup; + } + return glFunctionName; + } + protected abstract Map/*<String, String>*/ getFunctionNameMap() ; + + /** Maps the given "platform-independent" extension name to a real + function name. Currently this is only used to map + "GL_ARB_pbuffer" to "WGL_ARB_pbuffer/GLX_SGIX_pbuffer" and + "GL_ARB_pixel_format" to "WGL_ARB_pixel_format/n.a." + */ + protected String mapToRealGLExtensionName(String glExtensionName) { + Map/*<String, String>*/ map = getExtensionNameMap(); + String lookup = ( null != map ) ? (String) map.get(glExtensionName) : null; + if (lookup != null) { + return lookup; + } + return glExtensionName; + } + protected abstract Map/*<String, String>*/ getExtensionNameMap() ; + + /** Helper routine which resets a ProcAddressTable generated by the + GLEmitter by looking up anew all of its function pointers. */ + protected void resetProcAddressTable(Object table) { + GLProcAddressHelper.resetProcAddressTable(table, getDrawableImpl().getDynamicLookupHelper() ); + } + + /** Indicates whether the underlying OpenGL context has been + created. This is used to manage sharing of display lists and + textures between contexts. */ + public abstract boolean isCreated(); + + /** + * Sets the OpenGL implementation class and + * the cache of which GL functions are available for calling through this + * context. See {@link #isFunctionAvailable(String)} for more information on + * the definition of "available". + * + * @param force force the setting, even if is already being set. + * This might be usefull if you change the OpenGL implementation. + * + * @see #setContextVersion + */ + protected void setGLFunctionAvailability(boolean force, int major, int minor, int ctp) { + if(null!=this.gl && null!=glProcAddressTable && !force) { + return; // already done and not forced + } + if(null==this.gl || force) { + setGL(createGL(getGLDrawable().getGLProfile())); + } + + updateGLProcAddressTable(major, minor, ctp); + } + + /** + * Updates the cache of which GL functions are available for calling through this + * context. See {@link #isFunctionAvailable(String)} for more information on + * the definition of "available". + * + * @see #setContextVersion + */ + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if(null==this.gl) { + throw new GLException("setGLFunctionAvailability not called yet"); + } + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing OpenGL extension address table for " + this); + } + if (glProcAddressTable == null) { + glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), "ProcAddressTable", new Class[0], null); + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + } + resetProcAddressTable(getGLProcAddressTable()); + + setContextVersion(major, minor, ctp); + + extensionAvailability.reset(); + } + + /** + * Returns true if the specified OpenGL core- or extension-function can be + * successfully called using this GL context given the current host (OpenGL + * <i>client</i>) and display (OpenGL <i>server</i>) configuration. + * + * See {@link GL#isFunctionAvailable(String)} for more details. + * + * @param glFunctionName the name of the OpenGL function (e.g., use + * "glPolygonOffsetEXT" or "glPolygonOffset" to check if the {@link + * javax.media.opengl.GL#glPolygonOffset(float,float)} is available). + */ + public boolean isFunctionAvailable(String glFunctionName) { + if(isCreated()) { + // Check GL 1st (cached) + ProcAddressTable pTable = getGLProcAddressTable(); + try { + if(0!=pTable.getAddressFor(glFunctionName)) { + return true; + } + } catch (Exception e) {} + + // Check platform extensions 2nd (cached) + pTable = getPlatformExtProcAddressTable(); + try { + if(0!=pTable.getAddressFor(glFunctionName)) { + return true; + } + } catch (Exception e) {} + } + // dynamic function lookup at last incl name aliasing (not cached) + DynamicLookupHelper dynLookup = getDrawableImpl().getDynamicLookupHelper(); + String tmpBase = GLExtensionNames.normalizeVEN(GLExtensionNames.normalizeARB(glFunctionName, true), true); + long addr = 0; + int variants = GLExtensionNames.getFuncNamePermutationNumber(tmpBase); + for(int i = 0; 0==addr && i < variants; i++) { + String tmp = GLExtensionNames.getFuncNamePermutation(tmpBase, i); + try { + addr = dynLookup.dynamicLookupFunction(tmp); + } catch (Exception e) { } + } + if(0!=addr) { + return true; + } + return false; + } + + /** + * Returns true if the specified OpenGL extension can be + * successfully called using this GL context given the current host (OpenGL + * <i>client</i>) and display (OpenGL <i>server</i>) configuration. + * + * See {@link GL#isExtensionAvailable(String)} for more details. + * + * @param glExtensionName the name of the OpenGL extension (e.g., + * "GL_VERTEX_PROGRAM_ARB"). + */ + public boolean isExtensionAvailable(String glExtensionName) { + return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName)); + } + + public String getPlatformExtensionsString() { + return extensionAvailability.getPlatformExtensionsString(); + } + + public String getGLExtensions() { + return extensionAvailability.getGLExtensions(); + } + + public boolean isExtensionCacheInitialized() { + return extensionAvailability.isInitialized(); + } + + /** Indicates which floating-point pbuffer implementation is in + use. Returns one of GLPbuffer.APPLE_FLOAT, GLPbuffer.ATI_FLOAT, + or GLPbuffer.NV_FLOAT. */ + public int getFloatingPointMode() throws GLException { + throw new GLException("Not supported on non-pbuffer contexts"); + } + + /** On some platforms the mismatch between OpenGL's coordinate + system (origin at bottom left) and the window system's + coordinate system (origin at top left) necessitates a vertical + flip of pixels read from offscreen contexts. */ + public abstract boolean offscreenImageNeedsVerticalFlip(); + + /** Only called for offscreen contexts; needed by glReadPixels */ + public abstract int getOffscreenContextPixelDataType(); + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } + + //---------------------------------------------------------------------- + // Helpers for buffer object optimizations + + public void setBufferSizeTracker(GLBufferSizeTracker bufferSizeTracker) { + this.bufferSizeTracker = bufferSizeTracker; + } + + public GLBufferSizeTracker getBufferSizeTracker() { + return bufferSizeTracker; + } + + public GLBufferStateTracker getBufferStateTracker() { + return bufferStateTracker; + } + + public GLStateTracker getGLStateTracker() { + return glStateTracker; + } + + //--------------------------------------------------------------------------- + // Helpers for context optimization where the last context is left + // current on the OpenGL worker thread + // + + public boolean isOptimizable() { + return optimizationEnabled; + } + + public boolean hasWaiters() { + return lock.hasWaiters(); + } + + /* FIXME: needed only by the Java 2D / JOGL bridge; refactor + + public GLContextImpl(GLContext shareWith) { + this(shareWith, false); + } + + public GLContextImpl(GLContext shareWith, boolean dontShareWithJava2D) { + extensionAvailability = new ExtensionAvailabilityCache(this); + GLContext shareContext = shareWith; + if (!dontShareWithJava2D) { + shareContext = Java2D.filterShareContext(shareWith); + } + if (shareContext != null) { + GLContextShareSet.registerSharing(this, shareContext); + } + // Always indicate real behind-the-scenes sharing to track deleted objects + if (shareContext == null) { + shareContext = Java2D.filterShareContext(shareWith); + } + GLContextShareSet.registerForObjectTracking(shareWith, this, shareContext); + GLContextShareSet.registerForBufferObjectSharing(shareWith, this); + // This must occur after the above calls into the + // GLContextShareSet, which set up state needed by the GL object + setGL(createGL()); + } + + //--------------------------------------------------------------------------- + // Helpers for integration with Java2D/OpenGL pipeline when FBOs are + // being used + // + + public void setObjectTracker(GLObjectTracker tracker) { + this.tracker = tracker; + } + + public GLObjectTracker getObjectTracker() { + return tracker; + } + + public void setDeletedObjectTracker(GLObjectTracker deletedObjectTracker) { + this.deletedObjectTracker = deletedObjectTracker; + } + + public GLObjectTracker getDeletedObjectTracker() { + return deletedObjectTracker; + } + + // Tracks creation and deletion of server-side OpenGL objects when + // the Java2D/OpenGL pipeline is active and using FBOs to render + private GLObjectTracker tracker; + // Supports deletion of these objects when no other context is + // current which can support immediate deletion of them + private GLObjectTracker deletedObjectTracker; + + */ + + /** + * A class for storing and comparing OpenGL version numbers. + * This only works for desktop OpenGL at the moment. + */ + private static class Version implements Comparable + { + private boolean valid; + private int major, minor, sub; + public Version(int majorRev, int minorRev, int subMinorRev) + { + major = majorRev; + minor = minorRev; + sub = subMinorRev; + } + + /** + * @param versionString must be of the form "GL_VERSION_X" or + * "GL_VERSION_X_Y" or "GL_VERSION_X_Y_Z" or "X.Y", where X, Y, + * and Z are integers. + * + * @exception IllegalArgumentException if the argument is not a valid + * OpenGL version identifier + */ + public Version(String versionString) + { + try + { + if (versionString.startsWith("GL_VERSION_")) + { + StringTokenizer tok = new StringTokenizer(versionString, "_"); + + tok.nextToken(); // GL_ + tok.nextToken(); // VERSION_ + if (!tok.hasMoreTokens()) { major = 0; return; } + major = Integer.valueOf(tok.nextToken()).intValue(); + if (!tok.hasMoreTokens()) { minor = 0; return; } + minor = Integer.valueOf(tok.nextToken()).intValue(); + if (!tok.hasMoreTokens()) { sub = 0; return; } + sub = Integer.valueOf(tok.nextToken()).intValue(); + } + else + { + int radix = 10; + if (versionString.length() > 2) { + if (Character.isDigit(versionString.charAt(0)) && + versionString.charAt(1) == '.' && + Character.isDigit(versionString.charAt(2))) { + major = Character.digit(versionString.charAt(0), radix); + minor = Character.digit(versionString.charAt(2), radix); + + // See if there's version-specific information which might + // imply a more recent OpenGL version + StringTokenizer tok = new StringTokenizer(versionString, " "); + if (tok.hasMoreTokens()) { + tok.nextToken(); + if (tok.hasMoreTokens()) { + String token = tok.nextToken(); + int i = 0; + while (i < token.length() && !Character.isDigit(token.charAt(i))) { + i++; + } + if (i < token.length() - 2 && + Character.isDigit(token.charAt(i)) && + token.charAt(i+1) == '.' && + Character.isDigit(token.charAt(i+2))) { + int altMajor = Character.digit(token.charAt(i), radix); + int altMinor = Character.digit(token.charAt(i+2), radix); + // Avoid possibly confusing situations by putting some + // constraints on the upgrades we do to the major and + // minor versions + if ((altMajor == major && altMinor > minor) || + altMajor == major + 1) { + major = altMajor; + minor = altMinor; + } + } + } + } + } + } + } + valid = true; + } + catch (Exception e) + { + e.printStackTrace(); + // FIXME: refactor desktop OpenGL dependencies and make this + // class work properly for OpenGL ES + System.err.println("ExtensionAvailabilityCache: FunctionAvailabilityCache.Version.<init>: "+e); + major = 1; + minor = 0; + /* + throw (IllegalArgumentException) + new IllegalArgumentException( + "Illegally formatted version identifier: \"" + versionString + "\"") + .initCause(e); + */ + } + } + + public boolean isValid() { + return valid; + } + + public int compareTo(Object o) + { + Version vo = (Version)o; + if (major > vo.major) return 1; + else if (major < vo.major) return -1; + else if (minor > vo.minor) return 1; + else if (minor < vo.minor) return -1; + else if (sub > vo.sub) return 1; + else if (sub < vo.sub) return -1; + + return 0; // they are equal + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + } // end class Version + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java new file mode 100644 index 000000000..56a5b023f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java @@ -0,0 +1,126 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import javax.media.opengl.*; + +/** Implements the makeCurrent / release locking behavior of the + GLContext class. When "fail fast mode" is enabled, attempts to + lock the same GLContextLock on more than one thread cause + GLException to be raised. This lock is not recursive. Attempts to + lock it more than once on a given thread will cause GLException to + be raised. */ + +public class GLContextLock { + private Object lock = new Object(); + private Thread owner; + private boolean failFastMode = true; + private volatile int waiters; + + /** Locks this GLContextLock on the current thread. If fail fast + mode is enabled and the GLContextLock is already owned by + another thread, throws GLException. */ + public void lock() throws GLException { + synchronized(lock) { + Thread current = Thread.currentThread(); + if (owner == null) { + owner = current; + } else if (owner != current) { + while (owner != null) { + if (failFastMode) { + throw new GLException("Attempt to make context current on thread " + current + + " which is already current on thread " + owner); + } else { + try { + ++waiters; + lock.wait(); + } catch (InterruptedException e) { + throw new GLException(e); + } finally { + --waiters; + } + } + } + owner = current; + } else { + throw new GLException("Attempt to make the same context current twice on thread " + current); + } + } + } + + /** Unlocks this GLContextLock. */ + public void unlock() throws GLException { + synchronized (lock) { + Thread current = Thread.currentThread(); + if (owner == current) { + owner = null; + lock.notifyAll(); + } else { + if (owner != null) { + throw new GLException("Attempt by thread " + current + + " to release context owned by thread " + owner); + } else { + throw new GLException("Attempt by thread " + current + + " to release unowned context"); + } + } + } + } + + /** Indicates whether this lock is held by the current thread. */ + public boolean isHeld() { + synchronized(lock) { + Thread current = Thread.currentThread(); + return (owner == current); + } + } + + public void setFailFastMode(boolean onOrOff) { + failFastMode = onOrOff; + } + + public boolean getFailFastMode() { + return failFastMode; + } + + public boolean hasWaiters() { + return (waiters != 0); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextShareSet.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextShareSet.java new file mode 100644 index 000000000..abeb231f4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextShareSet.java @@ -0,0 +1,293 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +// FIXME: refactor Java SE dependencies +// import java.awt.GraphicsConfiguration; +// import java.awt.GraphicsDevice; +// import java.awt.GraphicsEnvironment; +import java.lang.ref.*; +import java.util.*; +import javax.media.opengl.*; + +/** Provides a mechanism by which OpenGL contexts can share textures + and display lists in the face of multithreading and asynchronous + context creation as is inherent in the AWT and Swing. */ + +public class GLContextShareSet { + // FIXME: refactor Java SE dependencies + // private static boolean forceTracking = Debug.isPropertyDefined("jogl.glcontext.forcetracking"); + private static final boolean DEBUG = Debug.debug("GLContextShareSet"); + + // This class is implemented with a WeakHashMap that goes from the + // contexts as keys to a complex data structure as value that tracks + // context creation and deletion. + + private static Map/*<GLContext, ShareSet>*/ shareMap = new WeakHashMap(); + private static Object dummyValue = new Object(); + + private static class ShareSet { + private Map allShares = new WeakHashMap(); + private Map createdShares = new WeakHashMap(); + private Map destroyedShares = new WeakHashMap(); + + public void add(GLContext ctx) { + if (allShares.put(ctx, dummyValue) == null) { + // FIXME: downcast to GLContextImpl undesirable + if (((GLContextImpl) ctx).isCreated()) { + createdShares.put(ctx, dummyValue); + } else { + destroyedShares.put(ctx, dummyValue); + } + } + } + + public GLContext getCreatedShare(GLContext ignore) { + for (Iterator iter = createdShares.keySet().iterator(); iter.hasNext(); ) { + GLContext ctx = (GLContext) iter.next(); + if (ctx != ignore) { + return ctx; + } + } + return null; + } + + public void contextCreated(GLContext ctx) { + Object res = destroyedShares.remove(ctx); + assert res != null : "State of ShareSet corrupted; thought context " + + ctx + " should have been in destroyed set but wasn't"; + res = createdShares.put(ctx, dummyValue); + assert res == null : "State of ShareSet corrupted; thought context " + + ctx + " shouldn't have been in created set but was"; + } + + public void contextDestroyed(GLContext ctx) { + Object res = createdShares.remove(ctx); + assert res != null : "State of ShareSet corrupted; thought context " + + ctx + " should have been in created set but wasn't"; + res = destroyedShares.put(ctx, dummyValue); + assert res == null : "State of ShareSet corrupted; thought context " + + ctx + " shouldn't have been in destroyed set but was"; + } + } + + /** Indicate that contexts <code>share1</code> and + <code>share2</code> will share textures and display lists. Both + must be non-null. */ + public static synchronized void registerSharing(GLContext share1, GLContext share2) { + if (share1 == null || share2 == null) { + throw new IllegalArgumentException("Both share1 and share2 must be non-null"); + } + ShareSet share = entryFor(share1); + if (share == null) { + share = entryFor(share2); + } + if (share == null) { + share = new ShareSet(); + } + share.add(share1); + share.add(share2); + addEntry(share1, share); + addEntry(share2, share); + } + + public static synchronized GLContext getShareContext(GLContext contextToCreate) { + ShareSet share = entryFor(contextToCreate); + if (share == null) { + return null; + } + return share.getCreatedShare(contextToCreate); + } + + public static synchronized void contextCreated(GLContext context) { + ShareSet share = entryFor(context); + if (share != null) { + share.contextCreated(context); + } + } + + public static synchronized void contextDestroyed(GLContext context) { + ShareSet share = entryFor(context); + if (share != null) { + share.contextDestroyed(context); + } + } + + /** In order to avoid glGet calls for buffer object checks related + to glVertexPointer, etc. calls as well as glMapBuffer calls, we + need to share the same GLBufferSizeTracker object between + contexts sharing textures and display lists. For now we keep + this mechanism orthogonal to the GLObjectTracker to hopefully + keep things easier to understand. (The GLObjectTracker is + currently only needed in a fairly esoteric case, when the + Java2D/JOGL bridge is active, but the GLBufferSizeTracker + mechanism is now always required.) */ + public static void registerForBufferObjectSharing(GLContext olderContextOrNull, GLContext newContext) { + // FIXME: downcasts to GLContextImpl undesirable + GLContextImpl older = (GLContextImpl) olderContextOrNull; + GLContextImpl newer = (GLContextImpl) newContext; + GLBufferSizeTracker tracker = null; + if (older != null) { + tracker = older.getBufferSizeTracker(); + assert (tracker != null) + : "registerForBufferObjectSharing was not called properly for the older context, or has a bug in it"; + } + if (tracker == null) { + tracker = new GLBufferSizeTracker(); + } + newer.setBufferSizeTracker(tracker); + } + + // FIXME: refactor Java SE dependencies + // /** Indicates that the two supplied contexts (which must be able to + // share textures and display lists) should be in the same + // namespace for tracking of server-side object creation and + // deletion. Because the sharing necessary behind the scenes is + // different than that requested at the user level, the two notions + // are different. This must be called immediately after the + // creation of the new context (which is the second argument) + // before any server-side OpenGL objects have been created in that + // context. */ + // public static void registerForObjectTracking(GLContext olderContextOrNull, + // GLContext newContext, + // GLContext realShareContext) { + // if (isObjectTrackingEnabled() || isObjectTrackingDebuggingEnabled()) { + // GLContextImpl impl1 = null; + // GLContextImpl impl2 = null; + // GLObjectTracker tracker = null; + // + // synchronized (GLContextShareSet.class) { + // if (olderContextOrNull != null && + // newContext != null) { + // if (entryFor(olderContextOrNull) != entryFor(newContext)) { + // throw new IllegalArgumentException("old and new contexts must be able to share textures and display lists"); + // } + // } + // + // // FIXME: downcast to GLContextImpl undesirable + // impl1 = (GLContextImpl) olderContextOrNull; + // impl2 = (GLContextImpl) newContext; + // + // GLObjectTracker deletedObjectTracker = null; + // GLContextImpl shareImpl = (GLContextImpl) realShareContext; + // // Before we zap the "user-level" object trackers, make sure + // // that all contexts in the share set share the destroyed object + // // tracker + // if (shareImpl != null) { + // deletedObjectTracker = shareImpl.getDeletedObjectTracker(); + // } + // if (deletedObjectTracker == null) { + // // Must create one and possibly set it up in the older context + // deletedObjectTracker = new GLObjectTracker(); + // if (DEBUG) { + // System.err.println("Created deletedObjectTracker " + deletedObjectTracker + " because " + + // ((shareImpl == null) ? "shareImpl was null" : "shareImpl's (" + shareImpl + ") deletedObjectTracker was null")); + // } + // + // if (shareImpl != null) { + // // FIXME: think should really assert in this case + // shareImpl.setDeletedObjectTracker(deletedObjectTracker); + // if (DEBUG) { + // System.err.println("Set deletedObjectTracker " + deletedObjectTracker + " in shareImpl context " + shareImpl); + // } + // } + // } + // impl2.setDeletedObjectTracker(deletedObjectTracker); + // if (DEBUG) { + // System.err.println("Set deletedObjectTracker " + deletedObjectTracker + " in impl2 context " + impl2); + // } + // } + // + // // Must not hold lock around this operation + // // Don't share object trackers with the primordial share context from Java2D + // if (Java2D.isOGLPipelineActive()) { + // // FIXME: probably need to do something different here + // // Need to be able to figure out the GraphicsDevice for the + // // older context if it's on-screen + // GraphicsDevice device = GraphicsEnvironment. + // getLocalGraphicsEnvironment(). + // getDefaultScreenDevice(); + // GLContext j2dShareContext = Java2D.getShareContext(device); + // if (impl1 != null && impl1 == j2dShareContext) { + // impl1 = null; + // } + // } + // + // synchronized (GLContextShareSet.class) { + // if (impl1 != null) { + // tracker = impl1.getObjectTracker(); + // assert (tracker != null) + // : "registerForObjectTracking was not called properly for the older context"; + // } + // if (tracker == null) { + // tracker = new GLObjectTracker(); + // } + // // Note that we don't assert that the tracker is non-null for + // // impl2 because the way we use this functionality we actually + // // overwrite the initially-set object tracker in the new context + // impl2.setObjectTracker(tracker); + // } + // } + // } + + //---------------------------------------------------------------------- + // Internals only below this point + + + private static ShareSet entryFor(GLContext context) { + return (ShareSet) shareMap.get(context); + } + + private static void addEntry(GLContext context, ShareSet share) { + if (shareMap.get(context) == null) { + shareMap.put(context, share); + } + } + + // FIXME: refactor Java SE dependencies + // private static boolean isObjectTrackingEnabled() { + // return ((Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled()) || + // isObjectTrackingDebuggingEnabled()); + // } + // + // private static boolean isObjectTrackingDebuggingEnabled() { + // return forceTracking; + // } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java new file mode 100644 index 000000000..cdf5beb24 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java @@ -0,0 +1,397 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.nio.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.common.util.*; +import com.jogamp.gluegen.runtime.*; +import java.lang.reflect.*; + +/** Extends GLDrawableFactory with a few methods for handling + typically software-accelerated offscreen rendering (Device + Independent Bitmaps on Windows, pixmaps on X11). Direct access to + these GLDrawables is not supplied directly to end users, though + they may be instantiated by the GLJPanel implementation. */ +public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { + protected static final boolean DEBUG = Debug.debug("GLDrawableFactory"); + + private boolean isValid = false; + + public void shutdown() { + validate(); + isValid = false; + } + + protected final void validate() { + if(!isValid) { + throw new GLException("GLDrawableFactory is already shutdown!"); + } + } + + //--------------------------------------------------------------------------- + // Dispatching GLDrawable construction in respect to the NativeWindow Capabilities + // + public GLDrawable createGLDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities caps = (GLCapabilities) target.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + GLDrawable result = null; + if(caps.isOnscreen()) { + if(DEBUG) { + System.out.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable: "+target); + } + result = createOnscreenDrawable(target); + } else { + if( ! ( target instanceof SurfaceChangeable ) ) { + throw new IllegalArgumentException("Passed NativeWindow must implement SurfaceChangeable for offscreen: "+target); + } + if(caps.isPBuffer()) { + if(DEBUG) { + System.out.println("GLDrawableFactoryImpl.createGLDrawable -> PbufferDrawable: "+target); + } + result = createGLPbufferDrawable(target); + } + if(null==result) { + if(DEBUG) { + System.out.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable: "+target); + } + result = createOffscreenDrawable(target); + } + } + if(DEBUG) { + System.out.println("GLDrawableFactoryImpl.createGLDrawable: "+result); + } + return result; + } + + //--------------------------------------------------------------------------- + // + // Onscreen GLDrawable construction + // + + protected abstract GLDrawableImpl createOnscreenDrawable(NativeWindow target); + + //--------------------------------------------------------------------------- + // + // PBuffer GLDrawable construction + // + + /** Target must implement SurfaceChangeable */ + protected abstract GLDrawableImpl createGLPbufferDrawableImpl(NativeWindow target); + + protected GLDrawableImpl createGLPbufferDrawable(NativeWindow target) { + if (!canCreateGLPbuffer(target.getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice())) { + throw new GLException("Pbuffer support not available with current graphics card"); + } + return createGLPbufferDrawableImpl(target); + } + + public GLDrawable createGLPbufferDrawable(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + int width, + int height) { + validate(); + if(height<=0 || height<=0) { + throw new GLException("Width and height of pbuffer must be positive (were (" + + width + ", " + height + "))"); + } + capabilities.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN + capabilities.setOnscreen(false); + capabilities.setPBuffer(true); + return createGLPbufferDrawable( createOffscreenWindow(capabilities, chooser, height, height) ); + } + + public GLPbuffer createGLPbuffer(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + int width, + int height, + GLContext shareWith) { + validate(); + return new GLPbufferImpl( (GLDrawableImpl) createGLPbufferDrawable(capabilities, chooser, height, height), + shareWith); + } + + + //--------------------------------------------------------------------------- + // + // Offscreen GLDrawable construction + // + + protected abstract GLDrawableImpl createOffscreenDrawable(NativeWindow target) ; + + public GLDrawable createOffscreenDrawable(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + int width, + int height) { + validate(); + if(width<=0 || height<=0) { + throw new GLException("Width and height of pbuffer must be positive (were (" + + width + ", " + height + "))"); + } + capabilities.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN + capabilities.setOnscreen(false); + capabilities.setPBuffer(false); + return createOffscreenDrawable( createOffscreenWindow(capabilities, chooser, width, height) ); + } + + /** + * creates an offscreen NativeWindow, which must implement SurfaceChangeable as well, + * so the windowing system related implementation is able to set the surface handle. + */ + protected abstract NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, + int width, int height); + + protected abstract GLDrawableImpl getSharedDrawable(); + protected abstract GLContextImpl getSharedContext(); + + protected GLDrawableFactoryImpl() { + super(); + isValid = true; + } + + protected void maybeDoSingleThreadedWorkaround(Runnable action) { + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + Threading.invokeOnOpenGLThread(action); + } else { + action.run(); + } + } + + /** + * Returns the sole GLDrawableFactoryImpl instance. + * + * @param glProfile GLProfile to determine the factory type, ie EGLDrawableFactory, + * or one of the native GLDrawableFactory's, ie X11/GLX, Windows/WGL or MacOSX/CGL. + */ + public static GLDrawableFactoryImpl getFactoryImpl(GLProfile glp) { + return (GLDrawableFactoryImpl) getFactory(glp); + } + + // Helper function for more lazily loading the GLU library; + // apparently can't use System.loadLibrary on UNIX because it uses + // RTLD_LOCAL and we need to call dlsym(RTLD_DEFAULT) + public abstract void loadGLULibrary(); + + //---------------------------------------------------------------------- + // Support for locking and unlocking the toolkit -- needed only on X11 platforms + // + + public void lockToolkit() { + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + } + + public void unlockToolkit() { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + + //--------------------------------------------------------------------------- + // Support for Java2D/JOGL bridge on Mac OS X; the external + // GLDrawable mechanism in the public API is sufficient to + // implement this functionality on all other platforms + // + + public abstract boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device); + + public abstract GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException; + + //---------------------------------------------------------------------- + // Gamma adjustment support + // Thanks to the LWJGL team for illustrating how to make these + // adjustments on various OSs. + + /* + * Portions Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /** + * Sets the gamma, brightness, and contrast of the current main + * display. Returns true if the settings were changed, false if + * not. If this method returns true, the display settings will + * automatically be reset upon JVM exit (assuming the JVM does not + * crash); if the user wishes to change the display settings back to + * normal ahead of time, use resetDisplayGamma(). Throws + * IllegalArgumentException if any of the parameters were + * out-of-bounds. + * + * @param gamma The gamma value, typically > 1.0 (default value is + * 1.0) + * @param brightness The brightness value between -1.0 and 1.0, + * inclusive (default value is 0) + * @param contrast The contrast, greater than 0.0 (default value is 1) + * @throws IllegalArgumentException if any of the parameters were + * out-of-bounds + */ + public boolean setDisplayGamma(float gamma, float brightness, float contrast) throws IllegalArgumentException { + validate(); + if ((brightness < -1.0f) || (brightness > 1.0f)) { + throw new IllegalArgumentException("Brightness must be between -1.0 and 1.0"); + } + if (contrast < 0) { + throw new IllegalArgumentException("Contrast must be greater than 0.0"); + } + // FIXME: ensure gamma is > 1.0? Are smaller / negative values legal? + int rampLength = getGammaRampLength(); + if (rampLength == 0) { + return false; + } + float[] gammaRamp = new float[rampLength]; + for (int i = 0; i < rampLength; i++) { + float intensity = (float) i / (float) (rampLength - 1); + // apply gamma + float rampEntry = (float) java.lang.Math.pow(intensity, gamma); + // apply brightness + rampEntry += brightness; + // apply contrast + rampEntry = (rampEntry - 0.5f) * contrast + 0.5f; + // Clamp entry to [0, 1] + if (rampEntry > 1.0f) + rampEntry = 1.0f; + else if (rampEntry < 0.0f) + rampEntry = 0.0f; + gammaRamp[i] = rampEntry; + } + registerGammaShutdownHook(); + return setGammaRamp(gammaRamp); + } + + public synchronized void resetDisplayGamma() { + validate(); + if (gammaShutdownHook == null) { + throw new IllegalArgumentException("Should not call this unless setDisplayGamma called first"); + } + resetGammaRamp(originalGammaRamp); + unregisterGammaShutdownHook(); + } + + //------------------------------------------------------ + // Gamma-related methods to be implemented by subclasses + // + + /** Returns the length of the computed gamma ramp for this OS and + hardware. Returns 0 if gamma changes are not supported. */ + protected int getGammaRampLength() { + return 0; + } + + /** Sets the gamma ramp for the main screen. Returns false if gamma + ramp changes were not supported. */ + protected boolean setGammaRamp(float[] ramp) { + return false; + } + + /** Gets the current gamma ramp. This is basically an opaque value + used only on some platforms to reset the gamma ramp to its + original settings. */ + protected Buffer getGammaRamp() { + return null; + } + + /** Resets the gamma ramp, potentially using the specified Buffer as + data to restore the original values. */ + protected void resetGammaRamp(Buffer originalGammaRamp) { + } + + // Shutdown hook mechanism for resetting gamma + private boolean gammaShutdownHookRegistered; + private Thread gammaShutdownHook; + private Buffer originalGammaRamp; + private synchronized void registerGammaShutdownHook() { + if (gammaShutdownHookRegistered) + return; + if (gammaShutdownHook == null) { + gammaShutdownHook = new Thread(new Runnable() { + public void run() { + synchronized (GLDrawableFactoryImpl.this) { + resetGammaRamp(originalGammaRamp); + } + } + }); + originalGammaRamp = getGammaRamp(); + } + Runtime.getRuntime().addShutdownHook(gammaShutdownHook); + gammaShutdownHookRegistered = true; + } + + private synchronized void unregisterGammaShutdownHook() { + if (!gammaShutdownHookRegistered) + return; + if (gammaShutdownHook == null) { + throw new InternalError("Error in gamma shutdown hook logic"); + } + Runtime.getRuntime().removeShutdownHook(gammaShutdownHook); + gammaShutdownHookRegistered = false; + // Leave the original gamma ramp data alone + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java new file mode 100644 index 000000000..7a4e84081 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java @@ -0,0 +1,180 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.util.*; +import javax.media.opengl.*; + +/** Encapsulates the implementation of most of the GLAutoDrawable's + methods to be able to share it between GLCanvas and GLJPanel. */ + +public class GLDrawableHelper { + private volatile List listeners = new ArrayList(); + private static final boolean DEBUG = Debug.debug("GLDrawableHelper"); + private static final boolean VERBOSE = Debug.verbose(); + private static final boolean NVIDIA_CRASH_WORKAROUND = Debug.isPropertyDefined("jogl.nvidia.crash.workaround", true); + private boolean autoSwapBufferMode = true; + + public GLDrawableHelper() { + } + + public synchronized String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("GLEventListeners num "+listeners.size()+" ["); + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + sb.append(iter.next()+", "); + } + sb.append("]"); + return sb.toString(); + } + + public synchronized void addGLEventListener(GLEventListener listener) { + List newListeners = (List) ((ArrayList) listeners).clone(); + newListeners.add(listener); + listeners = newListeners; + } + + public synchronized void removeGLEventListener(GLEventListener listener) { + List newListeners = (List) ((ArrayList) listeners).clone(); + newListeners.remove(listener); + listeners = newListeners; + } + + public synchronized void dispose(GLAutoDrawable drawable) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + ((GLEventListener) iter.next()).dispose(drawable); + } + } + + public void init(GLAutoDrawable drawable) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + ((GLEventListener) iter.next()).init(drawable); + } + } + + public void display(GLAutoDrawable drawable) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + ((GLEventListener) iter.next()).display(drawable); + } + } + + public void reshape(GLAutoDrawable drawable, + int x, int y, int width, int height) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + ((GLEventListener) iter.next()).reshape(drawable, x, y, width, height); + } + } + + public void setAutoSwapBufferMode(boolean onOrOff) { + autoSwapBufferMode = onOrOff; + } + + public boolean getAutoSwapBufferMode() { + return autoSwapBufferMode; + } + + private static final ThreadLocal perThreadInitAction = new ThreadLocal(); + /** Principal helper method which runs a Runnable with the context + made current. This could have been made part of GLContext, but a + desired goal is to be able to implement the GLCanvas in terms of + the GLContext's public APIs, and putting it into a separate + class helps ensure that we don't inadvertently use private + methods of the GLContext or its implementing classes. */ + public void invokeGL(GLDrawable drawable, + GLContext context, + Runnable runnable, + Runnable initAction) { + if(null==context) { + if (DEBUG) { + Exception e = new GLException(Thread.currentThread().getName()+" GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); + e.printStackTrace(); + } + return; + } + // Support for recursive makeCurrent() calls as well as calling + // other drawables' display() methods from within another one's + GLContext lastContext = GLContext.getCurrent(); + Runnable lastInitAction = (Runnable) perThreadInitAction.get(); + if (lastContext != null) { + lastContext.release(); + } + + int res = 0; + try { + res = context.makeCurrent(); + if (res != GLContext.CONTEXT_NOT_CURRENT) { + if(null!=initAction) { + perThreadInitAction.set(initAction); + if (res == GLContext.CONTEXT_CURRENT_NEW) { + if (DEBUG) { + System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); + } + initAction.run(); + } + } + if(null!=runnable) { + if (DEBUG && VERBOSE) { + System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running runnable"); + } + runnable.run(); + if (autoSwapBufferMode) { + if (drawable != null) { + drawable.swapBuffers(); + } + } + } + } + } finally { + try { + if (res != GLContext.CONTEXT_NOT_CURRENT) { + context.release(); + } + } catch (Exception e) { + } + if (lastContext != null) { + int res2 = lastContext.makeCurrent(); + if (res2 == GLContext.CONTEXT_CURRENT_NEW) { + lastInitAction.run(); + } + } + } + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java new file mode 100644 index 000000000..2fef8fd80 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java @@ -0,0 +1,177 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import com.jogamp.common.os.DynamicLookupHelper; +import javax.media.nativewindow.*; +import javax.media.opengl.*; + +public abstract class GLDrawableImpl implements GLDrawable { + protected static final boolean DEBUG = Debug.debug("GLDrawable"); + + protected GLDrawableImpl(GLDrawableFactory factory, + NativeWindow comp, + boolean realized) { + this.factory = factory; + this.component = comp; + this.realized = realized; + this.requestedCapabilities = (GLCapabilities)component.getGraphicsConfiguration().getNativeGraphicsConfiguration().getRequestedCapabilities(); // a copy .. + } + + /** + * Returns the DynamicLookupHelper + */ + public abstract DynamicLookupHelper getDynamicLookupHelper(); + + public GLDrawableFactoryImpl getFactoryImpl() { + return (GLDrawableFactoryImpl) getFactory(); + } + + /** For offscreen GLDrawables (pbuffers and "pixmap" drawables), + indicates that native resources should be reclaimed. */ + public void destroy() { + throw new GLException("Should not call this (should only be called for offscreen GLDrawables)"); + } + + public void swapBuffers() throws GLException { + GLCapabilities caps = (GLCapabilities)component.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + if ( caps.getDoubleBuffered() ) { + if(!component.surfaceSwap()) { + swapBuffersImpl(); + } + } else { + GLContext ctx = GLContext.getCurrent(); + if(null!=ctx && ctx.getGLDrawable()==this) { + ctx.getGL().glFinish(); + } + } + component.surfaceUpdated(this, component, System.currentTimeMillis()); + } + + protected abstract void swapBuffersImpl(); + + public static String toHexString(long hex) { + return "0x" + Long.toHexString(hex); + } + + public GLProfile getGLProfile() { + return requestedCapabilities.getGLProfile(); + } + + public GLCapabilities getChosenGLCapabilities() { + return (GLCapabilities)component.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); // a copy + } + + public GLCapabilities getRequestedGLCapabilities() { + return requestedCapabilities; + } + + public NativeWindow getNativeWindow() { + return component; + } + + public GLDrawableFactory getFactory() { + return factory; + } + + public void setRealized(boolean realized) { + if ( this.realized != realized ) { + if(DEBUG) { + System.err.println("setRealized: "+getClass().getName()+" "+this.realized+" -> "+realized); + } + this.realized = realized; + setRealizedImpl(); + } else if(DEBUG) { + System.err.println("setRealized: "+getClass().getName()+" "+this.realized+" == "+realized); + } + } + protected abstract void setRealizedImpl(); + + public boolean getRealized() { + return realized; + } + + public int getWidth() { + return component.getWidth(); + } + + /** Returns the current height of this GLDrawable. */ + public int getHeight() { + return component.getHeight(); + } + + public int lockSurface() throws GLException { + if (!realized) { + return NativeWindow.LOCK_SURFACE_NOT_READY; + } + return component.lockSurface(); + } + + public void unlockSurface() { + component.unlockSurface(); + } + + public boolean isSurfaceLocked() { + return component.isSurfaceLocked(); + } + + public String toString() { + return getClass().getName()+"[Realized "+getRealized()+ + ",\n\tFactory "+getFactory()+ + ",\n\tWindow "+getNativeWindow()+"]"; + } + + protected GLDrawableFactory factory; + protected NativeWindow component; + protected GLCapabilities requestedCapabilities; + + // Indicates whether the component (if an onscreen context) has been + // realized. Plausibly, before the component is realized the JAWT + // should return an error or NULL object from some of its + // operations; this appears to be the case on Win32 but is not true + // at least with Sun's current X11 implementation (1.4.x), which + // crashes with no other error reported if the DrawingSurfaceInfo is + // fetched from a locked DrawingSurface during the validation as a + // result of calling show() on the main thread. To work around this + // we prevent any JAWT or OpenGL operations from being done until + // addNotify() is called on the component. + protected boolean realized; + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java b/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java new file mode 100644 index 000000000..c3958eedf --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java @@ -0,0 +1,109 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +// FIXME: refactor Java SE dependencies +//import java.awt.Toolkit; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.HashSet; +import com.jogamp.common.jvm.JNILibLoaderBase; + +public class GLJNILibLoader extends JNILibLoaderBase { + public static void loadNEWT() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("newt", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadGLDesktop() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("jogl_desktop", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadGLDesktopES12() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("jogl_gl2es12", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadES2() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("jogl_es2", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadES1() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("jogl_es1", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadCgImpl() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String[] preload = { "nativewindow", "cg", "cgGL" }; + loadLibrary("jogl_cg", preload, true); + return null; + } + }); + } + + private static final String[] nativeOSPreload = { "nativewindow_x11" }; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java new file mode 100644 index 000000000..dd8d980a6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java @@ -0,0 +1,320 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +/** +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.event.*; +import java.beans.PropertyChangeListener; + */ + +import javax.media.nativewindow.*; +import javax.media.opengl.*; + +/** Platform-independent class exposing pbuffer functionality to + applications. This class is not exposed in the public API as it + would probably add no value; however it implements the GLDrawable + interface so can be interacted with via its display() method. */ + +public class GLPbufferImpl implements GLPbuffer { + private GLDrawableImpl pbufferDrawable; + private GLContextImpl context; + private GLDrawableHelper drawableHelper = new GLDrawableHelper(); + private int floatMode; + + public GLPbufferImpl(GLDrawableImpl pbufferDrawable, + GLContext parentContext) { + GLCapabilities caps = (GLCapabilities) + pbufferDrawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + if(caps.isOnscreen()) { + if(caps.isPBuffer()) { + throw new IllegalArgumentException("Error: Given drawable is Onscreen and Pbuffer: "+pbufferDrawable); + } + throw new IllegalArgumentException("Error: Given drawable is Onscreen: "+pbufferDrawable); + } else { + if(!caps.isPBuffer()) { + throw new IllegalArgumentException("Error: Given drawable is not Pbuffer: "+pbufferDrawable); + } + } + this.pbufferDrawable = pbufferDrawable; + context = (GLContextImpl) pbufferDrawable.createContext(parentContext); + context.setSynchronized(true); + } + + public GLContext createContext(GLContext shareWith) { + return pbufferDrawable.createContext(shareWith); + } + + public void setRealized(boolean realized) { + } + + public void setSize(int width, int height) { + // FIXME + throw new GLException("Not yet implemented"); + } + + public NativeWindow getNativeWindow() { + return pbufferDrawable.getNativeWindow(); + } + + public GLDrawableFactory getFactory() { + return pbufferDrawable.getFactory(); + } + + public int getWidth() { + return pbufferDrawable.getWidth(); + } + + public int getHeight() { + return pbufferDrawable.getHeight(); + } + + public void display() { + maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction, + displayAction, + false); + } + + public void repaint() { + display(); + } + + public void addGLEventListener(GLEventListener listener) { + drawableHelper.addGLEventListener(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + drawableHelper.removeGLEventListener(listener); + } + + public void setContext(GLContext ctx) { + context=(GLContextImpl)ctx; + } + + public GLContext getContext() { + return context; + } + + public GLDrawable getDrawable() { + return pbufferDrawable; + } + + public GL getGL() { + return getContext().getGL(); + } + + public GL setGL(GL gl) { + return getContext().setGL(gl); + } + + public void setAutoSwapBufferMode(boolean onOrOff) { + drawableHelper.setAutoSwapBufferMode(onOrOff); + } + + public boolean getAutoSwapBufferMode() { + return drawableHelper.getAutoSwapBufferMode(); + } + + public void swapBuffers() { + maybeDoSingleThreadedWorkaround(swapBuffersOnEventDispatchThreadAction, swapBuffersAction, false); + } + + public void bindTexture() { + // Doesn't make much sense to try to do this on the event dispatch + // thread given that it has to be called while the context is current + context.bindPbufferToTexture(); + } + + public void releaseTexture() { + // Doesn't make much sense to try to do this on the event dispatch + // thread given that it has to be called while the context is current + context.releasePbufferFromTexture(); + } + + public GLCapabilities getChosenGLCapabilities() { + if (pbufferDrawable == null) + return null; + + return pbufferDrawable.getChosenGLCapabilities(); + } + + public GLCapabilities getRequestedGLCapabilities() { + if (pbufferDrawable == null) + return null; + + return pbufferDrawable.getRequestedGLCapabilities(); + } + + public GLProfile getGLProfile() { + if (pbufferDrawable == null) + return null; + + return pbufferDrawable.getGLProfile(); + } + + private boolean surfaceLocked = false; + + public int lockSurface() throws GLException { + surfaceLocked=true; + return NativeWindow.LOCK_SUCCESS; + } + + public void unlockSurface() { + surfaceLocked=false; + } + + public boolean isSurfaceLocked() { + return surfaceLocked; + } + + //---------------------------------------------------------------------- + // No-ops for ComponentEvents + // + + /* + public void addComponentListener(ComponentListener l) {} + public void removeComponentListener(ComponentListener l) {} + public void addFocusListener(FocusListener l) {} + public void removeFocusListener(FocusListener l) {} + public void addHierarchyBoundsListener(HierarchyBoundsListener l) {} + public void removeHierarchyBoundsListener(HierarchyBoundsListener l) {} + public void addHierarchyListener(HierarchyListener l) {} + public void removeHierarchyListener(HierarchyListener l) {} + public void addInputMethodListener(InputMethodListener l) {} + public void removeInputMethodListener(InputMethodListener l) {} + public void addKeyListener(KeyListener l) {} + public void removeKeyListener(KeyListener l) {} + public void addMouseListener(MouseListener l) {} + public void removeMouseListener(MouseListener l) {} + public void addMouseMotionListener(MouseMotionListener l) {} + public void removeMouseMotionListener(MouseMotionListener l) {} + public void addMouseWheelListener(MouseWheelListener l) {} + public void removeMouseWheelListener(MouseWheelListener l) {} + public void addPropertyChangeListener(PropertyChangeListener listener) {} + public void removePropertyChangeListener(PropertyChangeListener listener) {} + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) {} + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) {} + */ + + public void destroy() { + // FIXME: not calling event listeners .. see GLAutoDrawable spec + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + Threading.invokeOnOpenGLThread(destroyAction); + } else { + destroyAction.run(); + } + } + + public int getFloatingPointMode() { + if (floatMode == 0) { + throw new GLException("Pbuffer not initialized, or floating-point support not requested"); + } + return floatMode; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void maybeDoSingleThreadedWorkaround(Runnable eventDispatchThreadAction, + Runnable invokeGLAction, + boolean isReshape) { + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + Threading.invokeOnOpenGLThread(eventDispatchThreadAction); + } else { + drawableHelper.invokeGL(pbufferDrawable, context, invokeGLAction, initAction); + } + } + + class InitAction implements Runnable { + public void run() { + floatMode = context.getFloatingPointMode(); + drawableHelper.init(GLPbufferImpl.this); + } + } + private InitAction initAction = new InitAction(); + + class DisplayAction implements Runnable { + public void run() { + drawableHelper.display(GLPbufferImpl.this); + } + } + private DisplayAction displayAction = new DisplayAction(); + + class SwapBuffersAction implements Runnable { + public void run() { + pbufferDrawable.swapBuffers(); + } + } + private SwapBuffersAction swapBuffersAction = new SwapBuffersAction(); + + // Workaround for ATI driver bugs related to multithreading issues + // like simultaneous rendering via Animators to canvases that are + // being resized on the AWT event dispatch thread + class DisplayOnEventDispatchThreadAction implements Runnable { + public void run() { + drawableHelper.invokeGL(pbufferDrawable, context, displayAction, initAction); + } + } + private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction = + new DisplayOnEventDispatchThreadAction(); + class SwapBuffersOnEventDispatchThreadAction implements Runnable { + public void run() { + drawableHelper.invokeGL(pbufferDrawable, context, swapBuffersAction, initAction); + } + } + private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction = + new SwapBuffersOnEventDispatchThreadAction(); + + class DestroyAction implements Runnable { + public void run() { + if (null != context) { + context.destroy(); + } + pbufferDrawable.destroy(); + } + } + private DestroyAction destroyAction = new DestroyAction(); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLStateTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/GLStateTracker.java new file mode 100755 index 000000000..744e7b924 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLStateTracker.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2006 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.util.*; +import javax.media.opengl.*; + +/** + * Tracks as closely as possible OpenGL states. + * GLStateTracker objects are allocated on a per-OpenGL-context basis. + * <p> + * Currently supported states: PixelStorei + */ + +public class GLStateTracker { + private static final boolean DEBUG = Debug.debug("GLStateTracker"); + + private volatile boolean enabled = true; + + private Map/*<Integer,Integer>*/ pixelStateMap = new HashMap/*<Integer,Integer>*/(); + + static class SavedState { + SavedState() { + this.pixelStateMap = null; + } + void putPixelStateMap(Map pixelStateMap) { + this.pixelStateMap = new HashMap(); + this.pixelStateMap.putAll(pixelStateMap); + } + Map getPixelStateMap() { return pixelStateMap; } + + private Map pixelStateMap; + // private Map otherStateMap; + } + private List/*<SavedState>*/ stack = new ArrayList(); + + public GLStateTracker() { + resetStates(); + } + + public void clearStates(boolean enable) { + enabled = enable; + pixelStateMap.clear(); + } + + public void setEnabled(boolean on) { + enabled = on; + } + + public boolean isEnabled() { + return enabled; + } + + public boolean getInt(int pname, int[] params, int params_offset) { + if(enabled) { + Integer key = boxKey(pname); + if(null!=key) { + Integer value = (Integer) pixelStateMap.get(key); + if(null!=value) { + params[params_offset] = value.intValue(); + } else { + GLException re = new GLException("Key (0x"+Integer.toHexString(key.intValue())+") is not mapped"); + throw re; + } + return true; + } + } + return false; + } + + public boolean getInt(int pname, java.nio.IntBuffer params, int dummy) { + if(enabled) { + Integer key = boxKey(pname); + if(null!=key) { + Integer value = (Integer) pixelStateMap.get(key); + if(null!=value) { + params.put(params.position(), value.intValue()); + } else { + GLException re = new GLException("Key (0x"+Integer.toHexString(key.intValue())+") is not mapped"); + throw re; + } + return true; + } + } + return false; + } + + public void setInt(int pname, int param) { + if(enabled) { + Integer key = boxKey(pname); + if(null!=key) { + pixelStateMap.put(key, boxInt(param)); + } + } + } + + public void pushAttrib(int flags) { + if(enabled) { + SavedState state = new SavedState(); + if( 0 != (flags&GL2.GL_CLIENT_PIXEL_STORE_BIT) ) { + state.putPixelStateMap(pixelStateMap); + } + stack.add(0, state); + } + } + + public void popAttrib() { + if(enabled) { + if(stack.size()==0) { + throw new GLException("stack contains no elements"); + } + SavedState state = (SavedState) stack.remove(0); + if(null==state) { + throw new GLException("null stack element (remaining stack size "+stack.size()+")"); + } + + Map/*<Integer,Integer>*/ pixelStateMapNew = new HashMap/*<Integer,Integer>*/(); + if ( null != state.getPixelStateMap() ) { + pixelStateMapNew.putAll(state.getPixelStateMap()); + } + pixelStateMap = pixelStateMapNew; + } + } + + private static final Integer GL_PACK_SWAP_BYTES = new Integer(GL2GL3.GL_PACK_SWAP_BYTES); + private static final Integer GL_PACK_LSB_FIRST = new Integer(GL2GL3.GL_PACK_LSB_FIRST); + private static final Integer GL_PACK_ROW_LENGTH = new Integer(GL2GL3.GL_PACK_ROW_LENGTH); + private static final Integer GL_PACK_SKIP_ROWS = new Integer(GL2GL3.GL_PACK_SKIP_ROWS); + private static final Integer GL_PACK_SKIP_PIXELS = new Integer(GL2GL3.GL_PACK_SKIP_PIXELS); + private static final Integer GL_PACK_ALIGNMENT = new Integer(GL.GL_PACK_ALIGNMENT); + private static final Integer GL_PACK_IMAGE_HEIGHT = new Integer(GL2GL3.GL_PACK_IMAGE_HEIGHT); + private static final Integer GL_PACK_SKIP_IMAGES = new Integer(GL2GL3.GL_PACK_SKIP_IMAGES); + + private static final Integer GL_UNPACK_SWAP_BYTES = new Integer(GL2GL3.GL_UNPACK_SWAP_BYTES); + private static final Integer GL_UNPACK_LSB_FIRST = new Integer(GL2GL3.GL_UNPACK_LSB_FIRST); + private static final Integer GL_UNPACK_ROW_LENGTH = new Integer(GL2GL3.GL_UNPACK_ROW_LENGTH); + private static final Integer GL_UNPACK_SKIP_ROWS = new Integer(GL2GL3.GL_UNPACK_SKIP_ROWS); + private static final Integer GL_UNPACK_SKIP_PIXELS = new Integer(GL2GL3.GL_UNPACK_SKIP_PIXELS); + private static final Integer GL_UNPACK_ALIGNMENT = new Integer(GL.GL_UNPACK_ALIGNMENT); + private static final Integer GL_UNPACK_IMAGE_HEIGHT = new Integer(GL2GL3.GL_UNPACK_IMAGE_HEIGHT); + private static final Integer GL_UNPACK_SKIP_IMAGES = new Integer(GL2GL3.GL_UNPACK_SKIP_IMAGES); + + private static final Integer zero = new Integer(0); + private static final Integer one = new Integer(1); + + private static Integer boxKey(int key) { + switch (key) { + case 0: return zero; + case GL2GL3.GL_PACK_SWAP_BYTES: return GL_PACK_SWAP_BYTES; + case GL2GL3.GL_PACK_LSB_FIRST: return GL_PACK_LSB_FIRST; + case GL2GL3.GL_PACK_ROW_LENGTH: return GL_PACK_ROW_LENGTH; + case GL2GL3.GL_PACK_SKIP_ROWS: return GL_PACK_SKIP_ROWS; + case GL2GL3.GL_PACK_SKIP_PIXELS: return GL_PACK_SKIP_PIXELS; + case GL.GL_PACK_ALIGNMENT: return GL_PACK_ALIGNMENT; + case GL2GL3.GL_PACK_IMAGE_HEIGHT: return GL_PACK_IMAGE_HEIGHT; + case GL2GL3.GL_PACK_SKIP_IMAGES: return GL_PACK_SKIP_IMAGES; + + case GL2GL3.GL_UNPACK_SWAP_BYTES: return GL_UNPACK_SWAP_BYTES; + case GL2GL3.GL_UNPACK_LSB_FIRST: return GL_UNPACK_LSB_FIRST; + case GL2GL3.GL_UNPACK_ROW_LENGTH: return GL_UNPACK_ROW_LENGTH; + case GL2GL3.GL_UNPACK_SKIP_ROWS: return GL_UNPACK_SKIP_ROWS; + case GL2GL3.GL_UNPACK_SKIP_PIXELS: return GL_UNPACK_SKIP_PIXELS; + case GL.GL_UNPACK_ALIGNMENT: return GL_UNPACK_ALIGNMENT; + case GL2GL3.GL_UNPACK_IMAGE_HEIGHT: return GL_UNPACK_IMAGE_HEIGHT; + case GL2GL3.GL_UNPACK_SKIP_IMAGES: return GL_UNPACK_SKIP_IMAGES; + + default: return null; + } + } + + public void resetStates() { + pixelStateMap.clear(); + + pixelStateMap.put(GL_PACK_SWAP_BYTES, zero /* GL_FALSE */); + pixelStateMap.put(GL_PACK_LSB_FIRST, zero /* GL_FALSE */); + pixelStateMap.put(GL_PACK_ROW_LENGTH, zero); + pixelStateMap.put(GL_PACK_SKIP_ROWS, zero); + pixelStateMap.put(GL_PACK_SKIP_PIXELS, zero); + pixelStateMap.put(GL_PACK_ALIGNMENT, new Integer(4)); + pixelStateMap.put(GL_PACK_IMAGE_HEIGHT, zero); + pixelStateMap.put(GL_PACK_SKIP_IMAGES, zero); + + pixelStateMap.put(GL_UNPACK_SWAP_BYTES, zero /* GL_FALSE */); + pixelStateMap.put(GL_UNPACK_LSB_FIRST, zero /* GL_FALSE */); + pixelStateMap.put(GL_UNPACK_ROW_LENGTH, zero); + pixelStateMap.put(GL_UNPACK_SKIP_ROWS, zero); + pixelStateMap.put(GL_UNPACK_SKIP_PIXELS, zero); + pixelStateMap.put(GL_UNPACK_ALIGNMENT, new Integer(4)); + pixelStateMap.put(GL_UNPACK_IMAGE_HEIGHT, zero); + pixelStateMap.put(GL_UNPACK_SKIP_IMAGES, zero); + } + + private static Integer boxInt(int value) { + switch (value) { + case 0: return zero; + case 1: return one; + + default: return new Integer(value); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLWorkerThread.java b/src/jogl/classes/com/jogamp/opengl/impl/GLWorkerThread.java new file mode 100755 index 000000000..768eea3f7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLWorkerThread.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2006 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.lang.reflect.InvocationTargetException; +import java.security.*; +import java.util.*; +import javax.media.opengl.*; + +/** Singleton thread upon which all OpenGL work is performed by + default. Unfortunately many vendors' OpenGL drivers are not really + thread-safe and stability is much improved by performing OpenGL + work on at most one thread. This is the default behavior of the + GLAutoDrawable implementations according to the {@link + javax.media.opengl.Threading Threading} class. The GLWorkerThread + replaces the original AWT event queue thread-based mechanism for + two reasons: first, more than one AWT event queue thread may be + spawned, for example if a dialog is being shown; second, it avoids + blocking the AWT event queue thread during OpenGL rendering. */ + +public class GLWorkerThread { + private static volatile boolean started; + private static volatile Thread thread; + private static Object lock; + private static volatile boolean shouldTerminate; + private static volatile Throwable exception; + + // The Runnable to execute immediately on the worker thread + private static volatile Runnable work; + // Queue of Runnables to be asynchronously invoked + private static List queue = new LinkedList(); + + /** Should only be called by Threading class if creation of the + GLWorkerThread was requested via the opengl.1thread system + property. */ + public static void start() { + if (!started) { + synchronized (GLWorkerThread.class) { + if (!started) { + lock = new Object(); + thread = new Thread(new WorkerRunnable(), + "JOGL GLWorkerThread"); + thread.setDaemon(true); + started = true; + synchronized (lock) { + thread.start(); + try { + lock.wait(); + } catch (InterruptedException e) { + } + } + + /* + + // Note: it appears that there is a bug in NVidia's current + // drivers where if a context was ever made current on a + // given thread and that thread has exited before program + // exit, a crash occurs in the drivers. Releasing the + // context from the given thread does not work around the + // problem. + // + // For the time being, we're going to work around this + // problem by not terminating the GLWorkerThread. In theory, + // shutting down the GLWorkerThread cleanly could be a good + // general solution to the problem of needing to + // cooperatively terminate all Animators at program exit. + // + // It appears that this doesn't even work around all of the + // kinds of crashes. Causing the context to be unilaterally + // released from the GLWorkerThread after each invocation + // seems to work around all of the kinds of crashes seen. + // + // These appear to be similar to the kinds of crashes seen + // when the Java2D/OpenGL pipeline terminates, and those are + // a known issue being fixed, so presumably these will be + // fixed in NVidia's next driver set. + + // Install shutdown hook to terminate daemon thread more or + // less cooperatively + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + Object lockTemp = lock; + if (lockTemp == null) { + // Already terminating (?) + return; + } + synchronized (lockTemp) { + shouldTerminate = true; + lockTemp.notifyAll(); + try { + lockTemp.wait(500); + } catch (InterruptedException e) { + } + } + } + }); + return null; + } + }); + + */ + + } else { + throw new RuntimeException("Should not start GLWorkerThread twice"); + } + } + } + } + + public static void invokeAndWait(Runnable runnable) + throws InvocationTargetException, InterruptedException { + if (!started) { + throw new RuntimeException("May not invokeAndWait on worker thread without starting it first"); + } + + Object lockTemp = lock; + if (lockTemp == null) { + return; // Terminating + } + + synchronized (lockTemp) { + if (thread == null) { + // Terminating + return; + } + + work = runnable; + lockTemp.notifyAll(); + lockTemp.wait(); + if (exception != null) { + Throwable localException = exception; + exception = null; + throw new InvocationTargetException(localException); + } + } + } + + public static void invokeLater(Runnable runnable) { + if (!started) { + throw new RuntimeException("May not invokeLater on worker thread without starting it first"); + } + + Object lockTemp = lock; + if (lockTemp == null) { + return; // Terminating + } + + synchronized (lockTemp) { + if (thread == null) { + // Terminating + return; + } + + queue.add(runnable); + lockTemp.notifyAll(); + } + } + + /** Indicates whether the OpenGL worker thread was started, i.e., + whether it is currently in use. */ + public static boolean isStarted() { + return started; + } + + /** Indicates whether the current thread is the OpenGL worker + thread. */ + public static boolean isWorkerThread() { + return (Thread.currentThread() == thread); + } + + static class WorkerRunnable implements Runnable { + public void run() { + // Notify starting thread that we're ready + synchronized (lock) { + lock.notifyAll(); + } + + while (!shouldTerminate) { + synchronized (lock) { + while (!shouldTerminate && + (work == null) && + queue.isEmpty()) { + try { + // Avoid race conditions with wanting to release contexts on this thread + lock.wait(1000); + } catch (InterruptedException e) { + } + + if (GLContext.getCurrent() != null) { + // Test later to see whether we need to release this context + break; + } + } + + if (shouldTerminate) { + lock.notifyAll(); + thread = null; + lock = null; + return; + } + + if (work != null) { + try { + work.run(); + } catch (Throwable t) { + exception = t; + } finally { + work = null; + lock.notifyAll(); + } + } + + while (!queue.isEmpty()) { + try { + Runnable curAsync = (Runnable) queue.remove(0); + curAsync.run(); + } catch (Throwable t) { + System.out.println("Exception occurred on JOGL OpenGL worker thread:"); + t.printStackTrace(); + } + } + + // See about releasing current context + GLContext curContext = GLContext.getCurrent(); + if (curContext != null && + (curContext instanceof GLContextImpl)) { + GLContextImpl impl = (GLContextImpl) curContext; + if (impl.hasWaiters()) { + impl.release(); + } + } + } + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javame_cdc_fp b/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javame_cdc_fp new file mode 100644 index 000000000..4a0eaa22b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javame_cdc_fp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2009 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. + * + */ + +package com.jogamp.opengl.impl; + +import java.lang.reflect.*; +import java.nio.*; + +/** Internal copy of selected routines from BufferUtil to avoid + outward dependencies on com.jogamp.opengl.util package. */ +public class InternalBufferUtil { + public static final int SIZEOF_BYTE = 1; + public static final int SIZEOF_SHORT = 2; + public static final int SIZEOF_INT = 4; + public static final int SIZEOF_FLOAT = 4; + + //---------------------------------------------------------------------- + // Allocation routines + // + + /** Allocates a new direct ByteBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static ByteBuffer newByteBuffer(int numElements) { + ByteBuffer bb = ByteBuffer.allocateDirect(numElements); + nativeOrder(bb); + return bb; + } + + /** Allocates a new direct IntBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static IntBuffer newIntBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_INT); + return bb.asIntBuffer(); + } + + /** Allocates a new direct ShortBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static ShortBuffer newShortBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_SHORT); + return bb.asShortBuffer(); + } + + /** Allocates a new direct FloatBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static FloatBuffer newFloatBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_FLOAT); + return bb.asFloatBuffer(); + } + + //---------------------------------------------------------------------- + // Copy routines (type-to-type) + // + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed FloatBuffer + into a newly-allocated direct ByteBuffer. The returned buffer + will have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyFloatBufferAsByteBuffer(FloatBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_FLOAT); + dest.asFloatBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed IntBuffer into + a newly-allocated direct ByteBuffer. The returned buffer will + have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyIntBufferAsByteBuffer(IntBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_INT); + dest.asIntBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed ShortBuffer + into a newly-allocated direct ByteBuffer. The returned buffer + will have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyShortBufferAsByteBuffer(ShortBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_SHORT); + dest.asShortBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed ByteBuffer into + a newly-allocated direct ByteBuffer. The returned buffer will + have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyByteBuffer(ByteBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining()); + dest.put(orig); + dest.rewind(); + return dest; + } + + //---------------------------------------------------------------------- + // Conversion routines + // + + public static float[] getFloatArray(double[] source) { + int i=source.length; + float[] dest = new float[i--]; + while(i>=0) { dest[i]=(float)source[i]; i--; } + return dest; + } + + public static ByteBuffer nativeOrder(ByteBuffer buf) { + if (!isCDCFP) { + try { + if (byteOrderClass == null) { + byteOrderClass = Class.forName("java.nio.ByteOrder"); + orderMethod = ByteBuffer.class.getMethod("order", new Class[] { byteOrderClass }); + Method nativeOrderMethod = byteOrderClass.getMethod("nativeOrder", null); + nativeOrderObject = nativeOrderMethod.invoke(null, null); + } + } catch (Throwable t) { + // Must be running on CDC / FP + isCDCFP = true; + } + + if (!isCDCFP) { + try { + orderMethod.invoke(buf, new Object[] { nativeOrderObject }); + } catch (Throwable t) { + } + } + } + return buf; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // NOTE that this work must be done reflectively at the present time + // because this code must compile and run correctly on both CDC/FP and J2SE + private static boolean isCDCFP; + private static Class byteOrderClass; + private static Object nativeOrderObject; + private static Method orderMethod; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javase b/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javase new file mode 100644 index 000000000..655fa95de --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javase @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2009 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. + * + */ + +package com.jogamp.opengl.impl; + +import java.lang.reflect.*; +import java.nio.*; + +/** Internal copy of selected routines from BufferUtil to avoid + outward dependencies on com.jogamp.opengl.util package. */ +public class InternalBufferUtil { + public static final int SIZEOF_BYTE = 1; + public static final int SIZEOF_SHORT = 2; + public static final int SIZEOF_INT = 4; + public static final int SIZEOF_FLOAT = 4; + public static final int SIZEOF_LONG = 8; + public static final int SIZEOF_DOUBLE = 8; + + //---------------------------------------------------------------------- + // Allocation routines + // + + /** Allocates a new direct ByteBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static ByteBuffer newByteBuffer(int numElements) { + ByteBuffer bb = ByteBuffer.allocateDirect(numElements); + nativeOrder(bb); + return bb; + } + + /** Allocates a new direct DoubleBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static DoubleBuffer newDoubleBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_DOUBLE); + return bb.asDoubleBuffer(); + } + + /** Allocates a new direct IntBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static IntBuffer newIntBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_INT); + return bb.asIntBuffer(); + } + + /** Allocates a new direct ShortBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static ShortBuffer newShortBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_SHORT); + return bb.asShortBuffer(); + } + + /** Allocates a new direct FloatBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static FloatBuffer newFloatBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_FLOAT); + return bb.asFloatBuffer(); + } + + //---------------------------------------------------------------------- + // Copy routines (type-to-ByteBuffer) + // + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed FloatBuffer + into a newly-allocated direct ByteBuffer. The returned buffer + will have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyFloatBufferAsByteBuffer(FloatBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_FLOAT); + dest.asFloatBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed IntBuffer into + a newly-allocated direct ByteBuffer. The returned buffer will + have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyIntBufferAsByteBuffer(IntBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_INT); + dest.asIntBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed ShortBuffer + into a newly-allocated direct ByteBuffer. The returned buffer + will have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyShortBufferAsByteBuffer(ShortBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_SHORT); + dest.asShortBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed ByteBuffer into + a newly-allocated direct ByteBuffer. The returned buffer will + have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyByteBuffer(ByteBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining()); + dest.put(orig); + dest.rewind(); + return dest; + } + + //---------------------------------------------------------------------- + // Conversion routines + // + + public static float[] getFloatArray(double[] source) { + int i=source.length; + float[] dest = new float[i--]; + while(i>=0) { dest[i]=(float)source[i]; i--; } + return dest; + } + + public static ByteBuffer nativeOrder(ByteBuffer buf) { + if (!isCDCFP) { + try { + if (byteOrderClass == null) { + byteOrderClass = Class.forName("java.nio.ByteOrder"); + orderMethod = ByteBuffer.class.getMethod("order", new Class[] { byteOrderClass }); + Method nativeOrderMethod = byteOrderClass.getMethod("nativeOrder", null); + nativeOrderObject = nativeOrderMethod.invoke(null, null); + } + } catch (Throwable t) { + // Must be running on CDC / FP + isCDCFP = true; + } + + if (!isCDCFP) { + try { + orderMethod.invoke(buf, new Object[] { nativeOrderObject }); + } catch (Throwable t) { + } + } + } + return buf; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // NOTE that this work must be done reflectively at the present time + // because this code must compile and run correctly on both CDC/FP and J2SE + private static boolean isCDCFP; + private static Class byteOrderClass; + private static Object nativeOrderObject; + private static Method orderMethod; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ProjectFloat.java b/src/jogl/classes/com/jogamp/opengl/impl/ProjectFloat.java new file mode 100755 index 000000000..dbd84c9de --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/ProjectFloat.java @@ -0,0 +1,1057 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** $Date: 2009-03-13 22:20:29 -0700 (Fri, 13 Mar 2009) $ $Revision: 1867 $ +** $Header$ +*/ + +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * 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.impl; + +import java.nio.*; + +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +/** + * ProjectFloat.java + * <p/> + * <p/> + * Created 11-jan-2004 + * + * @author Erik Duijs + * @author Kenneth Russell + */ +public class ProjectFloat { + private static final float[] IDENTITY_MATRIX = + new float[] { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + + private static final float[] ZERO_MATRIX = + new float[] { + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f }; + + // Note that we have cloned parts of the implementation in order to + // support incoming Buffers. The reason for this is to avoid loading + // non-direct buffer subclasses unnecessarily, because doing so can + // cause performance decreases on direct buffer operations, at least + // on the current HotSpot JVM. It would be nicer (and make the code + // simpler) to simply have the array-based entry points delegate to + // the versions taking Buffers by wrapping the arrays. + + // Array-based implementation + private final float[] matrix = new float[16]; + private final float[][] tempInvertMatrix = new float[4][4]; + + private final float[] in = new float[4]; + private final float[] out = new float[4]; + + private final float[] forward = new float[3]; + private final float[] side = new float[3]; + private final float[] up = new float[3]; + + // Buffer-based implementation + private FloatBuffer locbuf; + private final FloatBuffer matrixBuf; + private final FloatBuffer tempInvertMatrixBuf; + + private final FloatBuffer inBuf; + private final FloatBuffer outBuf; + + private final FloatBuffer forwardBuf; + private final FloatBuffer sideBuf; + private final FloatBuffer upBuf; + + public ProjectFloat() { + // Use direct buffers to avoid loading indirect buffer + // implementations for applications trying to avoid doing so. + // Slice up one big buffer because some NIO implementations + // allocate a huge amount of memory to back even the smallest of + // buffers. + locbuf = InternalBufferUtil.newFloatBuffer(2*16+2*4+3*3); + int pos = 0; + int sz = 16; + matrixBuf = slice(locbuf, pos, sz); + pos += sz; + tempInvertMatrixBuf = slice(locbuf, pos, sz); + pos += sz; + sz = 4; + inBuf = slice(locbuf, pos, sz); + pos += sz; + outBuf = slice(locbuf, pos, sz); + pos += sz; + sz = 3; + forwardBuf = slice(locbuf, pos, sz); + pos += sz; + sideBuf = slice(locbuf, pos, sz); + pos += sz; + upBuf = slice(locbuf, pos, sz); + } + + public void destroy() { + if(locbuf!=null) { + locbuf.clear(); + locbuf=null; + } + } + + private static FloatBuffer slice(FloatBuffer buf, int pos, int len) { + buf.position(pos); + buf.limit(pos + len); + return buf.slice(); + } + + /** + * Make matrix an identity matrix + */ + public static void gluMakeIdentityf(FloatBuffer m) { + int oldPos = m.position(); + m.put(IDENTITY_MATRIX); + m.position(oldPos); + } + + /** + * Make matrix an zero matrix + */ + public static void gluMakeZero(FloatBuffer m) { + int oldPos = m.position(); + m.put(ZERO_MATRIX); + m.position(oldPos); + } + + /** + * Make matrix an identity matrix + */ + public static void gluMakeIdentityf(float[] m) { + for (int i = 0; i < 16; i++) { + m[i] = IDENTITY_MATRIX[i]; + } + } + + /** + * Method __gluMultMatrixVecf + * + * @param matrix + * @param in + * @param out + */ + private void __gluMultMatrixVecf(float[] matrix, int matrix_offset, float[] in, float[] out) { + for (int i = 0; i < 4; i++) { + out[i] = + in[0] * matrix[0*4+i+matrix_offset] + + in[1] * matrix[1*4+i+matrix_offset] + + in[2] * matrix[2*4+i+matrix_offset] + + in[3] * matrix[3*4+i+matrix_offset]; + } + } + + /** + * Method __gluMultMatrixVecf + * + * @param matrix + * @param in + * @param out + */ + private void __gluMultMatrixVecf(FloatBuffer matrix, FloatBuffer in, FloatBuffer out) { + int inPos = in.position(); + int outPos = out.position(); + int matrixPos = matrix.position(); + for (int i = 0; i < 4; i++) { + out.put(i + outPos, + in.get(0+inPos) * matrix.get(0*4+i+matrixPos) + + in.get(1+inPos) * matrix.get(1*4+i+matrixPos) + + in.get(2+inPos) * matrix.get(2*4+i+matrixPos) + + in.get(3+inPos) * matrix.get(3*4+i+matrixPos)); + } + } + + /** + * @param src + * @param inverse + * + * @return + */ + public boolean gluInvertMatrixf(float[] src, float[] inverse) { + int i, j, k, swap; + float t; + float[][] temp = tempInvertMatrix; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp[i][j] = src[i*4+j]; + } + } + gluMakeIdentityf(inverse); + + for (i = 0; i < 4; i++) { + // + // Look for largest element in column + // + swap = i; + for (j = i + 1; j < 4; j++) { + if (Math.abs(temp[j][i]) > Math.abs(temp[i][i])) { + swap = j; + } + } + + if (swap != i) { + // + // Swap rows. + // + for (k = 0; k < 4; k++) { + t = temp[i][k]; + temp[i][k] = temp[swap][k]; + temp[swap][k] = t; + + t = inverse[i*4+k]; + inverse[i*4+k] = inverse[swap*4+k]; + inverse[swap*4+k] = t; + } + } + + if (temp[i][i] == 0) { + // + // No non-zero pivot. The matrix is singular, which shouldn't + // happen. This means the user gave us a bad matrix. + // + return false; + } + + t = temp[i][i]; + for (k = 0; k < 4; k++) { + temp[i][k] /= t; + inverse[i*4+k] /= t; + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp[j][i]; + for (k = 0; k < 4; k++) { + temp[j][k] -= temp[i][k] * t; + inverse[j*4+k] -= inverse[i*4+k]*t; + } + } + } + } + return true; + } + + /** + * @param src + * @param inverse + * + * @return + */ + public boolean gluInvertMatrixf(FloatBuffer src, FloatBuffer inverse) { + int i, j, k, swap; + float t; + + int srcPos = src.position(); + int invPos = inverse.position(); + + FloatBuffer temp = tempInvertMatrixBuf; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp.put(i*4+j, src.get(i*4+j + srcPos)); + } + } + gluMakeIdentityf(inverse); + + for (i = 0; i < 4; i++) { + // + // Look for largest element in column + // + swap = i; + for (j = i + 1; j < 4; j++) { + if (Math.abs(temp.get(j*4+i)) > Math.abs(temp.get(i*4+i))) { + swap = j; + } + } + + if (swap != i) { + // + // Swap rows. + // + for (k = 0; k < 4; k++) { + t = temp.get(i*4+k); + temp.put(i*4+k, temp.get(swap*4+k)); + temp.put(swap*4+k, t); + + t = inverse.get(i*4+k + invPos); + inverse.put(i*4+k + invPos, inverse.get(swap*4+k + invPos)); + inverse.put(swap*4+k + invPos, t); + } + } + + if (temp.get(i*4+i) == 0) { + // + // No non-zero pivot. The matrix is singular, which shouldn't + // happen. This means the user gave us a bad matrix. + // + return false; + } + + t = temp.get(i*4+i); + for (k = 0; k < 4; k++) { + temp.put(i*4+k, temp.get(i*4+k) / t); + inverse.put(i*4+k + invPos, inverse.get(i*4+k + invPos) / t); + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp.get(j*4+i); + for (k = 0; k < 4; k++) { + temp.put(j*4+k, temp.get(j*4+k) - temp.get(i*4+k) * t); + inverse.put(j*4+k + invPos, inverse.get(j*4+k + invPos) - inverse.get(i*4+k + invPos) * t); + } + } + } + } + return true; + } + + + /** + * @param a + * @param b + * @param r + */ + private void gluMultMatricesf(float[] a, int a_offset, float[] b, int b_offset, float[] r) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r[i*4+j] = + a[i*4+0+a_offset]*b[0*4+j+b_offset] + + a[i*4+1+a_offset]*b[1*4+j+b_offset] + + a[i*4+2+a_offset]*b[2*4+j+b_offset] + + a[i*4+3+a_offset]*b[3*4+j+b_offset]; + } + } + } + + + /** + * @param a + * @param b + * @param r + */ + public static void gluMultMatricesf(FloatBuffer a, FloatBuffer b, FloatBuffer r) { + int aPos = a.position(); + int bPos = b.position(); + int rPos = r.position(); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r.put(i*4+j + rPos, + a.get(i*4+0+aPos)*b.get(0*4+j+bPos) + + a.get(i*4+1+aPos)*b.get(1*4+j+bPos) + + a.get(i*4+2+aPos)*b.get(2*4+j+bPos) + + a.get(i*4+3+aPos)*b.get(3*4+j+bPos)); + } + } + } + + /** + * Normalize vector + * + * @param v + */ + public static void normalize(float[] v) { + float r; + + r = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + if ( r == 0.0 || r == 1.0) + return; + + r = 1.0f / r; + + v[0] *= r; + v[1] *= r; + v[2] *= r; + + return; + } + + /** + * Normalize vector + * + * @param v + */ + public static void normalize(FloatBuffer v) { + float r; + + int vPos = v.position(); + + r = (float) Math.sqrt(v.get(0+vPos) * v.get(0+vPos) + + v.get(1+vPos) * v.get(1+vPos) + + v.get(2+vPos) * v.get(2+vPos)); + if ( r == 0.0 || r == 1.0) + return; + + r = 1.0f / r; + + v.put(0+vPos, v.get(0+vPos) * r); + v.put(1+vPos, v.get(1+vPos) * r); + v.put(2+vPos, v.get(2+vPos) * r); + + return; + } + + + /** + * Calculate cross-product + * + * @param v1 + * @param v2 + * @param result + */ + private static void cross(float[] v1, float[] v2, float[] result) { + result[0] = v1[1] * v2[2] - v1[2] * v2[1]; + result[1] = v1[2] * v2[0] - v1[0] * v2[2]; + result[2] = v1[0] * v2[1] - v1[1] * v2[0]; + } + + /** + * Calculate cross-product + * + * @param v1 + * @param v2 + * @param result + */ + private static void cross(FloatBuffer v1, FloatBuffer v2, FloatBuffer result) { + int v1Pos = v1.position(); + int v2Pos = v2.position(); + int rPos = result.position(); + + result.put(0+rPos, v1.get(1+v1Pos) * v2.get(2+v2Pos) - v1.get(2+v1Pos) * v2.get(1+v2Pos)); + result.put(1+rPos, v1.get(2+v1Pos) * v2.get(0+v2Pos) - v1.get(0+v1Pos) * v2.get(2+v2Pos)); + result.put(2+rPos, v1.get(0+v1Pos) * v2.get(1+v2Pos) - v1.get(1+v1Pos) * v2.get(0+v2Pos)); + } + + /** + * Method gluOrtho2D. + * + * @param left + * @param right + * @param bottom + * @param top + */ + public void gluOrtho2D(GLMatrixFunc gl, float left, float right, float bottom, float top) { + gl.glOrthof(left, right, bottom, top, -1, 1); + } + + /** + * Method gluPerspective. + * + * @param fovy + * @param aspect + * @param zNear + * @param zFar + */ + public void gluPerspective(GLMatrixFunc gl, float fovy, float aspect, float zNear, float zFar) { + float sine, cotangent, deltaZ; + float radians = fovy / 2 * (float) Math.PI / 180; + + deltaZ = zFar - zNear; + sine = (float) Math.sin(radians); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) { + return; + } + + cotangent = (float) Math.cos(radians) / sine; + + gluMakeIdentityf(matrixBuf); + + matrixBuf.put(0 * 4 + 0, cotangent / aspect); + matrixBuf.put(1 * 4 + 1, cotangent); + matrixBuf.put(2 * 4 + 2, - (zFar + zNear) / deltaZ); + matrixBuf.put(2 * 4 + 3, -1); + matrixBuf.put(3 * 4 + 2, -2 * zNear * zFar / deltaZ); + matrixBuf.put(3 * 4 + 3, 0); + + gl.glMultMatrixf(matrixBuf); + } + + /** + * Method gluLookAt + * + * @param eyex + * @param eyey + * @param eyez + * @param centerx + * @param centery + * @param centerz + * @param upx + * @param upy + * @param upz + */ + public void gluLookAt(GLMatrixFunc gl, + float eyex, + float eyey, + float eyez, + float centerx, + float centery, + float centerz, + float upx, + float upy, + float upz) { + FloatBuffer forward = this.forwardBuf; + FloatBuffer side = this.sideBuf; + FloatBuffer up = this.upBuf; + + forward.put(0, centerx - eyex); + forward.put(1, centery - eyey); + forward.put(2, centerz - eyez); + + up.put(0, upx); + up.put(1, upy); + up.put(2, upz); + + normalize(forward); + + /* Side = forward x up */ + cross(forward, up, side); + normalize(side); + + /* Recompute up as: up = side x forward */ + cross(side, forward, up); + + gluMakeIdentityf(matrixBuf); + matrixBuf.put(0 * 4 + 0, side.get(0)); + matrixBuf.put(1 * 4 + 0, side.get(1)); + matrixBuf.put(2 * 4 + 0, side.get(2)); + + matrixBuf.put(0 * 4 + 1, up.get(0)); + matrixBuf.put(1 * 4 + 1, up.get(1)); + matrixBuf.put(2 * 4 + 1, up.get(2)); + + matrixBuf.put(0 * 4 + 2, -forward.get(0)); + matrixBuf.put(1 * 4 + 2, -forward.get(1)); + matrixBuf.put(2 * 4 + 2, -forward.get(2)); + + gl.glMultMatrixf(matrixBuf); + gl.glTranslatef(-eyex, -eyey, -eyez); + } + + /** + * Method gluProject + * + * @param objx + * @param objy + * @param objz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param win_pos + * + * @return + */ + public boolean gluProject(float objx, + float objy, + float objz, + float[] modelMatrix, + int modelMatrix_offset, + float[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + float[] win_pos, + int win_pos_offset ) { + + float[] in = this.in; + float[] out = this.out; + + in[0] = objx; + in[1] = objy; + in[2] = objz; + in[3] = 1.0f; + + __gluMultMatrixVecf(modelMatrix, modelMatrix_offset, in, out); + __gluMultMatrixVecf(projMatrix, projMatrix_offset, out, in); + + if (in[3] == 0.0f) + return false; + + in[3] = (1.0f / in[3]) * 0.5f; + + // Map x, y and z to range 0-1 + in[0] = in[0] * in[3] + 0.5f; + in[1] = in[1] * in[3] + 0.5f; + in[2] = in[2] * in[3] + 0.5f; + + // Map x,y to viewport + win_pos[0+win_pos_offset] = in[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset]; + win_pos[1+win_pos_offset] = in[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset]; + win_pos[2+win_pos_offset] = in[2]; + + return true; + } + + /** + * Method gluProject + * + * @param objx + * @param objy + * @param objz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param win_pos + * + * @return + */ + public boolean gluProject(float objx, + float objy, + float objz, + FloatBuffer modelMatrix, + FloatBuffer projMatrix, + IntBuffer viewport, + FloatBuffer win_pos) { + + FloatBuffer in = this.inBuf; + FloatBuffer out = this.outBuf; + + in.put(0, objx); + in.put(1, objy); + in.put(2, objz); + in.put(3, 1.0f); + + __gluMultMatrixVecf(modelMatrix, in, out); + __gluMultMatrixVecf(projMatrix, out, in); + + if (in.get(3) == 0.0f) + return false; + + in.put(3, (1.0f / in.get(3)) * 0.5f); + + // Map x, y and z to range 0-1 + in.put(0, in.get(0) * in.get(3) + 0.5f); + in.put(1, in.get(1) * in.get(3) + 0.5f); + in.put(2, in.get(2) * in.get(3) + 0.5f); + + // Map x,y to viewport + int vPos = viewport.position(); + int wPos = win_pos.position(); + win_pos.put(0+wPos, in.get(0) * viewport.get(2+vPos) + viewport.get(0+vPos)); + win_pos.put(1+wPos, in.get(1) * viewport.get(3+vPos) + viewport.get(1+vPos)); + win_pos.put(2+wPos, in.get(2)); + + return true; + } + + + /** + * Method gluUnproject + * + * @param winx + * @param winy + * @param winz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param obj_pos + * + * @return + */ + public boolean gluUnProject(float winx, + float winy, + float winz, + float[] modelMatrix, + int modelMatrix_offset, + float[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + float[] obj_pos, + int obj_pos_offset) { + float[] in = this.in; + float[] out = this.out; + + gluMultMatricesf(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); + + if (!gluInvertMatrixf(matrix, matrix)) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = 1.0f; + + // Map x and y from window coordinates + in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; + in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; + + // Map to range -1 to 1 + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + __gluMultMatrixVecf(matrix, 0, in, out); + + if (out[3] == 0.0) + return false; + + out[3] = 1.0f / out[3]; + + obj_pos[0+obj_pos_offset] = out[0] * out[3]; + obj_pos[1+obj_pos_offset] = out[1] * out[3]; + obj_pos[2+obj_pos_offset] = out[2] * out[3]; + + return true; + } + + + /** + * Method gluUnproject + * + * @param winx + * @param winy + * @param winz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param obj_pos + * + * @return + */ + public boolean gluUnProject(float winx, + float winy, + float winz, + FloatBuffer modelMatrix, + FloatBuffer projMatrix, + IntBuffer viewport, + FloatBuffer obj_pos) { + FloatBuffer in = this.inBuf; + FloatBuffer out = this.outBuf; + + gluMultMatricesf(modelMatrix, projMatrix, matrixBuf); + + if (!gluInvertMatrixf(matrixBuf, matrixBuf)) + return false; + + in.put(0, winx); + in.put(1, winy); + in.put(2, winz); + in.put(3, 1.0f); + + // Map x and y from window coordinates + int vPos = viewport.position(); + int oPos = obj_pos.position(); + in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos)); + in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos)); + + // Map to range -1 to 1 + in.put(0, in.get(0) * 2 - 1); + in.put(1, in.get(1) * 2 - 1); + in.put(2, in.get(2) * 2 - 1); + + __gluMultMatrixVecf(matrixBuf, in, out); + + if (out.get(3) == 0.0f) + return false; + + out.put(3, 1.0f / out.get(3)); + + obj_pos.put(0+oPos, out.get(0) * out.get(3)); + obj_pos.put(1+oPos, out.get(1) * out.get(3)); + obj_pos.put(2+oPos, out.get(2) * out.get(3)); + + return true; + } + + + /** + * Method gluUnproject4 + * + * @param winx + * @param winy + * @param winz + * @param clipw + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param near + * @param far + * @param obj_pos + * + * @return + */ + public boolean gluUnProject4(float winx, + float winy, + float winz, + float clipw, + float[] modelMatrix, + int modelMatrix_offset, + float[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + float near, + float far, + float[] obj_pos, + int obj_pos_offset ) { + float[] in = this.in; + float[] out = this.out; + + gluMultMatricesf(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); + + if (!gluInvertMatrixf(matrix, matrix)) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = clipw; + + // Map x and y from window coordinates + in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; + in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; + in[2] = (in[2] - near) / (far - near); + + // Map to range -1 to 1 + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + __gluMultMatrixVecf(matrix, 0, in, out); + + if (out[3] == 0.0f) + return false; + + obj_pos[0+obj_pos_offset] = out[0]; + obj_pos[1+obj_pos_offset] = out[1]; + obj_pos[2+obj_pos_offset] = out[2]; + obj_pos[3+obj_pos_offset] = out[3]; + return true; + } + + /** + * Method gluUnproject4 + * + * @param winx + * @param winy + * @param winz + * @param clipw + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param near + * @param far + * @param obj_pos + * + * @return + */ + public boolean gluUnProject4(float winx, + float winy, + float winz, + float clipw, + FloatBuffer modelMatrix, + FloatBuffer projMatrix, + IntBuffer viewport, + float near, + float far, + FloatBuffer obj_pos) { + FloatBuffer in = this.inBuf; + FloatBuffer out = this.outBuf; + + gluMultMatricesf(modelMatrix, projMatrix, matrixBuf); + + if (!gluInvertMatrixf(matrixBuf, matrixBuf)) + return false; + + in.put(0, winx); + in.put(1, winy); + in.put(2, winz); + in.put(3, clipw); + + // Map x and y from window coordinates + int vPos = viewport.position(); + in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos)); + in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos)); + in.put(2, (in.get(2) - near) / (far - near)); + + // Map to range -1 to 1 + in.put(0, in.get(0) * 2 - 1); + in.put(1, in.get(1) * 2 - 1); + in.put(2, in.get(2) * 2 - 1); + + __gluMultMatrixVecf(matrixBuf, in, out); + + if (out.get(3) == 0.0f) + return false; + + int oPos = obj_pos.position(); + obj_pos.put(0+oPos, out.get(0)); + obj_pos.put(1+oPos, out.get(1)); + obj_pos.put(2+oPos, out.get(2)); + obj_pos.put(3+oPos, out.get(3)); + return true; + } + + + /** + * Method gluPickMatrix + * + * @param x + * @param y + * @param deltaX + * @param deltaY + * @param viewport + */ + public void gluPickMatrix(GLMatrixFunc gl, + float x, + float y, + float deltaX, + float deltaY, + IntBuffer viewport) { + if (deltaX <= 0 || deltaY <= 0) { + return; + } + + /* Translate and scale the picked region to the entire window */ + int vPos = viewport.position(); + gl.glTranslatef((viewport.get(2+vPos) - 2 * (x - viewport.get(0+vPos))) / deltaX, + (viewport.get(3+vPos) - 2 * (y - viewport.get(1+vPos))) / deltaY, + 0); + gl.glScalef(viewport.get(2) / deltaX, viewport.get(3) / deltaY, 1.0f); + } + + /** + * Method gluPickMatrix + * + * @param x + * @param y + * @param deltaX + * @param deltaY + * @param viewport + * @param viewport_offset + */ + public void gluPickMatrix(GLMatrixFunc gl, + float x, + float y, + float deltaX, + float deltaY, + int[] viewport, + int viewport_offset) { + if (deltaX <= 0 || deltaY <= 0) { + return; + } + + /* Translate and scale the picked region to the entire window */ + gl.glTranslatef((viewport[2+viewport_offset] - 2 * (x - viewport[0+viewport_offset])) / deltaX, + (viewport[3+viewport_offset] - 2 * (y - viewport[1+viewport_offset])) / deltaY, + 0); + gl.glScalef(viewport[2+viewport_offset] / deltaX, viewport[3+viewport_offset] / deltaY, 1.0f); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javame_cdc_fp b/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javame_cdc_fp new file mode 100644 index 000000000..f686bea92 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javame_cdc_fp @@ -0,0 +1,10 @@ +package com.jogamp.opengl.impl; + +public class SystemUtil { + + /** Wrapper for System.getenv(), which doesn't work on platforms + earlier than JDK 5 */ + public static String getenv(String variableName) { + return null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javase b/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javase new file mode 100644 index 000000000..dbb717a32 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javase @@ -0,0 +1,18 @@ +package com.jogamp.opengl.impl; + +public class SystemUtil { + + private static volatile boolean getenvSupported = true; + /** Wrapper for System.getenv(), which doesn't work on platforms + earlier than JDK 5 */ + public static String getenv(String variableName) { + if (getenvSupported) { + try { + return System.getenv(variableName); + } catch (Error e) { + getenvSupported = false; + } + } + return null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java new file mode 100644 index 000000000..1a68f38d4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2009 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. + * + */ + +package com.jogamp.opengl.impl; + +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLException; + +/** Implementation of the {@link javax.media.opengl.Threading} class. */ + +public class ThreadingImpl { + public static final int AWT = 1; + public static final int WORKER = 2; + + protected static final boolean DEBUG = Debug.debug("Threading"); + + private static boolean singleThreaded = true; + private static int mode; + private static boolean hasAWT; + // We need to know whether we're running on X11 platforms to change + // our behavior when the Java2D/JOGL bridge is active + private static boolean _isX11; + + private static final ThreadingPlugin threadingPlugin; + + static { + Object threadingPluginTmp = + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String workaround = Debug.getProperty("jogl.1thread", true); + // Default to using the AWT thread on all platforms except + // Windows. On OS X there is instability apparently due to + // using the JAWT on non-AWT threads. On X11 platforms there + // are potential deadlocks which can be caused if the AWT + // EventQueue thread hands work off to the GLWorkerThread + // while holding the AWT lock. The optimization of + // makeCurrent / release calls isn't worth these stability + // problems. + hasAWT = ReflectionUtil.isClassAvailable("java.awt.Canvas") && + ReflectionUtil.isClassAvailable("javax.media.opengl.awt.GLCanvas"); + + String osType = NativeWindowFactory.getNativeWindowType(false); + _isX11 = NativeWindowFactory.TYPE_X11.equals(osType); + // boolean isWindows = NativeWindowFactory.TYPE_WINDOWS.equals(osType); + + // int defaultMode = (isWindows ? WORKER : ( hasAWT ? AWT : WORKER ) ); + int defaultMode = ( hasAWT ? AWT : WORKER ); + + mode = defaultMode; + if (workaround != null) { + workaround = workaround.toLowerCase(); + if (workaround.equals("true") || + workaround.equals("auto")) { + // Nothing to do; singleThreaded and mode already set up + } else if (workaround.equals("worker")) { + singleThreaded = true; + mode = WORKER; + } else if (workaround.equals("awt")) { + singleThreaded = true; + mode = AWT; + } else { + singleThreaded = false; + } + } + printWorkaroundNotice(); + + Object threadingPluginObj=null; + // try to fetch the AWTThreadingPlugin + try { + threadingPluginObj = ReflectionUtil.createInstance("com.jogamp.opengl.impl.awt.AWTThreadingPlugin"); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + return threadingPluginObj; + } + }); + threadingPlugin = (ThreadingPlugin) threadingPluginTmp; + if(DEBUG) { + System.err.println("Threading: hasAWT "+hasAWT+", mode "+((mode==AWT)?"AWT":"WORKER")+", plugin "+threadingPlugin); + } + } + + /** No reason to ever instantiate this class */ + private ThreadingImpl() {} + + public static boolean isX11() { return _isX11; } + public static int getMode() { return mode; } + + /** If an implementation of the javax.media.opengl APIs offers a + multithreading option but the default behavior is single-threading, + this API provides a mechanism for end users to disable single-threading + in this implementation. Users are strongly discouraged from + calling this method unless they are aware of all of the + consequences and are prepared to enforce some amount of + threading restrictions in their applications. Disabling + single-threading, for example, may have unintended consequences + on GLAutoDrawable implementations such as GLCanvas, GLJPanel and + GLPbuffer. Currently there is no supported way to re-enable it + once disabled, partly to discourage careless use of this + method. This method should be called as early as possible in an + application. */ + public static void disableSingleThreading() { + singleThreaded = false; + if (Debug.verbose()) { + System.err.println("Application forced disabling of single-threading of javax.media.opengl implementation"); + } + } + + /** Indicates whether OpenGL work is being automatically forced to a + single thread in this implementation. */ + public static boolean isSingleThreaded() { + return singleThreaded; + } + + /** Indicates whether the current thread is the single thread on + which this implementation of the javax.media.opengl APIs + performs all of its OpenGL-related work. This method should only + be called if the single-thread model is in effect. */ + public static boolean isOpenGLThread() throws GLException { + if (!isSingleThreaded()) { + throw new GLException("Should only call this in single-threaded mode"); + } + + if(null!=threadingPlugin) { + return threadingPlugin.isOpenGLThread(); + } + + switch (mode) { + case AWT: + return true; + case WORKER: + return GLWorkerThread.isWorkerThread(); + default: + throw new InternalError("Illegal single-threading mode " + mode); + } + } + + /** Executes the passed Runnable on the single thread used for all + OpenGL work in this javax.media.opengl API implementation. It is + not specified exactly which thread is used for this + purpose. This method should only be called if the single-thread + model is in use and if the current thread is not the OpenGL + thread (i.e., if <code>isOpenGLThread()</code> returns + false). It is up to the end user to check to see whether the + current thread is the OpenGL thread and either execute the + Runnable directly or perform the work inside it. */ + public static void invokeOnOpenGLThread(Runnable r) throws GLException { + if (!isSingleThreaded()) { + throw new GLException ("Should only call this in single-threaded mode"); + } + + if (isOpenGLThread()) { + throw new GLException ("Should only call this from other threads than the OpenGL thread"); + } + + if(null!=threadingPlugin) { + threadingPlugin.invokeOnOpenGLThread(r); + return; + } + + switch (mode) { + case AWT: + r.run(); + break; + + case WORKER: + if (!GLWorkerThread.isStarted()) { + synchronized (GLWorkerThread.class) { + if (!GLWorkerThread.isStarted()) { + GLWorkerThread.start(); + } + } + } + try { + GLWorkerThread.invokeAndWait(r); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (InterruptedException e) { + throw new GLException(e); + } + break; + + default: + throw new InternalError("Illegal single-threading mode " + mode); + } + } + + /** This is a workaround for AWT-related deadlocks which only seem + to show up in the context of applets */ + public static boolean isAWTMode() { + return (mode == AWT); + } + + private static void printWorkaroundNotice() { + if (singleThreaded && Debug.verbose()) { + System.err.println("Using " + + (mode == AWT ? "AWT" : "OpenGL worker") + + " thread for performing OpenGL work in javax.media.opengl implementation"); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ThreadingPlugin.java b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingPlugin.java new file mode 100644 index 000000000..37e4aac70 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingPlugin.java @@ -0,0 +1,62 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import javax.media.opengl.*; + +public interface ThreadingPlugin { + /** Indicates whether the current thread is the single thread on + which this implementation of the javax.media.opengl APIs + performs all of its OpenGL-related work. This method should only + be called if the single-thread model is in effect. */ + public boolean isOpenGLThread() throws GLException; + + /** Executes the passed Runnable on the single thread used for all + OpenGL work in this javax.media.opengl API implementation. It is + not specified exactly which thread is used for this + purpose. This method should only be called if the single-thread + model is in use and if the current thread is not the OpenGL + thread (i.e., if <code>isOpenGLThread()</code> returns + false). It is up to the end user to check to see whether the + current thread is the OpenGL thread and either execute the + Runnable directly or perform the work inside it. */ + public void invokeOnOpenGLThread(Runnable r) throws GLException; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTThreadingPlugin.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTThreadingPlugin.java new file mode 100755 index 000000000..07bf2f2db --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTThreadingPlugin.java @@ -0,0 +1,129 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.awt; + +import javax.media.opengl.*; + +import java.awt.event.*; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.opengl.impl.*; + +public class AWTThreadingPlugin implements ThreadingPlugin { + + public AWTThreadingPlugin() {} + + public boolean isOpenGLThread() throws GLException { + switch (ThreadingImpl.getMode()) { + case ThreadingImpl.AWT: + if (Java2D.isOGLPipelineActive()) { + // FIXME: ideally only the QFT would be considered to be the + // "OpenGL thread", but we can not currently run all of + // JOGL's OpenGL work on that thread. See the FIXME in + // invokeOnOpenGLThread. + return (Java2D.isQueueFlusherThread() || + (ThreadingImpl.isX11() && EventQueue.isDispatchThread())); + } else { + return EventQueue.isDispatchThread(); + } + case ThreadingImpl.WORKER: + if (Java2D.isOGLPipelineActive()) { + // FIXME: ideally only the QFT would be considered to be the + // "OpenGL thread", but we can not currently run all of + // JOGL's OpenGL work on that thread. See the FIXME in + // invokeOnOpenGLThread. + return (Java2D.isQueueFlusherThread() || + (ThreadingImpl.isX11() && GLWorkerThread.isWorkerThread())); + } else { + return GLWorkerThread.isWorkerThread(); + } + default: + throw new InternalError("Illegal single-threading mode " + ThreadingImpl.getMode()); + } + } + + public void invokeOnOpenGLThread(Runnable r) throws GLException { + switch (ThreadingImpl.getMode()) { + case ThreadingImpl.AWT: + // FIXME: ideally should run all OpenGL work on the Java2D QFT + // thread when it's enabled, but unfortunately there are + // deadlock issues on X11 platforms when making our + // heavyweight OpenGL contexts current on the QFT because we + // perform the JAWT lock inside the makeCurrent() + // implementation, which attempts to grab the AWT lock on the + // QFT which is not allowed. For now, on X11 platforms, + // continue to perform this work on the EDT. + if (Java2D.isOGLPipelineActive() && !ThreadingImpl.isX11()) { + Java2D.invokeWithOGLContextCurrent(null, r); + } else { + try { + EventQueue.invokeAndWait(r); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (InterruptedException e) { + throw new GLException(e); + } + } + break; + + case ThreadingImpl.WORKER: + if (!GLWorkerThread.isStarted()) { + synchronized (GLWorkerThread.class) { + if (!GLWorkerThread.isStarted()) { + GLWorkerThread.start(); + } + } + } + try { + GLWorkerThread.invokeAndWait(r); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (InterruptedException e) { + throw new GLException(e); + } + break; + + default: + throw new InternalError("Illegal single-threading mode " + ThreadingImpl.getMode()); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java new file mode 100644 index 000000000..e5570a8ee --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java @@ -0,0 +1,125 @@ +/* + * 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.impl.awt; + +import com.jogamp.nativewindow.impl.jawt.*; + +import com.jogamp.opengl.impl.*; + +import javax.media.opengl.*; + +import java.lang.reflect.*; +import java.awt.GraphicsEnvironment; + +public class AWTUtil { + // See whether we're running in headless mode + private static boolean headlessMode; + private static Class j2dClazz = null; + private static Method isOGLPipelineActive = null; + private static Method isQueueFlusherThread = null; + private static boolean j2dOk = false; + + static { + lockedToolkit = false; + headlessMode = GraphicsEnvironment.isHeadless(); + if(!headlessMode) { + try { + j2dClazz = Class.forName("com.jogamp.opengl.impl.awt.Java2D"); + isOGLPipelineActive = j2dClazz.getMethod("isOGLPipelineActive", null); + isQueueFlusherThread = j2dClazz.getMethod("isQueueFlusherThread", null); + j2dOk = true; + } catch (Exception e) {} + } + } + + private static boolean lockedToolkit; + + public static synchronized void lockToolkit() throws GLException { + if (lockedToolkit) { + throw new GLException("Toolkit already locked"); + } + lockedToolkit = true; + + if (headlessMode) { + // Workaround for running (to some degree) in headless + // environments but still supporting rendering via pbuffers + // For full correctness, would need to implement a Lock class + return; + } + + if(j2dOk) { + try { + if( !((Boolean)isOGLPipelineActive.invoke(null, null)).booleanValue() || + !((Boolean)isQueueFlusherThread.invoke(null, null)).booleanValue() ) { + JAWTUtil.lockToolkit(); + } + } catch (Exception e) { j2dOk=false; } + } + if(!j2dOk) { + JAWTUtil.lockToolkit(); + } + } + + public static synchronized void unlockToolkit() { + if (lockedToolkit) { + lockedToolkit = false; + if (headlessMode) { + // Workaround for running (to some degree) in headless + // environments but still supporting rendering via pbuffers + // For full correctness, would need to implement a Lock class + return; + } + + if(j2dOk) { + try { + if( !((Boolean)isOGLPipelineActive.invoke(null, null)).booleanValue() || + !((Boolean)isQueueFlusherThread.invoke(null, null)).booleanValue() ) { + JAWTUtil.unlockToolkit(); + } + } catch (Exception e) { j2dOk=false; } + } + if(!j2dOk) { + JAWTUtil.unlockToolkit(); + } + } + } + + public static boolean isToolkitLocked() { + return JAWTUtil.isToolkitLocked(); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java new file mode 100755 index 000000000..b871c66a7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2003-2005 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.awt; + +import com.jogamp.opengl.impl.*; + +import java.awt.*; +import java.awt.image.*; +import java.lang.reflect.*; +import java.security.*; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +/** Defines integration with the Java2D OpenGL pipeline. This + integration is only supported in 1.6 and is highly experimental. */ + +public class Java2D { + private static boolean DEBUG = Debug.debug("Java2D"); + private static boolean VERBOSE = Debug.verbose(); + private static boolean isHeadless; + private static boolean isOGLPipelineActive; + private static Method invokeWithOGLContextCurrentMethod; + private static Method isQueueFlusherThreadMethod; + private static Method getOGLViewportMethod; + private static Method getOGLScissorBoxMethod; + private static Method getOGLSurfaceIdentifierMethod; + // This one is currently optional and is only in very recent Mustang builds + private static Method getOGLTextureTypeMethod; + + // The following methods and fields are needed for proper support of + // Frame Buffer Objects in the Java2D/OpenGL pipeline + // (-Dsun.java2d.opengl.fbobject=true) + private static boolean fbObjectSupportInitialized; + private static Method invokeWithOGLSharedContextCurrentMethod; + private static Method getOGLSurfaceTypeMethod; + + // Publicly-visible constants for OpenGL surface types + public static final int UNDEFINED = getOGLUtilitiesIntField("UNDEFINED"); + public static final int WINDOW = getOGLUtilitiesIntField("WINDOW"); + public static final int PBUFFER = getOGLUtilitiesIntField("PBUFFER"); + public static final int TEXTURE = getOGLUtilitiesIntField("TEXTURE"); + public static final int FLIP_BACKBUFFER = getOGLUtilitiesIntField("FLIP_BACKBUFFER"); + public static final int FBOBJECT = getOGLUtilitiesIntField("FBOBJECT"); + + // If FBOs are enabled in the Java2D/OpenGL pipeline, all contexts + // created by JOGL must share textures and display lists with the + // Java2D contexts in order to access the frame buffer object for + // potential rendering, and to simultaneously support sharing of + // textures and display lists with one another. Java2D has the + // notion of a single shared context with which all other contexts + // (on the same display device?) share textures and display lists; + // this is an approximation to that notion which will be refined + // later. + private static boolean initializedJ2DFBOShareContext; + private static GLContext j2dFBOShareContext; + + // Accessors for new methods in sun.java2d.opengl.CGLSurfaceData + // class on OS X for enabling bridge + // public static long createOGLContextOnSurface(Graphics g, long ctx); + // public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx); + // public static void destroyOGLContext(long ctx); + private static Method createOGLContextOnSurfaceMethod; + private static Method makeOGLContextCurrentOnSurfaceMethod; + private static Method destroyOGLContextMethod; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + if (DEBUG && VERBOSE) { + System.err.println("Checking for Java2D/OpenGL support"); + } + try { + isHeadless = true; + // Figure out whether the default graphics configuration is an + // OpenGL graphics configuration + GraphicsConfiguration cfg = + GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice(). + getDefaultConfiguration(); + // If we get here, we aren't running in headless mode + isHeadless = false; + String name = cfg.getClass().getName(); + if (DEBUG && VERBOSE) { + System.err.println("Java2D support: default GraphicsConfiguration = " + name); + } + isOGLPipelineActive = (name.startsWith("sun.java2d.opengl")); + + if (isOGLPipelineActive) { + try { + // Try to get methods we need to integrate + Class utils = Class.forName("sun.java2d.opengl.OGLUtilities"); + invokeWithOGLContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLContextCurrent", + new Class[] { + Graphics.class, + Runnable.class + }); + invokeWithOGLContextCurrentMethod.setAccessible(true); + + isQueueFlusherThreadMethod = utils.getDeclaredMethod("isQueueFlusherThread", + new Class[] {}); + isQueueFlusherThreadMethod.setAccessible(true); + + getOGLViewportMethod = utils.getDeclaredMethod("getOGLViewport", + new Class[] { + Graphics.class, + Integer.TYPE, + Integer.TYPE + }); + getOGLViewportMethod.setAccessible(true); + + getOGLScissorBoxMethod = utils.getDeclaredMethod("getOGLScissorBox", + new Class[] { + Graphics.class + }); + getOGLScissorBoxMethod.setAccessible(true); + + getOGLSurfaceIdentifierMethod = utils.getDeclaredMethod("getOGLSurfaceIdentifier", + new Class[] { + Graphics.class + }); + getOGLSurfaceIdentifierMethod.setAccessible(true); + + // Try to get additional methods required for proper FBO support + fbObjectSupportInitialized = true; + try { + invokeWithOGLSharedContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLSharedContextCurrent", + new Class[] { + GraphicsConfiguration.class, + Runnable.class + }); + invokeWithOGLSharedContextCurrentMethod.setAccessible(true); + + getOGLSurfaceTypeMethod = utils.getDeclaredMethod("getOGLSurfaceType", + new Class[] { + Graphics.class + }); + getOGLSurfaceTypeMethod.setAccessible(true); + } catch (Exception e) { + fbObjectSupportInitialized = false; + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("Disabling Java2D/JOGL FBO support"); + } + } + + // Try to get an additional method for FBO support in recent Mustang builds + try { + getOGLTextureTypeMethod = utils.getDeclaredMethod("getOGLTextureType", + new Class[] { + Graphics.class + }); + getOGLTextureTypeMethod.setAccessible(true); + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("GL_ARB_texture_rectangle FBO support disabled"); + } + } + + // Try to set up APIs for enabling the bridge on OS X, + // where it isn't possible to create generalized + // external GLDrawables + Class cglSurfaceData = null; + try { + cglSurfaceData = Class.forName("sun.java2d.opengl.CGLSurfaceData"); + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("Unable to find class sun.java2d.opengl.CGLSurfaceData for OS X"); + } + } + if (cglSurfaceData != null) { + // FIXME: for now, assume that FBO support is not enabled on OS X + fbObjectSupportInitialized = false; + + // We need to find these methods in order to make the bridge work on OS X + createOGLContextOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("createOGLContextOnSurface", + new Class[] { + Graphics.class, + Long.TYPE + }); + createOGLContextOnSurfaceMethod.setAccessible(true); + + makeOGLContextCurrentOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("makeOGLContextCurrentOnSurface", + new Class[] { + Graphics.class, + Long.TYPE + }); + makeOGLContextCurrentOnSurfaceMethod.setAccessible(true); + + destroyOGLContextMethod = cglSurfaceData.getDeclaredMethod("destroyOGLContext", + new Class[] { + Long.TYPE + }); + destroyOGLContextMethod.setAccessible(true); + } + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("Disabling Java2D/JOGL integration"); + } + isOGLPipelineActive = false; + } + } + } catch (HeadlessException e) { + // The AWT is running in headless mode, so the Java 2D / JOGL bridge is clearly disabled + } + + if (DEBUG) { + System.err.println("JOGL/Java2D integration " + (isOGLPipelineActive ? "enabled" : "disabled")); + } + return null; + } + }); + } + + public static boolean isOGLPipelineActive() { + return isOGLPipelineActive; + } + + public static boolean isFBOEnabled() { + return fbObjectSupportInitialized; + } + + public static boolean isQueueFlusherThread() { + checkActive(); + + try { + return ((Boolean) isQueueFlusherThreadMethod.invoke(null, new Object[] {})).booleanValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Makes current the OpenGL context associated with the passed + Graphics object and runs the given Runnable on the Queue + Flushing Thread in one atomic action. */ + public static void invokeWithOGLContextCurrent(Graphics g, Runnable r) throws GLException { + checkActive(); + + try { + // FIXME: this may need adjustment + // This seems to be needed in many applications which don't + // initialize an OpenGL context before this and which would + // otherwise cause initFBOShareContext to be called from the + // Queue Flusher Thread, which isn't allowed + initFBOShareContext(GraphicsEnvironment. + getLocalGraphicsEnvironment(). + getDefaultScreenDevice()); + + AWTUtil.lockToolkit(); + try { + invokeWithOGLContextCurrentMethod.invoke(null, new Object[] {g, r}); + } finally { + AWTUtil.unlockToolkit(); + } + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Makes current the "shared" OpenGL context associated with the + given GraphicsConfiguration object, allowing JOGL to share + server-side OpenGL objects like textures and display lists with + this context when necessary. This is needed when Java2D's FBO + support is enabled, because in order to render into that FBO, + JOGL must share textures and display lists with it. Returns + false if the passed GraphicsConfiguration was not an OpenGL + GraphicsConfiguration. */ + public static boolean invokeWithOGLSharedContextCurrent(GraphicsConfiguration g, Runnable r) throws GLException { + checkActive(); + + try { + AWTUtil.lockToolkit(); + try { + return ((Boolean) invokeWithOGLSharedContextCurrentMethod.invoke(null, new Object[] {g, r})).booleanValue(); + } finally { + AWTUtil.unlockToolkit(); + } + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns the OpenGL viewport associated with the given Graphics + object, assuming that the Graphics object is associated with a + component of the specified width and height. The user should + call glViewport() with the returned rectangle's bounds in order + to get correct rendering results. Should only be called from the + Queue Flusher Thread. */ + public static Rectangle getOGLViewport(Graphics g, + int componentWidth, + int componentHeight) { + checkActive(); + + try { + return (Rectangle) getOGLViewportMethod.invoke(null, new Object[] {g, + new Integer(componentWidth), + new Integer(componentHeight)}); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns the OpenGL scissor region associated with the given + Graphics object, taking into account all clipping regions, etc. + To avoid destroying Java2D's previous rendering results, this + method should be called and the resulting rectangle's bounds + passed to a call to glScissor(). Should only be called from the + Queue Flusher Thread. */ + public static Rectangle getOGLScissorBox(Graphics g) { + checkActive(); + + try { + return (Rectangle) getOGLScissorBoxMethod.invoke(null, new Object[] {g}); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns an opaque "surface identifier" associated with the given + Graphics object. If this changes from invocation to invocation, + the underlying OpenGL drawable for the Graphics object has + changed and a new external GLDrawable and GLContext should be + created (and the old ones destroyed). Should only be called from + the Queue Flusher Thread.*/ + public static Object getOGLSurfaceIdentifier(Graphics g) { + checkActive(); + + try { + return getOGLSurfaceIdentifierMethod.invoke(null, new Object[] {g}); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns the underlying surface type for the given Graphics + object. This indicates, in particular, whether Java2D is + currently rendering into a pbuffer or FBO. */ + public static int getOGLSurfaceType(Graphics g) { + checkActive(); + + try { + // FIXME: fallback path for pre-b73 (?) Mustang builds -- remove + // once fbobject support is in OGLUtilities + if (!fbObjectSupportInitialized) { + return 0; + } + + return ((Integer) getOGLSurfaceTypeMethod.invoke(null, new Object[] { g })).intValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns the underlying texture target of the given Graphics + object assuming it is rendering to an FBO. Returns either + GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB. */ + public static int getOGLTextureType(Graphics g) { + checkActive(); + + if (getOGLTextureTypeMethod == null) { + return GL.GL_TEXTURE_2D; + } + + try { + return ((Integer) getOGLTextureTypeMethod.invoke(null, new Object[] { g })).intValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns either the given GLContext or a substitute one with + which clients should share textures and display lists. Needed + when the Java2D/OpenGL pipeline is active and FBOs are being + used for rendering. FIXME: may need to alter the API in the + future to indicate which GraphicsDevice the source context is + associated with. */ + public static GLContext filterShareContext(GLContext shareContext) { + if (isHeadless) + return shareContext; + + // FIXME: this may need adjustment + initFBOShareContext(GraphicsEnvironment. + getLocalGraphicsEnvironment(). + getDefaultScreenDevice()); + if (j2dFBOShareContext != null) { + return j2dFBOShareContext; + } + return shareContext; + } + + /** Returns the GLContext associated with the Java2D "share + context", with which all contexts created by JOGL must share + textures and display lists when the FBO option is enabled for + the Java2D/OpenGL pipeline. */ + public static GLContext getShareContext(GraphicsDevice device) { + initFBOShareContext(device); + // FIXME: for full generality probably need to have multiple of + // these, one per GraphicsConfiguration seen? + return j2dFBOShareContext; + } + + //---------------------------------------------------------------------- + // Mac OS X-specific methods + // + + /** (Mac OS X-specific) Creates a new OpenGL context on the surface + associated with the given Graphics object, sharing textures and + display lists with the specified (CGLContextObj) share context. */ + public static long createOGLContextOnSurface(Graphics g, long shareCtx) { + checkActive(); + + try { + return ((Long) createOGLContextOnSurfaceMethod.invoke(null, new Object[] { g, new Long(shareCtx) })).longValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** (Mac OS X-specific) Makes the given OpenGL context current on + the surface associated with the given Graphics object. */ + public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx) { + checkActive(); + + try { + return ((Boolean) makeOGLContextCurrentOnSurfaceMethod.invoke(null, new Object[] { g, new Long(ctx) })).booleanValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** (Mac OS X-specific) Destroys the given OpenGL context. */ + public static void destroyOGLContext(long ctx) { + checkActive(); + + try { + destroyOGLContextMethod.invoke(null, new Object[] { new Long(ctx) }); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static void checkActive() { + if (!isOGLPipelineActive()) { + throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)"); + } + } + + private static int getOGLUtilitiesIntField(final String name) { + Integer i = (Integer) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class utils = Class.forName("sun.java2d.opengl.OGLUtilities"); + Field f = utils.getField(name); + f.setAccessible(true); + return f.get(null); + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + } + return null; + } + } + }); + if (i == null) + return 0; + if (DEBUG && VERBOSE) { + System.err.println("OGLUtilities." + name + " = " + i.intValue()); + } + return i.intValue(); + } + + private static void initFBOShareContext(final GraphicsDevice device) { + // Note 1: this must not be done in the static initalizer due to + // deadlock problems. + + // Note 2: the first execution of this method must not be from the + // Java2D Queue Flusher Thread. + + if (isOGLPipelineActive() && + isFBOEnabled() && + !initializedJ2DFBOShareContext) { + + // FIXME: this technique is probably not adequate in multi-head + // situations. Ideally we would keep track of a given share + // context on a per-GraphicsConfiguration basis or something + // similar rather than keeping one share context in a global + // variable. + initializedJ2DFBOShareContext = true; + if (DEBUG) { + System.err.println("Starting initialization of J2D FBO share context"); + } + invokeWithOGLSharedContextCurrent(device.getDefaultConfiguration(), new Runnable() { + public void run() { + j2dFBOShareContext = GLDrawableFactory.getFactory(GLProfile.getDefault()).createExternalGLContext(); + } + }); + if (DEBUG) { + System.err.println("Ending initialization of J2D FBO share context"); + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2DGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2DGLContext.java new file mode 100644 index 000000000..07bc54b6a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2DGLContext.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.awt; + +import com.jogamp.opengl.impl.*; +import java.awt.Graphics; + +/** Provides a construct by which the shared GLJPanel code can + * interact with a few methods in the Mac OS X-specific Java2D/JOGL + * bridge implementation. + */ + +public interface Java2DGLContext { + public void setGraphics(Graphics g); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java new file mode 100755 index 000000000..48f80977c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; +import java.nio.*; +import java.util.*; + +public abstract class EGLContext extends GLContextImpl { + private long eglContext; + private boolean eglQueryStringInitialized; + private boolean eglQueryStringAvailable; + private EGLExt eglExt; + // Table that holds the addresses of the native C-language entry points for + // EGL extension functions. + private EGLExtProcAddressTable eglExtProcAddressTable; + + public EGLContext(GLDrawableImpl drawable, GLDrawableImpl drawableRead, + GLContext shareWith) { + super(drawable, drawableRead, shareWith); + } + + public EGLContext(GLDrawableImpl drawable, + GLContext shareWith) { + this(drawable, null, shareWith); + } + + public Object getPlatformGLExtensions() { + return getEGLExt(); + } + + public EGLExt getEGLExt() { + if (eglExt == null) { + eglExt = new EGLExtImpl(this); + } + return eglExt; + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return eglExtProcAddressTable; + } + + public final EGLExtProcAddressTable getEGLExtProcAddressTable() { + return eglExtProcAddressTable; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return null; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return null; } + + public long getContext() { + return eglContext; + } + + protected int makeCurrentImpl() throws GLException { + if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) { + throw new GLException("drawable not properly initialized: "+drawable); + } + boolean created = false; + if (eglContext == 0) { + create(); + created = true; + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context 0x" + + Long.toHexString(eglContext) + " for " + getClass().getName()); + } + } + if (EGL.eglGetCurrentContext() != eglContext) { + if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), + ((EGLDrawable)drawable).getSurface(), + ((EGLDrawable)drawableRead).getSurface(), + eglContext)) { + throw new GLException("Error making context 0x" + + Long.toHexString(eglContext) + " current: error code " + EGL.eglGetError()); + } + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_ES|CTX_PROFILE_CORE|CTX_OPTION_ANY); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), + EGL.EGL_NO_SURFACE, + EGL.EGL_NO_SURFACE, + EGL.EGL_NO_CONTEXT)) { + throw new GLException("Error freeing OpenGL context 0x" + + Long.toHexString(eglContext) + ": error code " + EGL.eglGetError()); + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected void destroyImpl() throws GLException { + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (eglContext != 0) { + if (!EGL.eglDestroyContext(((EGLDrawable)drawable).getDisplay(), eglContext)) { + throw new GLException("Error destroying OpenGL context 0x" + + Long.toHexString(eglContext) + ": error code " + EGL.eglGetError()); + } + eglContext = 0; + GLContextShareSet.contextDestroyed(this); + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + return 0; // FIXME + } + + protected void destroyContextARBImpl(long _context) { + // FIXME + } + + protected void create() throws GLException { + long eglDisplay = ((EGLDrawable)drawable).getDisplay(); + EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration(); + GLProfile glProfile = drawable.getGLProfile(); + long eglConfig = config.getNativeConfig(); + long shareWith = EGL.EGL_NO_CONTEXT; + + if (eglDisplay == 0) { + throw new GLException("Error: attempted to create an OpenGL context without a display connection"); + } + if (eglConfig == 0) { + throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration"); + } + + try { + // might be unavailable on EGL < 1.2 + if(!EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API)) { + throw new GLException("eglBindAPI to ES failed , error 0x"+Integer.toHexString(EGL.eglGetError())); + } + } catch (GLException glex) { + if (DEBUG) { + glex.printStackTrace(); + } + } + + EGLContext other = (EGLContext) GLContextShareSet.getShareContext(this); + if (other != null) { + shareWith = other.getContext(); + if (shareWith == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + + int[] contextAttrs = new int[] { + EGL.EGL_CONTEXT_CLIENT_VERSION, -1, + EGL.EGL_NONE + }; + if (glProfile.usesNativeGLES2()) { + contextAttrs[1] = 2; + } else if (glProfile.usesNativeGLES1()) { + contextAttrs[1] = 1; + } else { + throw new GLException("Error creating OpenGL context - invalid GLProfile: "+glProfile); + } + eglContext = EGL.eglCreateContext(eglDisplay, eglConfig, shareWith, contextAttrs, 0); + if (eglContext == 0) { + throw new GLException("Error creating OpenGL context: eglDisplay 0x"+Long.toHexString(eglDisplay)+ + ", "+glProfile+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + GLContextShareSet.contextCreated(this); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created OpenGL context 0x" + + Long.toHexString(eglContext) + + ",\n\twrite surface 0x" + Long.toHexString(((EGLDrawable)drawable).getSurface()) + + ",\n\tread surface 0x" + Long.toHexString(((EGLDrawable)drawableRead).getSurface())+ + ",\n\t"+this+ + ",\n\tsharing with 0x" + Long.toHexString(shareWith)); + } + if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), + ((EGLDrawable)drawable).getSurface(), + ((EGLDrawable)drawableRead).getSurface(), + eglContext)) { + throw new GLException("Error making context 0x" + + Long.toHexString(eglContext) + " current: error code " + EGL.eglGetError()); + } + setGLFunctionAvailability(true, glProfile.usesNativeGLES2()?2:1, 0, CTX_PROFILE_ES|CTX_PROFILE_CORE|CTX_OPTION_ANY); + } + + public boolean isCreated() { + return (eglContext != 0); + } + + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing EGL extension address table"); + } + eglQueryStringInitialized = false; + eglQueryStringAvailable = false; + + if (eglExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + eglExtProcAddressTable = new EGLExtProcAddressTable(); + } + resetProcAddressTable(getEGLExtProcAddressTable()); + super.updateGLProcAddressTable(major, minor, ctp); + } + + public synchronized String getPlatformExtensionsString() { + if (!eglQueryStringInitialized) { + eglQueryStringAvailable = + getDrawableImpl().getDynamicLookupHelper().dynamicLookupFunction("eglQueryString") != 0; + eglQueryStringInitialized = true; + } + if (eglQueryStringAvailable) { + GLDrawableFactoryImpl factory = getDrawableImpl().getFactoryImpl(); + factory.lockToolkit(); + try { + String ret = EGL.eglQueryString(((EGLDrawable)drawable).getDisplay(), + EGL.EGL_EXTENSIONS); + if (DEBUG) { + System.err.println("!!! EGL extensions: " + ret); + } + return ret; + } finally { + factory.unlockToolkit(); + } + } else { + return ""; + } + } + + protected void setSwapIntervalImpl(int interval) { + if (EGL.eglSwapInterval(((EGLDrawable)drawable).getDisplay(), interval)) { + currentSwapInterval = interval ; + } + } + + public abstract void bindPbufferToTexture(); + + public abstract void releasePbufferFromTexture(); + + //---------------------------------------------------------------------- + // Currently unimplemented stuff + // + + public void copy(GLContext source, int mask) throws GLException { + throw new GLException("Not yet implemented"); + } + + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java new file mode 100755 index 000000000..dcfe06bdc --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import com.jogamp.common.os.DynamicLookupHelper; +import com.jogamp.opengl.impl.GLDrawableImpl; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; +import javax.media.opengl.*; + +public abstract class EGLDrawable extends GLDrawableImpl { + protected boolean ownEGLDisplay = false; // for destruction + protected boolean ownEGLSurface = false; // for destruction + private EGLGraphicsConfiguration eglConfig; + protected long eglDisplay; + protected long eglSurface; + + protected EGLDrawable(EGLDrawableFactory factory, + NativeWindow component) throws GLException { + super(factory, component, false); + eglSurface=EGL.EGL_NO_SURFACE; + eglDisplay=0; + } + + public long getDisplay() { + return eglDisplay; + } + + public long getSurface() { + return eglSurface; + } + + public EGLGraphicsConfiguration getGraphicsConfiguration() { + return eglConfig; + } + + public GLCapabilities getChosenGLCapabilities() { + return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilities)eglConfig.getChosenCapabilities(); + } + + public abstract GLContext createContext(GLContext shareWith); + + protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle); + + private void recreateSurface() { + // create a new EGLSurface .. + if(EGL.EGL_NO_SURFACE!=eglSurface) { + EGL.eglDestroySurface(eglDisplay, eglSurface); + } + + if(DEBUG) { + System.err.println("createSurface using eglDisplay 0x"+Long.toHexString(eglDisplay)+", "+eglConfig); + } + + eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), component.getSurfaceHandle()); + if (EGL.EGL_NO_SURFACE==eglSurface) { + throw new GLException("Creation of window surface failed: "+eglConfig+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + + if(DEBUG) { + System.err.println("setSurface using component: handle 0x"+Long.toHexString(component.getSurfaceHandle())+" -> 0x"+Long.toHexString(eglSurface)); + } + } + + protected void setRealizedImpl() { + if (realized) { + if ( NativeWindow.LOCK_SURFACE_NOT_READY == lockSurface() ) { + throw new GLException("Couldn't lock surface"); + } + // lockSurface() also resolved the window/surface handles + try { + AbstractGraphicsConfiguration aConfig = component.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); + if(aDevice instanceof EGLGraphicsDevice) { + // just fetch the data .. trust but verify .. + eglDisplay = aDevice.getHandle(); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display in EGLGraphicsDevice from "+aDevice); + } + if(aConfig instanceof EGLGraphicsConfiguration) { + eglConfig = (EGLGraphicsConfiguration) aConfig; // done .. + if (null == eglConfig) { + throw new GLException("Null EGLGraphicsConfiguration from "+aConfig); + } + + int[] tmp = new int[1]; + if ( 0 != component.getSurfaceHandle() && + EGL.eglQuerySurface(eglDisplay, component.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { + // component holds static EGLSurface + eglSurface = component.getSurfaceHandle(); + if(DEBUG) { + System.err.println("setSurface re-using component's EGLSurface: handle 0x"+Long.toHexString(eglSurface)); + } + } else { + // EGLSurface is ours .. + ownEGLSurface=true; + + eglConfig.updateGraphicsConfiguration(); + + recreateSurface(); + } + } else { + throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig); + } + } else { + // create a new EGL config .. + ownEGLDisplay=true; + // EGLSurface is ours .. + ownEGLSurface=true; + + long nDisplay=0; + if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) { + nDisplay = component.getSurfaceHandle(); // don't even ask .. + } else { + nDisplay = aDevice.getHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY + } + eglDisplay = EGL.eglGetDisplay(nDisplay); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + if(DEBUG) { + System.err.println("eglDisplay("+Long.toHexString(nDisplay)+" <surfaceHandle>): failed, using EGL_DEFAULT_DISPLAY"); + } + nDisplay = EGL.EGL_DEFAULT_DISPLAY; + eglDisplay = EGL.eglGetDisplay(nDisplay); + } + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL display: nhandle 0x"+Long.toHexString(nDisplay)+", "+aDevice+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("eglDisplay("+Long.toHexString(nDisplay)+"): 0x"+Long.toHexString(eglDisplay)); + } + if (!EGL.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay); + DefaultGraphicsScreen s = new DefaultGraphicsScreen(e, aConfig.getScreen().getIndex()); + GLCapabilities caps = (GLCapabilities) aConfig.getChosenCapabilities(); // yes, use the already choosen Capabilities (x11,win32,..) + eglConfig = (EGLGraphicsConfiguration) GraphicsConfigurationFactory.getFactory(e).chooseGraphicsConfiguration(caps, null, s); + if (null == eglConfig) { + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s); + } else if(DEBUG) { + System.err.println("Chosen eglConfig: "+eglConfig); + } + recreateSurface(); + } + } finally { + unlockSurface(); + } + } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) { + // Destroy the window surface + if (!EGL.eglDestroySurface(eglDisplay, eglSurface)) { + throw new GLException("Error destroying window surface (eglDestroySurface)"); + } + eglSurface = EGL.EGL_NO_SURFACE; + if (ownEGLDisplay && EGL.EGL_NO_DISPLAY!=eglDisplay) { + EGL.eglTerminate(eglDisplay); + } + eglDisplay=EGL.EGL_NO_DISPLAY; + eglConfig=null; + } + } + + public int getWidth() { + int[] tmp = new int[1]; + if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) { + throw new GLException("Error querying surface width"); + } + return tmp[0]; + } + + public int getHeight() { + int[] tmp = new int[1]; + if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) { + throw new GLException("Error querying surface height"); + } + return tmp[0]; + } + + public DynamicLookupHelper getDynamicLookupHelper() { + return EGLDynamicLookupHelper.getDynamicLookupHelper(getGLProfile()); + } + + public String toString() { + return getClass().getName()+"[realized "+getRealized()+ + ",\n\tfactory "+getFactory()+ + ",\n\twindow "+getNativeWindow()+ + ",\n\teglSurface 0x"+Long.toHexString(eglSurface)+ + ",\n\teglConfig "+eglConfig+ + ",\n\trequested "+getRequestedGLCapabilities()+ + ",\n\tchosen "+getChosenGLCapabilities()+"]"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java new file mode 100755 index 000000000..4fccf22f8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class EGLDrawableFactory extends GLDrawableFactoryImpl { + + static { + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new EGLGraphicsConfigurationFactory(); + + // Check for other underlying stuff .. + if(NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) { + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.x11.glx.X11GLXGraphicsConfigurationFactory"); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + } + } + + public EGLDrawableFactory() { + super(); + } + + + protected final GLDrawableImpl getSharedDrawable() { return null; } + protected final GLContextImpl getSharedContext() { return null; } + + public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new EGLOnscreenDrawable(this, target); + } + + protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + throw new GLException("Not yet implemented"); + } + + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + return true; + } + + protected GLDrawableImpl createGLPbufferDrawableImpl(NativeWindow target) { + return new EGLPbufferDrawable(this, target); + } + + protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { + NullWindow nw = new NullWindow(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(capabilities, chooser)); + nw.setSize(width, height); + return nw; + } + + public GLContext createExternalGLContext() { + AbstractGraphicsScreen absScreen = DefaultGraphicsScreen.createScreenDevice(0); + return new EGLExternalContext(absScreen); + } + + public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + return false; + } + + public GLDrawable createExternalGLDrawable() { + throw new GLException("Not yet implemented"); + } + + public void loadGLULibrary() { + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + throw new GLException("Unimplemented on this platform"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java new file mode 100755 index 000000000..9e34dc9e9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import com.jogamp.common.os.DynamicLookupHelper; +import com.jogamp.common.os.NativeLibrary; +import java.util.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import java.security.*; + +/** + * Abstract implementation of the DynamicLookupHelper for EGL, + * which decouples it's dependencies to EGLDrawableFactory. + * + * Currently two implementations exist, one for ES1 and one for ES2. + */ +public abstract class EGLDynamicLookupHelper implements DynamicLookupHelper { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("EGL"); + protected static final boolean DEBUG_LOOKUP; + + private static final EGLDynamicLookupHelper eglES1DynamicLookupHelper; + private static final EGLDynamicLookupHelper eglES2DynamicLookupHelper; + private List/*<NativeLibrary>*/ glesLibraries; + + static { + AccessControlContext localACC=AccessController.getContext(); + DEBUG_LOOKUP = com.jogamp.opengl.impl.Debug.isPropertyDefined("jogl.debug.DynamicLookup", true, localACC); + + EGLDynamicLookupHelper tmp=null; + try { + tmp = new EGLES1DynamicLookupHelper(); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + eglES1DynamicLookupHelper = tmp; + + tmp=null; + try { + tmp = new EGLES2DynamicLookupHelper(); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + eglES2DynamicLookupHelper = tmp; + } + + public static EGLDynamicLookupHelper getDynamicLookupHelper(GLProfile glp) { + if (glp.usesNativeGLES2()) { + if(null==eglES2DynamicLookupHelper) { + throw new GLException("EGLDynamicLookupHelper for ES2 not available"); + } + return eglES2DynamicLookupHelper; + } else if (glp.usesNativeGLES1()) { + if(null==eglES1DynamicLookupHelper) { + throw new GLException("EGLDynamicLookupHelper for ES1 not available"); + } + return eglES1DynamicLookupHelper; + } else { + throw new GLException("Unsupported: "+glp); + } + } + + public static EGLDynamicLookupHelper getDynamicLookupHelper(int esProfile) { + if (2==esProfile) { + if(null==eglES2DynamicLookupHelper) { + throw new GLException("EGLDynamicLookupHelper for ES2 not available"); + } + return eglES2DynamicLookupHelper; + } else if (1==esProfile) { + if(null==eglES1DynamicLookupHelper) { + throw new GLException("EGLDynamicLookupHelper for ES1 not available"); + } + return eglES1DynamicLookupHelper; + } else { + throw new GLException("Unsupported: ES"+esProfile); + } + } + + protected EGLDynamicLookupHelper() { + loadGLESLibrary(getESProfile()); + EGL.resetProcAddressTable(this); + } + + /** Must return the proper ES profile number, 1 for ES1 and 2 for ES2 */ + protected abstract int getESProfile(); + + /** Must return at least one OpenGL ES library name */ + protected abstract List/*<String>*/ getGLESLibNames(); + + /** May return OpenGL ES library name(s) */ + protected List/*<String>*/ getEGLLibNames() { + List/*<String>*/ eglLibNames = new ArrayList(); + + // EGL + eglLibNames.add("EGL"); + // for windows distributions using the 'unlike' lib prefix, + // where our tool does not add it. + eglLibNames.add("libEGL"); + + return eglLibNames; + } + + private NativeLibrary loadFirstAvailable(List/*<String>*/ libNames, ClassLoader loader) { + for (Iterator iter = libNames.iterator(); iter.hasNext(); ) { + NativeLibrary lib = NativeLibrary.open((String) iter.next(), loader, false /*global*/); + if (lib != null) { + return lib; + } + } + return null; + } + + private boolean loadEGLLibrary(ClassLoader loader, List/*<String>*/ eglLibNames) { + NativeLibrary lib = null; + if(null!=eglLibNames && eglLibNames.size()>0) { + // EGL libraries .. + lib = loadFirstAvailable(eglLibNames, loader); + if ( null != lib ) { + glesLibraries.add(lib); + } + } + return null!=lib; + } + + private void loadGLESLibrary(int esProfile) { + List/*<String>*/ glesLibNames = getGLESLibNames(); + List/*<String>*/ eglLibNames = getEGLLibNames(); + boolean eglLoaded = false; + + ClassLoader loader = getClass().getClassLoader(); + NativeLibrary lib = null; + + glesLibraries = new ArrayList(); + + // ES libraries .. + lib = loadFirstAvailable(glesLibNames, loader); + if ( null == lib ) { + /*** FIXME: Have to think about this .. + // try again with EGL loaded first .. + if ( !eglLoaded && loadEGLLibrary(loader, eglLibNames) ) { + eglLoaded = true ; + lib = loadFirstAvailable(glesLibNames, loader); + } + if ( null == lib ) { + throw new GLException("Unable to dynamically load OpenGL ES library for profile ES" + esProfile); + } */ + throw new GLException("Unable to dynamically load OpenGL ES library for profile ES" + esProfile); + } + glesLibraries.add(lib); + + if ( !eglLoaded && !loadEGLLibrary(loader, eglLibNames) ) { + throw new GLException("Unable to dynamically load EGL library for profile ES" + esProfile); + } + + if (esProfile==2) { + GLJNILibLoader.loadES2(); + } else if (esProfile==1) { + GLJNILibLoader.loadES1(); + } else { + throw new GLException("Unsupported: ES"+esProfile); + } + } + + private long dynamicLookupFunctionOnLibs(String glFuncName) { + String funcName=glFuncName; + long addr = dynamicLookupFunctionOnLibsImpl(funcName); + if( 0==addr && NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) { + // Hack: try some C++ decoration here for Imageon's emulation libraries .. + final int argAlignment=4; // 4 byte alignment of each argument + final int maxArguments=12; // experience .. + for(int arg=0; 0==addr && arg<=maxArguments; arg++) { + funcName = "_"+glFuncName+"@"+(arg*argAlignment); + addr = dynamicLookupFunctionOnLibsImpl(funcName); + } + } + if(DEBUG_LOOKUP) { + if(0!=addr) { + System.err.println("Lookup-Native: "+glFuncName+" / "+funcName+" 0x"+Long.toHexString(addr)); + } else { + System.err.println("Lookup-Native: "+glFuncName+" / "+funcName+" ** FAILED ** "); + } + } + return addr; + } + + private long dynamicLookupFunctionOnLibsImpl(String glFuncName) { + // Look up this function name in all known libraries + for (Iterator iter = glesLibraries.iterator(); iter.hasNext(); ) { + NativeLibrary lib = (NativeLibrary) iter.next(); + long addr = lib.dynamicLookupFunction(glFuncName); + if (addr != 0) { + return addr; + } + } + return 0; + } + + private long eglGetProcAddressHandle = 0; + + public long dynamicLookupFunction(String glFuncName) { + if(null==glFuncName) { + return 0; + } + + // bootstrap eglGetProcAddress + if(0==eglGetProcAddressHandle) { + eglGetProcAddressHandle = dynamicLookupFunctionOnLibs("eglGetProcAddress"); + if(0==eglGetProcAddressHandle) { + GLException e = new GLException("Couldn't find eglGetProcAddress function entry"); + if(DEBUG) { + e.printStackTrace(); + } + throw e; + } + } + + if(glFuncName.equals("eglGetProcAddress")) { + return eglGetProcAddressHandle; + } + + long addr = EGL.eglGetProcAddress(eglGetProcAddressHandle, glFuncName); + if(DEBUG_LOOKUP) { + if(0!=addr) { + System.err.println("Lookup-EGL: <"+glFuncName+"> 0x"+Long.toHexString(addr)); + } + } + if(0==addr) { + addr = dynamicLookupFunctionOnLibs(glFuncName); + } + return addr; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java new file mode 100755 index 000000000..e5740a4f0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import java.util.*; + +/** + * Implementation of the EGLDynamicLookupHelper for ES1. + */ +public class EGLES1DynamicLookupHelper extends EGLDynamicLookupHelper { + + protected EGLES1DynamicLookupHelper() { + super(); + } + + protected int getESProfile() { + return 1; + } + + protected List/*<String>*/ getGLESLibNames() { + List/*<String>*/ glesLibNames = new ArrayList(); + + glesLibNames.add("GLES_CM"); + glesLibNames.add("GLES_CL"); + glesLibNames.add("GLESv1_CM"); + // for windows distributions using the 'unlike' lib prefix, + // where our tool does not add it. + glesLibNames.add("libGLES_CM"); + glesLibNames.add("libGLES_CL"); + glesLibNames.add("libGLESv1_CM"); + + return glesLibNames; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java new file mode 100755 index 000000000..c4fc66630 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import java.util.*; + +/** + * Implementation of the EGLDynamicLookupHelper for ES2. + */ +public class EGLES2DynamicLookupHelper extends EGLDynamicLookupHelper { + + protected EGLES2DynamicLookupHelper() { + super(); + } + + protected int getESProfile() { + return 2; + } + + protected List/*<String>*/ getGLESLibNames() { + List/*<String>*/ glesLibNames = new ArrayList(); + + glesLibNames.add("GLES20"); + glesLibNames.add("GLESv2"); + glesLibNames.add("GLESv2_CM"); + // for windows distributions using the 'unlike' lib prefix + // where our tool does not add it. + glesLibNames.add("libGLES20"); + glesLibNames.add("libGLESv2"); + glesLibNames.add("libGLESv2_CM"); + + return glesLibNames; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLExternalContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLExternalContext.java new file mode 100755 index 000000000..5a8454ea7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLExternalContext.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import javax.media.nativewindow.*; + +public class EGLExternalContext extends EGLContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + public EGLExternalContext(AbstractGraphicsScreen screen) { + super(null, null); + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_IS_ARB_CREATED|CTX_PROFILE_ES|CTX_PROFILE_CORE|CTX_OPTION_ANY); + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java new file mode 100644 index 000000000..2d5154442 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import com.jogamp.common.nio.PointerBuffer; +import java.util.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { + protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + + public long getNativeConfig() { + return config; + } + + public int getNativeConfigID() { + return configID; + } + + public EGLGraphicsConfiguration(AbstractGraphicsScreen absScreen, + GLCapabilities capsChosen, GLCapabilities capsRequested, GLCapabilitiesChooser chooser, + long cfg, int cfgID) { + super(absScreen, capsChosen, capsRequested); + this.chooser = chooser; + config = cfg; + configID = cfgID; + } + + public static EGLGraphicsConfiguration create(GLCapabilities capsRequested, AbstractGraphicsScreen absScreen, int cfgID) { + AbstractGraphicsDevice absDevice = absScreen.getDevice(); + if(null==absDevice || !(absDevice instanceof EGLGraphicsDevice)) { + throw new GLException("GraphicsDevice must be a valid EGLGraphicsDevice"); + } + long dpy = absDevice.getHandle(); + if (dpy == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display: "+absDevice); + } + GLProfile glp = capsRequested.getGLProfile(); + long cfg = EGLConfigId2EGLConfig(glp, dpy, cfgID); + GLCapabilities caps = EGLConfig2Capabilities(glp, dpy, cfg, false, capsRequested.isOnscreen(), capsRequested.isPBuffer()); + return new EGLGraphicsConfiguration(absScreen, caps, capsRequested, new DefaultGLCapabilitiesChooser(), cfg, cfgID); + } + + public Object clone() { + return super.clone(); + } + + protected void updateGraphicsConfiguration() { + EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(getRequestedCapabilities(), + chooser, + getScreen()); + if(null!=newConfig) { + // FIXME: setScreen( ... ); + setChosenCapabilities(newConfig.getChosenCapabilities()); + config = newConfig.getNativeConfig(); + configID = newConfig.getNativeConfigID(); + if(DEBUG) { + System.err.println("!!! updateGraphicsConfiguration: "+this); + } + } + } + + public static long EGLConfigId2EGLConfig(GLProfile glp, long display, int configID) { + int[] attrs = new int[] { + EGL.EGL_CONFIG_ID, configID, + EGL.EGL_NONE + }; + PointerBuffer configs = PointerBuffer.allocateDirect(1); + int[] numConfigs = new int[1]; + if (!EGL.eglChooseConfig(display, + attrs, 0, + configs, 1, + numConfigs, 0)) { + return 0; + } + if (numConfigs[0] == 0) { + return 0; + } + return configs.get(0); + } + + public static boolean EGLConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { + boolean res; + + if ( onscreen ) { + res = ( 0 != (val & EGL.EGL_WINDOW_BIT) ) ; + } else { + if ( usePBuffer ) { + res = ( 0 != (val & EGL.EGL_PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & EGL.EGL_PIXMAP_BIT) ) ; + } + } + + return res; + } + + public static GLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config, + boolean relaxed, boolean onscreen, boolean usePBuffer) { + GLCapabilities caps = new GLCapabilities(glp); + int[] val = new int[1]; + + // Read the actual configuration into the choosen caps + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val, 0)) { + caps.setRedBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val, 0)) { + caps.setGreenBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val, 0)) { + caps.setBlueBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val, 0)) { + caps.setAlphaBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val, 0)) { + caps.setStencilBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val, 0)) { + caps.setDepthBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SAMPLES, val, 0)) { + caps.setSampleBuffers(val[0]>0?true:false); + caps.setNumSamples(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_TYPE, val, 0)) { + caps.setBackgroundOpaque(val[0] != EGL.EGL_TRANSPARENT_RGB); + } + if(!caps.isBackgroundOpaque()) { + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_RED_VALUE, val, 0)) { + caps.setTransparentRedValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_GREEN_VALUE, val, 0)) { + caps.setTransparentGreenValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_BLUE_VALUE, val, 0)) { + caps.setTransparentBlueValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); + } + /** Not defined in EGL + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_ALPHA_VALUE, val, 0)) { + caps.setTransparentAlphaValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); + } */ + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SURFACE_TYPE, val, 0)) { + if(EGLConfigDrawableTypeVerify(val[0], onscreen, usePBuffer)) { + caps.setDoubleBuffered(onscreen); + caps.setOnscreen(onscreen); + caps.setPBuffer(usePBuffer); + } else if(relaxed) { + caps.setDoubleBuffered( 0 != (val[0] & EGL.EGL_WINDOW_BIT) ); + caps.setOnscreen( 0 != (val[0] & EGL.EGL_WINDOW_BIT) ); + caps.setPBuffer ( 0 != (val[0] & EGL.EGL_PBUFFER_BIT) ); + } else { + if(DEBUG) { + System.err.println("EGL_SURFACE_TYPE does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (val[0] & EGL.EGL_WINDOW_BIT) )+", pbuffer "+( 0 != (val[0] & EGL.EGL_PBUFFER_BIT) )+", pixmap "+( 0 != (val[0] & EGL.EGL_PIXMAP_BIT) )+")"); + } + return null; + } + } else { + throw new GLException("Could not determine EGL_SURFACE_TYPE !!!"); + } + + return caps; + } + + public static int[] GLCapabilities2AttribList(GLCapabilities caps) { + int[] attrs = new int[32]; + int idx=0; + + attrs[idx++] = EGL.EGL_SURFACE_TYPE; + attrs[idx++] = caps.isOnscreen() ? ( EGL.EGL_WINDOW_BIT ) : ( caps.isPBuffer() ? EGL.EGL_PBUFFER_BIT : EGL.EGL_PIXMAP_BIT ) ; + + attrs[idx++] = EGL.EGL_RED_SIZE; + attrs[idx++] = caps.getRedBits(); + + attrs[idx++] = EGL.EGL_GREEN_SIZE; + attrs[idx++] = caps.getGreenBits(); + + attrs[idx++] = EGL.EGL_BLUE_SIZE; + attrs[idx++] = caps.getBlueBits(); + + attrs[idx++] = EGL.EGL_ALPHA_SIZE; + attrs[idx++] = caps.getAlphaBits() > 0 ? caps.getAlphaBits() : EGL.EGL_DONT_CARE; + + attrs[idx++] = EGL.EGL_STENCIL_SIZE; + attrs[idx++] = caps.getStencilBits() > 0 ? caps.getStencilBits() : EGL.EGL_DONT_CARE; + + attrs[idx++] = EGL.EGL_DEPTH_SIZE; + attrs[idx++] = caps.getDepthBits(); + + attrs[idx++] = EGL.EGL_SAMPLES; + attrs[idx++] = caps.getSampleBuffers() ? caps.getNumSamples() : 1; + + attrs[idx++] = EGL.EGL_TRANSPARENT_TYPE; + attrs[idx++] = caps.isBackgroundOpaque() ? EGL.EGL_NONE : EGL.EGL_TRANSPARENT_TYPE; + + // 20 + + if(!caps.isBackgroundOpaque()) { + attrs[idx++] = EGL.EGL_TRANSPARENT_RED_VALUE; + attrs[idx++] = caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():EGL.EGL_DONT_CARE; + + attrs[idx++] = EGL.EGL_TRANSPARENT_GREEN_VALUE; + attrs[idx++] = caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():EGL.EGL_DONT_CARE; + + attrs[idx++] = EGL.EGL_TRANSPARENT_BLUE_VALUE; + attrs[idx++] = caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():EGL.EGL_DONT_CARE; + + /** Not define in EGL + attrs[idx++] = EGL.EGL_TRANSPARENT_ALPHA_VALUE; + attrs[idx++] = caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():EGL.EGL_DONT_CARE; */ + } + + // 26 + + attrs[idx++] = EGL.EGL_RENDERABLE_TYPE; + if(caps.getGLProfile().usesNativeGLES1()) { + attrs[idx++] = EGL.EGL_OPENGL_ES_BIT; + } + else if(caps.getGLProfile().usesNativeGLES2()) { + attrs[idx++] = EGL.EGL_OPENGL_ES2_BIT; + } else { + attrs[idx++] = EGL.EGL_OPENGL_BIT; + } + + // 28 + + attrs[idx++] = EGL.EGL_NONE; + + return attrs; + } + + public static int[] CreatePBufferSurfaceAttribList(int width, int height, int texFormat) { + int[] attrs = new int[16]; + int idx=0; + + attrs[idx++] = EGL.EGL_WIDTH; + attrs[idx++] = width; + + attrs[idx++] = EGL.EGL_HEIGHT; + attrs[idx++] = height; + + attrs[idx++] = EGL.EGL_TEXTURE_FORMAT; + attrs[idx++] = texFormat; + + attrs[idx++] = EGL.EGL_TEXTURE_TARGET; + attrs[idx++] = EGL.EGL_NO_TEXTURE==texFormat ? EGL.EGL_NO_TEXTURE : EGL.EGL_TEXTURE_2D; + + attrs[idx++] = EGL.EGL_NONE; + + return attrs; + } + + public String toString() { + return getClass().toString()+"["+getScreen()+", eglConfigID 0x"+Integer.toHexString(configID)+ + ",\n\trequested " + getRequestedCapabilities()+ + ",\n\tchosen " + getChosenCapabilities()+ + "]"; + + } + + private GLCapabilitiesChooser chooser; + private long config; + private int configID; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..33e301ee9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.egl; + +import com.jogamp.common.nio.PointerBuffer; +import java.io.PrintStream; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; + +import javax.media.opengl.*; + + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on X11 platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class EGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = GraphicsConfigurationFactory.DEBUG || com.jogamp.opengl.impl.Debug.debug("EGL"); + + public EGLGraphicsConfigurationFactory() { + // become the selector for KD/EGL .. + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.egl.EGLGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if (absScreen == null) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects"); + } + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + + return chooseGraphicsConfigurationStatic((GLCapabilities) capabilities, + (GLCapabilitiesChooser) chooser, + absScreen); + } + + public static EGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if (capabilities == null) { + capabilities = new GLCapabilities(null); + } + GLProfile glp = capabilities.getGLProfile(); + + if(null==absScreen) { + throw new GLException("Null AbstractGraphicsScreen"); + } + AbstractGraphicsDevice absDevice = absScreen.getDevice(); + + if(null==absDevice || !(absDevice instanceof EGLGraphicsDevice)) { + throw new GLException("GraphicsDevice must be a valid EGLGraphicsDevice"); + } + long eglDisplay = absDevice.getHandle(); + + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display: "+absDevice); + } + + GLCapabilities caps2 = (GLCapabilities) capabilities.clone(); + if(!caps2.isOnscreen()) { + // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN + caps2.setDoubleBuffered(false); + } + + EGLGraphicsConfiguration res = eglChooseConfig(eglDisplay, caps2, capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + if(DEBUG) { + System.err.println("eglChooseConfig failed with given capabilities "+caps2); + } + + if (chooser == null) { + chooser = new DefaultGLCapabilitiesChooser(); + } + + PointerBuffer configs = PointerBuffer.allocateDirect(10); + int[] numConfigs = new int[1]; + + if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs, 0)) { + throw new GLException("Graphics configuration fetch (eglGetConfigs) failed"); + } + if (numConfigs[0] == 0) { + throw new GLException("Graphics configuration fetch (eglGetConfigs) - no EGLConfig found"); + } + GLCapabilities[] caps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], + caps2.isOnscreen(), caps2.isPBuffer()); + if(DEBUG) { + System.err.println("EGL Get Configs: "+numConfigs[0]+", Caps "+caps.length); + printCaps("eglGetConfigs", caps, System.err); + } + int chosen = -1; + try { + chosen = chooser.chooseCapabilities(caps2, caps, -1); + } catch (NativeWindowException e) { throw new GLException(e); } + if(chosen<0) { + throw new GLException("Graphics configuration chooser failed"); + } + if(DEBUG) { + System.err.println("Chosen "+caps[chosen]); + } + res = eglChooseConfig(eglDisplay, caps[chosen], capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + if(DEBUG) { + System.err.println("eglChooseConfig failed with eglGetConfig/choosen capabilities "+caps[chosen]); + } + + // Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..] + // + // rgb888 - d16, s4 + GLCapabilities fixedCaps = new GLCapabilities(glp); + fixedCaps.setRedBits(8); + fixedCaps.setGreenBits(8); + fixedCaps.setBlueBits(8); + fixedCaps.setDepthBits(16); + fixedCaps.setSampleBuffers(true); + fixedCaps.setNumSamples(4); + if(DEBUG) { + System.err.println("trying fixed caps (1): "+fixedCaps); + } + res = eglChooseConfig(eglDisplay, fixedCaps, capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + + // + // rgb565 - d16, s0 + fixedCaps = new GLCapabilities(glp); + fixedCaps.setRedBits(5); + fixedCaps.setGreenBits(6); + fixedCaps.setBlueBits(5); + fixedCaps.setDepthBits(16); + if(DEBUG) { + System.err.println("trying fixed caps (2): "+fixedCaps); + } + res = eglChooseConfig(eglDisplay, fixedCaps, capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + + // + // rgb565 - d16, s4 + fixedCaps = new GLCapabilities(glp); + fixedCaps.setRedBits(5); + fixedCaps.setGreenBits(6); + fixedCaps.setBlueBits(5); + fixedCaps.setDepthBits(16); + fixedCaps.setSampleBuffers(true); + fixedCaps.setNumSamples(4); + if(DEBUG) { + System.err.println("trying fixed caps (3): "+fixedCaps); + } + res = eglChooseConfig(eglDisplay, fixedCaps, capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + throw new GLException("Graphics configuration failed [direct caps, eglGetConfig/chooser and fixed-caps(1-3)]"); + } + + protected static EGLGraphicsConfiguration eglChooseConfig(long eglDisplay, + GLCapabilities capsChosen0, GLCapabilities capsRequested, GLCapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GLProfile glp = capsChosen0.getGLProfile(); + int[] attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen0); + PointerBuffer configs = PointerBuffer.allocateDirect(1); + int[] numConfigs = new int[1]; + if (!EGL.eglChooseConfig(eglDisplay, + attrs, 0, + configs, configs.capacity(), + numConfigs, 0)) { + throw new GLException("Graphics configuration selection (eglChooseConfig) failed for "+capsChosen0); + } + if (numConfigs[0] > 0) { + if(DEBUG) { + GLCapabilities[] caps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], + capsChosen0.isOnscreen(), capsChosen0.isPBuffer()); + System.err.println("EGL Choose Configs: "+numConfigs[0]+", Caps "+caps.length); + printCaps("eglChooseConfig", caps, System.err); + } + int[] val = new int[1]; + // get the configID + if(!EGL.eglGetConfigAttrib(eglDisplay, configs.get(0), EGL.EGL_CONFIG_ID, val, 0)) { + if(DEBUG) { + // FIXME: this happens on a ATI PC Emulation .. + System.err.println("EGL couldn't retrieve ConfigID for already chosen eglConfig "+capsChosen0+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + return null; + } + GLCapabilities capsChosen1 = EGLGraphicsConfiguration.EGLConfig2Capabilities(glp, eglDisplay, configs.get(0), + true, capsChosen0.isOnscreen(), capsChosen0.isPBuffer()); + if(null!=capsChosen1) { + if(DEBUG) { + System.err.println("eglChooseConfig found: eglDisplay 0x"+Long.toHexString(eglDisplay)+ + ", eglConfig ID 0x"+Integer.toHexString(val[0])+ + ", "+capsChosen0+" -> "+capsChosen1); + } + return new EGLGraphicsConfiguration(absScreen, capsChosen1, capsRequested, chooser, configs.get(0), val[0]); + } + if(DEBUG) { + System.err.println("eglChooseConfig couldn't verify: eglDisplay 0x"+Long.toHexString(eglDisplay)+ + ", eglConfig ID 0x"+Integer.toHexString(val[0])+ + ", for "+capsChosen0); + } + } else { + if(DEBUG) { + System.err.println("EGL Choose Configs: None using eglDisplay 0x"+Long.toHexString(eglDisplay)+ + ", "+capsChosen0); + } + } + return null; + } + + protected static GLCapabilities[] eglConfigs2GLCaps(GLProfile glp, long eglDisplay, PointerBuffer configs, int num, + boolean onscreen, boolean usePBuffer) { + GLCapabilities[] caps = new GLCapabilities[num]; + for(int i=0; i<num; i++) { + caps[i] = EGLGraphicsConfiguration.EGLConfig2Capabilities(glp, eglDisplay, configs.get(i), + true, onscreen, usePBuffer); + } + return caps; + } + + protected static void printCaps(String prefix, GLCapabilities[] caps, PrintStream out) { + for(int i=0; i<caps.length; i++) { + out.println(prefix+"["+i+"] "+caps[i]); + } + } + + protected static EGLGraphicsConfiguration createOffscreenGraphicsConfiguration(GLCapabilities caps, GLCapabilitiesChooser chooser) { + if(caps.isOnscreen()) { + throw new GLException("Error: Onscreen set: "+caps); + } + caps.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN + long eglDisplay = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("eglDisplay(EGL_DEFAULT_DISPLAY): 0x"+Long.toHexString(eglDisplay)); + } + if (!EGL.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay); + DefaultGraphicsScreen s = new DefaultGraphicsScreen(e, 0); + EGLGraphicsConfiguration eglConfig = chooseGraphicsConfigurationStatic(caps, chooser, s); + if (null == eglConfig) { + EGL.eglTerminate(eglDisplay); + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s); + } else if(DEBUG) { + System.err.println("Chosen eglConfig: "+eglConfig); + } + return eglConfig; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenContext.java new file mode 100755 index 000000000..b74991671 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenContext.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; +import java.nio.*; +import java.util.*; + +public class EGLOnscreenContext extends EGLContext { + public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) { + super(drawable, shareWith); + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + return super.makeCurrentImpl(); + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY) && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected void releaseImpl() throws GLException { + try { + super.releaseImpl(); + } finally { + if (!isOptimizable() && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java new file mode 100644 index 000000000..3864fc39c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java @@ -0,0 +1,80 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class EGLOnscreenDrawable extends EGLDrawable { + protected EGLOnscreenDrawable(EGLDrawableFactory factory, NativeWindow component) throws GLException { + super(factory, component); + } + + public GLContext createContext(GLContext shareWith) { + return new EGLOnscreenContext(this, shareWith); + } + + protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { + return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null); + } + + protected void swapBuffersImpl() { + boolean didLock = false; + if (!isSurfaceLocked()) { + // Usually the surface shall be locked within [makeCurrent .. swap .. release] + if (lockSurface() == NativeWindow.LOCK_SURFACE_NOT_READY) { + return; + } + didLock = true; + } + try { + EGL.eglSwapBuffers(eglDisplay, eglSurface); + } finally { + if (didLock) { + unlockSurface(); + } + } + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferContext.java new file mode 100755 index 000000000..5c634b9bd --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferContext.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; +import java.nio.*; +import java.util.*; + +public class EGLPbufferContext extends EGLContext { + public EGLPbufferContext(EGLPbufferDrawable drawable, GLContext shareWith) { + super(drawable, shareWith); + } + + public int getFloatingPointMode() { + return 0; // FIXME ?? + } + + public void bindPbufferToTexture() { + throw new GLException("Not yet implemented"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Not yet implemented"); + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferDrawable.java new file mode 100644 index 000000000..03b02b77e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferDrawable.java @@ -0,0 +1,99 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; +import com.jogamp.opengl.impl.*; + +public class EGLPbufferDrawable extends EGLDrawable { + private int texFormat; + protected static final boolean useTexture = false; // No yet .. + + protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeWindow target) { + super(factory, target); + ownEGLDisplay = true; + + // get choosen ones .. + GLCapabilities caps = (GLCapabilities) getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + + if(useTexture) { + this.texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; + } else { + this.texFormat = EGL.EGL_NO_TEXTURE; + } + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + setRealized(true); + + if (DEBUG) { + System.out.println("Created pbuffer: " + this); + } + + } + + protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { + NativeWindow nw = getNativeWindow(); + int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat); + long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0); + if (EGL.EGL_NO_SURFACE==surf) { + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+nw.getWidth()+"x"+nw.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); + } + ((SurfaceChangeable)nw).setSurfaceHandle(surf); + return surf; + } + + public GLContext createContext(GLContext shareWith) { + return new EGLPbufferContext(this, shareWith); + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/gl2/ProjectDouble.java b/src/jogl/classes/com/jogamp/opengl/impl/gl2/ProjectDouble.java new file mode 100755 index 000000000..2eb3ca5df --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/gl2/ProjectDouble.java @@ -0,0 +1,1041 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** $Date: 2009-03-13 22:20:29 -0700 (Fri, 13 Mar 2009) $ $Revision: 1867 $ +** $Header$ +*/ + +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * 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.impl.gl2; + +import java.nio.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +/** + * Project.java + * <p/> + * <p/> + * Created 11-jan-2004 + * + * @author Erik Duijs + * @author Kenneth Russell + */ +public class ProjectDouble { + private static final double[] IDENTITY_MATRIX = + new double[] { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 }; + + // Note that we have cloned parts of the implementation in order to + // support incoming Buffers. The reason for this is to avoid loading + // non-direct buffer subclasses unnecessarily, because doing so can + // cause performance decreases on direct buffer operations, at least + // on the current HotSpot JVM. It would be nicer (and make the code + // simpler) to simply have the array-based entry points delegate to + // the versions taking Buffers by wrapping the arrays. + + // Array-based implementation + private final double[] matrix = new double[16]; + + private final double[][] tempMatrix = new double[4][4]; + private final double[] in = new double[4]; + private final double[] out = new double[4]; + + private final double[] forward = new double[3]; + private final double[] side = new double[3]; + private final double[] up = new double[3]; + + // Buffer-based implementation + private DoubleBuffer locbuf; + private final DoubleBuffer matrixBuf; + + private final DoubleBuffer tempMatrixBuf; + private final DoubleBuffer inBuf; + private final DoubleBuffer outBuf; + + private final DoubleBuffer forwardBuf; + private final DoubleBuffer sideBuf; + private final DoubleBuffer upBuf; + + public ProjectDouble() { + // Use direct buffers to avoid loading indirect buffer + // implementations for applications trying to avoid doing so. + // Slice up one big buffer because some NIO implementations + // allocate a huge amount of memory to back even the smallest of + // buffers. + DoubleBuffer locbuf = InternalBufferUtil.newDoubleBuffer(128); + int pos = 0; + int sz = 16; + matrixBuf = slice(locbuf, pos, sz); + pos += sz; + tempMatrixBuf = slice(locbuf, pos, sz); + pos += sz; + sz = 4; + inBuf = slice(locbuf, pos, sz); + pos += sz; + outBuf = slice(locbuf, pos, sz); + pos += sz; + sz = 3; + forwardBuf = slice(locbuf, pos, sz); + pos += sz; + sideBuf = slice(locbuf, pos, sz); + pos += sz; + upBuf = slice(locbuf, pos, sz); + } + + public void destroy() { + if(locbuf!=null) { + locbuf.clear(); + locbuf=null; + } + } + + private static DoubleBuffer slice(DoubleBuffer buf, int pos, int len) { + buf.position(pos); + buf.limit(pos + len); + return buf.slice(); + } + + /** + * Make matrix an identity matrix + */ + private void __gluMakeIdentityd(DoubleBuffer m) { + int oldPos = m.position(); + m.put(IDENTITY_MATRIX); + m.position(oldPos); + } + + /** + * Make matrix an identity matrix + */ + private void __gluMakeIdentityd(double[] m) { + for (int i = 0; i < 16; i++) { + m[i] = IDENTITY_MATRIX[i]; + } + } + + /** + * Method __gluMultMatrixVecd + * + * @param matrix + * @param in + * @param out + */ + private void __gluMultMatrixVecd(double[] matrix, int matrix_offset, double[] in, double[] out) { + for (int i = 0; i < 4; i++) { + out[i] = + in[0] * matrix[0*4+i+matrix_offset] + + in[1] * matrix[1*4+i+matrix_offset] + + in[2] * matrix[2*4+i+matrix_offset] + + in[3] * matrix[3*4+i+matrix_offset]; + } + } + + /** + * Method __gluMultMatrixVecd + * + * @param matrix + * @param in + * @param out + */ + private void __gluMultMatrixVecd(DoubleBuffer matrix, DoubleBuffer in, DoubleBuffer out) { + int inPos = in.position(); + int outPos = out.position(); + int matrixPos = matrix.position(); + for (int i = 0; i < 4; i++) { + out.put(i + outPos, + in.get(0+inPos) * matrix.get(0*4+i+matrixPos) + + in.get(1+inPos) * matrix.get(1*4+i+matrixPos) + + in.get(2+inPos) * matrix.get(2*4+i+matrixPos) + + in.get(3+inPos) * matrix.get(3*4+i+matrixPos)); + } + } + + /** + * @param src + * @param inverse + * + * @return + */ + private boolean __gluInvertMatrixd(double[] src, double[] inverse) { + int i, j, k, swap; + double t; + double[][] temp = tempMatrix; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp[i][j] = src[i*4+j]; + } + } + __gluMakeIdentityd(inverse); + + for (i = 0; i < 4; i++) { + // + // Look for largest element in column + // + swap = i; + for (j = i + 1; j < 4; j++) { + if (Math.abs(temp[j][i]) > Math.abs(temp[i][i])) { + swap = j; + } + } + + if (swap != i) { + // + // Swap rows. + // + for (k = 0; k < 4; k++) { + t = temp[i][k]; + temp[i][k] = temp[swap][k]; + temp[swap][k] = t; + + t = inverse[i*4+k]; + inverse[i*4+k] = inverse[swap*4+k]; + inverse[swap*4+k] = t; + } + } + + if (temp[i][i] == 0) { + // + // No non-zero pivot. The matrix is singular, which shouldn't + // happen. This means the user gave us a bad matrix. + // + return false; + } + + t = temp[i][i]; + for (k = 0; k < 4; k++) { + temp[i][k] /= t; + inverse[i*4+k] /= t; + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp[j][i]; + for (k = 0; k < 4; k++) { + temp[j][k] -= temp[i][k] * t; + inverse[j*4+k] -= inverse[i*4+k]*t; + } + } + } + } + return true; + } + + /** + * @param src + * @param inverse + * + * @return + */ + private boolean __gluInvertMatrixd(DoubleBuffer src, DoubleBuffer inverse) { + int i, j, k, swap; + double t; + + int srcPos = src.position(); + int invPos = inverse.position(); + + DoubleBuffer temp = tempMatrixBuf; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp.put(i*4+j, src.get(i*4+j + srcPos)); + } + } + __gluMakeIdentityd(inverse); + + for (i = 0; i < 4; i++) { + // + // Look for largest element in column + // + swap = i; + for (j = i + 1; j < 4; j++) { + if (Math.abs(temp.get(j*4+i)) > Math.abs(temp.get(i*4+i))) { + swap = j; + } + } + + if (swap != i) { + // + // Swap rows. + // + for (k = 0; k < 4; k++) { + t = temp.get(i*4+k); + temp.put(i*4+k, temp.get(swap*4+k)); + temp.put(swap*4+k, t); + + t = inverse.get(i*4+k + invPos); + inverse.put(i*4+k + invPos, inverse.get(swap*4+k + invPos)); + inverse.put(swap*4+k + invPos, t); + } + } + + if (temp.get(i*4+i) == 0) { + // + // No non-zero pivot. The matrix is singular, which shouldn't + // happen. This means the user gave us a bad matrix. + // + return false; + } + + t = temp.get(i*4+i); + for (k = 0; k < 4; k++) { + temp.put(i*4+k, temp.get(i*4+k) / t); + inverse.put(i*4+k + invPos, inverse.get(i*4+k + invPos) / t); + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp.get(j*4+i); + for (k = 0; k < 4; k++) { + temp.put(j*4+k, temp.get(j*4+k) - temp.get(i*4+k) * t); + inverse.put(j*4+k + invPos, inverse.get(j*4+k + invPos) - inverse.get(i*4+k + invPos) * t); + } + } + } + } + return true; + } + + + /** + * @param a + * @param b + * @param r + */ + private void __gluMultMatricesd(double[] a, int a_offset, double[] b, int b_offset, double[] r) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r[i*4+j] = + a[i*4+0+a_offset]*b[0*4+j+b_offset] + + a[i*4+1+a_offset]*b[1*4+j+b_offset] + + a[i*4+2+a_offset]*b[2*4+j+b_offset] + + a[i*4+3+a_offset]*b[3*4+j+b_offset]; + } + } + } + + + /** + * @param a + * @param b + * @param r + */ + private void __gluMultMatricesd(DoubleBuffer a, DoubleBuffer b, DoubleBuffer r) { + int aPos = a.position(); + int bPos = b.position(); + int rPos = r.position(); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r.put(i*4+j + rPos, + a.get(i*4+0+aPos)*b.get(0*4+j+bPos) + + a.get(i*4+1+aPos)*b.get(1*4+j+bPos) + + a.get(i*4+2+aPos)*b.get(2*4+j+bPos) + + a.get(i*4+3+aPos)*b.get(3*4+j+bPos)); + } + } + } + + /** + * Normalize vector + * + * @param v + */ + private static void normalize(double[] v) { + double r; + + r = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + if ( r == 0.0 ) + return; + + r = 1.0 / r; + + v[0] *= r; + v[1] *= r; + v[2] *= r; + + return; + } + + /** + * Normalize vector + * + * @param v + */ + private static void normalize(DoubleBuffer v) { + double r; + + int vPos = v.position(); + + r = Math.sqrt(v.get(0+vPos) * v.get(0+vPos) + + v.get(1+vPos) * v.get(1+vPos) + + v.get(2+vPos) * v.get(2+vPos)); + if ( r == 0.0 ) + return; + + r = 1.0 / r; + + v.put(0+vPos, v.get(0+vPos) * r); + v.put(1+vPos, v.get(1+vPos) * r); + v.put(2+vPos, v.get(2+vPos) * r); + + return; + } + + + /** + * Calculate cross-product + * + * @param v1 + * @param v2 + * @param result + */ + private static void cross(double[] v1, double[] v2, double[] result) { + result[0] = v1[1] * v2[2] - v1[2] * v2[1]; + result[1] = v1[2] * v2[0] - v1[0] * v2[2]; + result[2] = v1[0] * v2[1] - v1[1] * v2[0]; + } + + /** + * Calculate cross-product + * + * @param v1 + * @param v2 + * @param result + */ + private static void cross(DoubleBuffer v1, DoubleBuffer v2, DoubleBuffer result) { + int v1Pos = v1.position(); + int v2Pos = v2.position(); + int rPos = result.position(); + + result.put(0+rPos, v1.get(1+v1Pos) * v2.get(2+v2Pos) - v1.get(2+v1Pos) * v2.get(1+v2Pos)); + result.put(1+rPos, v1.get(2+v1Pos) * v2.get(0+v2Pos) - v1.get(0+v1Pos) * v2.get(2+v2Pos)); + result.put(2+rPos, v1.get(0+v1Pos) * v2.get(1+v2Pos) - v1.get(1+v1Pos) * v2.get(0+v2Pos)); + } + + /** + * Method gluOrtho2D. + * + * @param left + * @param right + * @param bottom + * @param top + */ + public void gluOrtho2D(GL2 gl, double left, double right, double bottom, double top) { + gl.glOrtho(left, right, bottom, top, -1, 1); + } + + /** + * Method gluPerspective. + * + * @param fovy + * @param aspect + * @param zNear + * @param zFar + */ + public void gluPerspective(GL2 gl, double fovy, double aspect, double zNear, double zFar) { + double sine, cotangent, deltaZ; + double radians = fovy / 2 * Math.PI / 180; + + deltaZ = zFar - zNear; + sine = Math.sin(radians); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) { + return; + } + + cotangent = Math.cos(radians) / sine; + + __gluMakeIdentityd(matrixBuf); + + matrixBuf.put(0 * 4 + 0, cotangent / aspect); + matrixBuf.put(1 * 4 + 1, cotangent); + matrixBuf.put(2 * 4 + 2, - (zFar + zNear) / deltaZ); + matrixBuf.put(2 * 4 + 3, -1); + matrixBuf.put(3 * 4 + 2, -2 * zNear * zFar / deltaZ); + matrixBuf.put(3 * 4 + 3, 0); + + gl.glMultMatrixd(matrixBuf); + } + + /** + * Method gluLookAt + * + * @param eyex + * @param eyey + * @param eyez + * @param centerx + * @param centery + * @param centerz + * @param upx + * @param upy + * @param upz + */ + public void gluLookAt(GL2 gl, + double eyex, + double eyey, + double eyez, + double centerx, + double centery, + double centerz, + double upx, + double upy, + double upz) { + DoubleBuffer forward = this.forwardBuf; + DoubleBuffer side = this.sideBuf; + DoubleBuffer up = this.upBuf; + + forward.put(0, centerx - eyex); + forward.put(1, centery - eyey); + forward.put(2, centerz - eyez); + + up.put(0, upx); + up.put(1, upy); + up.put(2, upz); + + normalize(forward); + + /* Side = forward x up */ + cross(forward, up, side); + normalize(side); + + /* Recompute up as: up = side x forward */ + cross(side, forward, up); + + __gluMakeIdentityd(matrixBuf); + matrixBuf.put(0 * 4 + 0, side.get(0)); + matrixBuf.put(1 * 4 + 0, side.get(1)); + matrixBuf.put(2 * 4 + 0, side.get(2)); + + matrixBuf.put(0 * 4 + 1, up.get(0)); + matrixBuf.put(1 * 4 + 1, up.get(1)); + matrixBuf.put(2 * 4 + 1, up.get(2)); + + matrixBuf.put(0 * 4 + 2, -forward.get(0)); + matrixBuf.put(1 * 4 + 2, -forward.get(1)); + matrixBuf.put(2 * 4 + 2, -forward.get(2)); + + gl.glMultMatrixd(matrixBuf); + gl.glTranslated(-eyex, -eyey, -eyez); + } + + /** + * Method gluProject + * + * @param objx + * @param objy + * @param objz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param win_pos + * + * @return + */ + public boolean gluProject(double objx, + double objy, + double objz, + double[] modelMatrix, + int modelMatrix_offset, + double[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + double[] win_pos, + int win_pos_offset ) { + + double[] in = this.in; + double[] out = this.out; + + in[0] = objx; + in[1] = objy; + in[2] = objz; + in[3] = 1.0; + + __gluMultMatrixVecd(modelMatrix, modelMatrix_offset, in, out); + __gluMultMatrixVecd(projMatrix, projMatrix_offset, out, in); + + if (in[3] == 0.0) + return false; + + in[3] = (1.0 / in[3]) * 0.5; + + // Map x, y and z to range 0-1 + in[0] = in[0] * in[3] + 0.5f; + in[1] = in[1] * in[3] + 0.5f; + in[2] = in[2] * in[3] + 0.5f; + + // Map x,y to viewport + win_pos[0+win_pos_offset] = in[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset]; + win_pos[1+win_pos_offset] = in[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset]; + win_pos[2+win_pos_offset] = in[2]; + + return true; + } + + /** + * Method gluProject + * + * @param objx + * @param objy + * @param objz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param win_pos + * + * @return + */ + public boolean gluProject(double objx, + double objy, + double objz, + DoubleBuffer modelMatrix, + DoubleBuffer projMatrix, + IntBuffer viewport, + DoubleBuffer win_pos) { + + DoubleBuffer in = this.inBuf; + DoubleBuffer out = this.outBuf; + + in.put(0, objx); + in.put(1, objy); + in.put(2, objz); + in.put(3, 1.0); + + __gluMultMatrixVecd(modelMatrix, in, out); + __gluMultMatrixVecd(projMatrix, out, in); + + if (in.get(3) == 0.0) + return false; + + in.put(3, (1.0 / in.get(3)) * 0.5); + + // Map x, y and z to range 0-1 + in.put(0, in.get(0) * in.get(3) + 0.5f); + in.put(1, in.get(1) * in.get(3) + 0.5f); + in.put(2, in.get(2) * in.get(3) + 0.5f); + + // Map x,y to viewport + int vPos = viewport.position(); + int wPos = win_pos.position(); + win_pos.put(0+wPos, in.get(0) * viewport.get(2+vPos) + viewport.get(0+vPos)); + win_pos.put(1+wPos, in.get(1) * viewport.get(3+vPos) + viewport.get(1+vPos)); + win_pos.put(2+wPos, in.get(2)); + + return true; + } + + + /** + * Method gluUnproject + * + * @param winx + * @param winy + * @param winz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param obj_pos + * + * @return + */ + public boolean gluUnProject(double winx, + double winy, + double winz, + double[] modelMatrix, + int modelMatrix_offset, + double[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + double[] obj_pos, + int obj_pos_offset) { + double[] in = this.in; + double[] out = this.out; + + __gluMultMatricesd(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); + + if (!__gluInvertMatrixd(matrix, matrix)) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = 1.0; + + // Map x and y from window coordinates + in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; + in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; + + // Map to range -1 to 1 + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + __gluMultMatrixVecd(matrix, 0, in, out); + + if (out[3] == 0.0) + return false; + + out[3] = 1.0 / out[3]; + + obj_pos[0+obj_pos_offset] = out[0] * out[3]; + obj_pos[1+obj_pos_offset] = out[1] * out[3]; + obj_pos[2+obj_pos_offset] = out[2] * out[3]; + + return true; + } + + + /** + * Method gluUnproject + * + * @param winx + * @param winy + * @param winz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param obj_pos + * + * @return + */ + public boolean gluUnProject(double winx, + double winy, + double winz, + DoubleBuffer modelMatrix, + DoubleBuffer projMatrix, + IntBuffer viewport, + DoubleBuffer obj_pos) { + DoubleBuffer in = this.inBuf; + DoubleBuffer out = this.outBuf; + + __gluMultMatricesd(modelMatrix, projMatrix, matrixBuf); + + if (!__gluInvertMatrixd(matrixBuf, matrixBuf)) + return false; + + in.put(0, winx); + in.put(1, winy); + in.put(2, winz); + in.put(3, 1.0); + + // Map x and y from window coordinates + int vPos = viewport.position(); + int oPos = obj_pos.position(); + in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos)); + in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos)); + + // Map to range -1 to 1 + in.put(0, in.get(0) * 2 - 1); + in.put(1, in.get(1) * 2 - 1); + in.put(2, in.get(2) * 2 - 1); + + __gluMultMatrixVecd(matrixBuf, in, out); + + if (out.get(3) == 0.0) + return false; + + out.put(3, 1.0 / out.get(3)); + + obj_pos.put(0+oPos, out.get(0) * out.get(3)); + obj_pos.put(1+oPos, out.get(1) * out.get(3)); + obj_pos.put(2+oPos, out.get(2) * out.get(3)); + + return true; + } + + + /** + * Method gluUnproject4 + * + * @param winx + * @param winy + * @param winz + * @param clipw + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param near + * @param far + * @param obj_pos + * + * @return + */ + public boolean gluUnProject4(double winx, + double winy, + double winz, + double clipw, + double[] modelMatrix, + int modelMatrix_offset, + double[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + double near, + double far, + double[] obj_pos, + int obj_pos_offset ) { + double[] in = this.in; + double[] out = this.out; + + __gluMultMatricesd(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); + + if (!__gluInvertMatrixd(matrix, matrix)) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = clipw; + + // Map x and y from window coordinates + in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; + in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; + in[2] = (in[2] - near) / (far - near); + + // Map to range -1 to 1 + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + __gluMultMatrixVecd(matrix, 0, in, out); + + if (out[3] == 0.0) + return false; + + obj_pos[0+obj_pos_offset] = out[0]; + obj_pos[1+obj_pos_offset] = out[1]; + obj_pos[2+obj_pos_offset] = out[2]; + obj_pos[3+obj_pos_offset] = out[3]; + return true; + } + + /** + * Method gluUnproject4 + * + * @param winx + * @param winy + * @param winz + * @param clipw + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param near + * @param far + * @param obj_pos + * + * @return + */ + public boolean gluUnProject4(double winx, + double winy, + double winz, + double clipw, + DoubleBuffer modelMatrix, + DoubleBuffer projMatrix, + IntBuffer viewport, + double near, + double far, + DoubleBuffer obj_pos) { + DoubleBuffer in = this.inBuf; + DoubleBuffer out = this.outBuf; + + __gluMultMatricesd(modelMatrix, projMatrix, matrixBuf); + + if (!__gluInvertMatrixd(matrixBuf, matrixBuf)) + return false; + + in.put(0, winx); + in.put(1, winy); + in.put(2, winz); + in.put(3, clipw); + + // Map x and y from window coordinates + int vPos = viewport.position(); + in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos)); + in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos)); + in.put(2, (in.get(2) - near) / (far - near)); + + // Map to range -1 to 1 + in.put(0, in.get(0) * 2 - 1); + in.put(1, in.get(1) * 2 - 1); + in.put(2, in.get(2) * 2 - 1); + + __gluMultMatrixVecd(matrixBuf, in, out); + + if (out.get(3) == 0.0) + return false; + + int oPos = obj_pos.position(); + obj_pos.put(0+oPos, out.get(0)); + obj_pos.put(1+oPos, out.get(1)); + obj_pos.put(2+oPos, out.get(2)); + obj_pos.put(3+oPos, out.get(3)); + return true; + } + + + /** + * Method gluPickMatrix + * + * @param x + * @param y + * @param deltaX + * @param deltaY + * @param viewport + */ + public void gluPickMatrix(GL2 gl, + double x, + double y, + double deltaX, + double deltaY, + IntBuffer viewport) { + if (deltaX <= 0 || deltaY <= 0) { + return; + } + + /* Translate and scale the picked region to the entire window */ + int vPos = viewport.position(); + gl.glTranslated((viewport.get(2+vPos) - 2 * (x - viewport.get(0+vPos))) / deltaX, + (viewport.get(3+vPos) - 2 * (y - viewport.get(1+vPos))) / deltaY, + 0); + gl.glScaled(viewport.get(2) / deltaX, viewport.get(3) / deltaY, 1.0); + } + + /** + * Method gluPickMatrix + * + * @param x + * @param y + * @param deltaX + * @param deltaY + * @param viewport + * @param viewport_offset + */ + public void gluPickMatrix(GL2 gl, + double x, + double y, + double deltaX, + double deltaY, + int[] viewport, + int viewport_offset) { + if (deltaX <= 0 || deltaY <= 0) { + return; + } + + /* Translate and scale the picked region to the entire window */ + gl.glTranslated((viewport[2+viewport_offset] - 2 * (x - viewport[0+viewport_offset])) / deltaX, + (viewport[3+viewport_offset] - 2 * (y - viewport[1+viewport_offset])) / deltaY, + 0); + gl.glScaled(viewport[2+viewport_offset] / deltaX, viewport[3+viewport_offset] / deltaY, 1.0); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/gl2/Util.java b/src/jogl/classes/com/jogamp/opengl/impl/gl2/Util.java new file mode 100644 index 000000000..a542dcf19 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/gl2/Util.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * 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.impl.gl2; + +import com.jogamp.opengl.impl.*; + +import java.nio.IntBuffer; +import javax.media.opengl.*; + +/** + * Util.java + * <p/> + * <p/> + * Created 7-jan-2004 + * + * @author Erik Duijs + */ +class Util { + + /** + * temp int[] of one for getting an int from some GL functions + */ + private int[] scratch = new int[1]; + + /** + * Return ceiling of integer division + * + * @param a + * @param b + * + * @return int + */ + protected static int ceil(int a, int b) { + return (a % b == 0 ? a / b : a / b + 1); + } + + /** + * Method compPerPix. + * + * @param format + * + * @return int + */ + protected static int compPerPix(int format) { + /* Determine number of components per pixel */ + switch ( format ) { + case GL2.GL_COLOR_INDEX: + case GL2.GL_STENCIL_INDEX: + case GL2.GL_DEPTH_COMPONENT: + case GL2.GL_RED: + case GL2.GL_GREEN: + case GL2.GL_BLUE: + case GL2.GL_ALPHA: + case GL2.GL_LUMINANCE: + return 1; + case GL2.GL_LUMINANCE_ALPHA: + return 2; + case GL2.GL_RGB: + case GL2.GL_BGR: + return 3; + case GL2.GL_RGBA: + case GL2.GL_BGRA: + return 4; + default : + return -1; + } + } + + /** + * Method nearestPower. + * <p/> + * Compute the nearest power of 2 number. This algorithm is a little strange, but it works quite well. + * + * @param value + * + * @return int + */ + protected static int nearestPower(int value) { + int i; + + i = 1; + + /* Error! */ + if ( value == 0 ) + return -1; + + for ( ; ; ) { + if ( value == 1 ) { + return i; + } else if ( value == 3 ) { + return i << 2; + } + value >>= 1; + i <<= 1; + } + } + + /** + * Method bytesPerPixel. + * + * @param format + * @param type + * + * @return int + */ + protected static int bytesPerPixel(int format, int type) { + int n, m; + + switch ( format ) { + case GL2.GL_COLOR_INDEX: + case GL2.GL_STENCIL_INDEX: + case GL2.GL_DEPTH_COMPONENT: + case GL2.GL_RED: + case GL2.GL_GREEN: + case GL2.GL_BLUE: + case GL2.GL_ALPHA: + case GL2.GL_LUMINANCE: + n = 1; + break; + case GL2.GL_LUMINANCE_ALPHA: + n = 2; + break; + case GL2.GL_RGB: + case GL2.GL_BGR: + n = 3; + break; + case GL2.GL_RGBA: + case GL2.GL_BGRA: + n = 4; + break; + default : + n = 0; + } + + switch ( type ) { + case GL2.GL_UNSIGNED_BYTE: + m = 1; + break; + case GL2.GL_BYTE: + m = 1; + break; + case GL2.GL_BITMAP: + m = 1; + break; + case GL2.GL_UNSIGNED_SHORT: + m = 2; + break; + case GL2.GL_SHORT: + m = 2; + break; + case GL2.GL_UNSIGNED_INT: + m = 4; + break; + case GL2.GL_INT: + m = 4; + break; + case GL2.GL_FLOAT: + m = 4; + break; + default : + m = 0; + } + + return n * m; + } + + /** + * Convenience method for returning an int, rather than getting it out of a buffer yourself. + * + * @param what + * + * @return int + */ + protected int glGetIntegerv(GL gl, int what) { + gl.glGetIntegerv(what, scratch, 0); + return scratch[0]; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/gl2/fixme/GLObjectTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/gl2/fixme/GLObjectTracker.java new file mode 100755 index 000000000..3e3b6ae87 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/gl2/fixme/GLObjectTracker.java @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2006 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.gl2; + +import com.jogamp.opengl.impl.*; + +import java.nio.*; +import javax.media.opengl.*; + +/** + * Tracks the creation of server-side OpenGL objects which can be + * shared between contexts. Ordinarily, when an OpenGL context is + * deleted and no other contexts are sharing server-side objects with + * it, all of the server-side objects are automatically deleted by the + * OpenGL implementation. It is not necessary for the end user to + * explicitly delete these objects. However, when the Java2D/OpenGL + * pipeline is active and frame buffer objects are being used for + * rendering, it is necessary for all OpenGL contexts created by JOGL + * to share server-side objects with the Java2D OpenGL context. This + * means that these objects "leak" into the namespace used by Java2D. + * In order to prevent memory leaks and to present the same + * programming model to the end user, it is necessary to track the + * creation and destruction of all of these server-side OpenGL objects + * and to explicitly release them when all of the JOGL-created + * contexts which can see them have been released. <P> + * + * The {@link #ref ref} and {@link #unref unref} methods should be + * used during the creation and destruction of OpenGL contexts by JOGL + * in order to update the liveness of the objects being tracked. The + * various other methods should be called by the OpenGL binding in the + * various named methods. + */ + +public class GLObjectTracker { + private static final boolean DEBUG = Debug.debug("GLObjectTracker"); + + //---------------------------------------------------------------------- + // Adders + // + + // glGenBuffers + public synchronized void addBuffers(int n, IntBuffer ids) { + add(getList(BUFFERS), n, ids); + } + + // glGenBuffers + public synchronized void addBuffers(int n, int[] ids, int ids_offset) { + add(getList(BUFFERS), n, ids, ids_offset); + } + + // glGenBuffersARB + public synchronized void addBuffersARB(int n, IntBuffer ids) { + add(getList(BUFFERS_ARB), n, ids); + } + + // glGenBuffersARB + public synchronized void addBuffersARB(int n, int[] ids, int ids_offset) { + add(getList(BUFFERS_ARB), n, ids, ids_offset); + } + + // glGenFencesAPPLE + public synchronized void addFencesAPPLE(int n, IntBuffer ids) { + add(getList(FENCES_APPLE), n, ids); + } + + // glGenFencesAPPLE + public synchronized void addFencesAPPLE(int n, int[] ids, int ids_offset) { + add(getList(FENCES_APPLE), n, ids, ids_offset); + } + + // glGenFencesNV + public synchronized void addFencesNV(int n, IntBuffer ids) { + add(getList(FENCES_NV), n, ids); + } + + // glGenFencesNV + public synchronized void addFencesNV(int n, int[] ids, int ids_offset) { + add(getList(FENCES_NV), n, ids, ids_offset); + } + + // glGenFragmentShadersATI + public synchronized void addFragmentShadersATI(int start, int n) { + add(getList(FRAGMENT_SHADERS_ATI), start, n); + } + + // glGenFramebuffersEXT + public synchronized void addFramebuffersEXT(int n, IntBuffer ids) { + add(getList(FRAMEBUFFERS_EXT), n, ids); + } + + // glGenFramebuffersEXT + public synchronized void addFramebuffersEXT(int n, int[] ids, int ids_offset) { + add(getList(FRAMEBUFFERS_EXT), n, ids, ids_offset); + } + + // glGenLists + public synchronized void addLists(int start, int n) { + add(getList(LISTS), start, n); + } + + // glGenOcclusionQueriesNV + public synchronized void addOcclusionQueriesNV(int n, IntBuffer ids) { + add(getList(OCCLUSION_QUERIES_NV), n, ids); + } + + // glGenOcclusionQueriesNV + public synchronized void addOcclusionQueriesNV(int n, int[] ids, int ids_offset) { + add(getList(OCCLUSION_QUERIES_NV), n, ids, ids_offset); + } + + // glCreateProgram + public synchronized void addProgramObject(int obj) { + add(getList(PROGRAM_OBJECTS), obj, 1); + } + + // glCreateProgramObjectARB + public synchronized void addProgramObjectARB(int obj) { + add(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1); + } + + // glGenProgramsARB + public synchronized void addProgramsARB(int n, IntBuffer ids) { + add(getList(PROGRAMS_ARB), n, ids); + } + + // glGenProgramsARB + public synchronized void addProgramsARB(int n, int[] ids, int ids_offset) { + add(getList(PROGRAMS_ARB), n, ids, ids_offset); + } + + // glGenProgramsNV + public synchronized void addProgramsNV(int n, IntBuffer ids) { + add(getList(PROGRAMS_NV), n, ids); + } + + // glGenProgramsNV + public synchronized void addProgramsNV(int n, int[] ids, int ids_offset) { + add(getList(PROGRAMS_NV), n, ids, ids_offset); + } + + // glGenQueries + public synchronized void addQueries(int n, IntBuffer ids) { + add(getList(QUERIES), n, ids); + } + + // glGenQueries + public synchronized void addQueries(int n, int[] ids, int ids_offset) { + add(getList(QUERIES), n, ids, ids_offset); + } + + // glGenQueriesARB + public synchronized void addQueriesARB(int n, IntBuffer ids) { + add(getList(QUERIES_ARB), n, ids); + } + + // glGenQueriesARB + public synchronized void addQueriesARB(int n, int[] ids, int ids_offset) { + add(getList(QUERIES_ARB), n, ids, ids_offset); + } + + // glGenRenderbuffersEXT + public synchronized void addRenderbuffersEXT(int n, IntBuffer ids) { + add(getList(RENDERBUFFERS_EXT), n, ids); + } + + // glGenRenderbuffersEXT + public synchronized void addRenderbuffersEXT(int n, int[] ids, int ids_offset) { + add(getList(RENDERBUFFERS_EXT), n, ids, ids_offset); + } + + // glCreateShader + public synchronized void addShaderObject(int obj) { + add(getList(SHADER_OBJECTS), obj, 1); + } + + // glCreateShaderObjectARB + public synchronized void addShaderObjectARB(int obj) { + add(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1); + } + + // glGenTextures + public synchronized void addTextures(int n, IntBuffer ids) { + add(getList(TEXTURES), n, ids); + } + + // glGenTextures + public synchronized void addTextures(int n, int[] ids, int ids_offset) { + add(getList(TEXTURES), n, ids, ids_offset); + } + + // glGenVertexArraysAPPLE + public synchronized void addVertexArraysAPPLE(int n, IntBuffer ids) { + add(getList(VERTEX_ARRAYS_APPLE), n, ids); + } + + // glGenVertexArraysAPPLE + public synchronized void addVertexArraysAPPLE(int n, int[] ids, int ids_offset) { + add(getList(VERTEX_ARRAYS_APPLE), n, ids, ids_offset); + } + + // glGenVertexShadersEXT + public synchronized void addVertexShadersEXT(int start, int n) { + add(getList(VERTEX_SHADERS_EXT), start, n); + } + + //---------------------------------------------------------------------- + // Removers + // + + // glDeleteBuffers + public synchronized void removeBuffers(int n, IntBuffer ids) { + remove(getList(BUFFERS), n, ids); + } + + // glDeleteBuffers + public synchronized void removeBuffers(int n, int[] ids, int ids_offset) { + remove(getList(BUFFERS), n, ids, ids_offset); + } + + // glDeleteBuffersARB + public synchronized void removeBuffersARB(int n, IntBuffer ids) { + remove(getList(BUFFERS_ARB), n, ids); + } + + // glDeleteBuffersARB + public synchronized void removeBuffersARB(int n, int[] ids, int ids_offset) { + remove(getList(BUFFERS_ARB), n, ids, ids_offset); + } + + // glDeleteFencesAPPLE + public synchronized void removeFencesAPPLE(int n, IntBuffer ids) { + remove(getList(FENCES_APPLE), n, ids); + } + + // glDeleteFencesAPPLE + public synchronized void removeFencesAPPLE(int n, int[] ids, int ids_offset) { + remove(getList(FENCES_APPLE), n, ids, ids_offset); + } + + // glDeleteFencesNV + public synchronized void removeFencesNV(int n, IntBuffer ids) { + remove(getList(FENCES_NV), n, ids); + } + + // glDeleteFencesNV + public synchronized void removeFencesNV(int n, int[] ids, int ids_offset) { + remove(getList(FENCES_NV), n, ids, ids_offset); + } + + // glDeleteFragmentShaderATI + public synchronized void removeFragmentShaderATI(int obj) { + remove(getList(FRAGMENT_SHADERS_ATI), obj, 1); + } + + // glDeleteFramebuffersEXT + public synchronized void removeFramebuffersEXT(int n, IntBuffer ids) { + remove(getList(FRAMEBUFFERS_EXT), n, ids); + } + + // glDeleteFramebuffersEXT + public synchronized void removeFramebuffersEXT(int n, int[] ids, int ids_offset) { + remove(getList(FRAMEBUFFERS_EXT), n, ids, ids_offset); + } + + // glDeleteLists + public synchronized void removeLists(int start, int n) { + remove(getList(LISTS), start, n); + } + + // glDeleteOcclusionQueriesNV + public synchronized void removeOcclusionQueriesNV(int n, IntBuffer ids) { + remove(getList(OCCLUSION_QUERIES_NV), n, ids); + } + + // glDeleteOcclusionQueriesNV + public synchronized void removeOcclusionQueriesNV(int n, int[] ids, int ids_offset) { + remove(getList(OCCLUSION_QUERIES_NV), n, ids, ids_offset); + } + + // glDeleteProgram + public synchronized void removeProgramObject(int obj) { + remove(getList(PROGRAM_OBJECTS), obj, 1); + } + + // glDeleteObjectARB + public synchronized void removeProgramOrShaderObjectARB(int obj) { + remove(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1); + } + + // glDeleteProgramsARB + public synchronized void removeProgramsARB(int n, IntBuffer ids) { + remove(getList(PROGRAMS_ARB), n, ids); + } + + // glDeleteProgramsARB + public synchronized void removeProgramsARB(int n, int[] ids, int ids_offset) { + remove(getList(PROGRAMS_ARB), n, ids, ids_offset); + } + + // glDeleteProgramsNV + public synchronized void removeProgramsNV(int n, IntBuffer ids) { + remove(getList(PROGRAMS_NV), n, ids); + } + + // glDeleteProgramsNV + public synchronized void removeProgramsNV(int n, int[] ids, int ids_offset) { + remove(getList(PROGRAMS_NV), n, ids, ids_offset); + } + + // glDeleteQueries + public synchronized void removeQueries(int n, IntBuffer ids) { + remove(getList(QUERIES), n, ids); + } + + // glDeleteQueries + public synchronized void removeQueries(int n, int[] ids, int ids_offset) { + remove(getList(QUERIES), n, ids, ids_offset); + } + + // glDeleteQueriesARB + public synchronized void removeQueriesARB(int n, IntBuffer ids) { + remove(getList(QUERIES_ARB), n, ids); + } + + // glDeleteQueriesARB + public synchronized void removeQueriesARB(int n, int[] ids, int ids_offset) { + remove(getList(QUERIES_ARB), n, ids, ids_offset); + } + + // glDeleteRenderbuffersEXT + public synchronized void removeRenderbuffersEXT(int n, IntBuffer ids) { + remove(getList(RENDERBUFFERS_EXT), n, ids); + } + + // glDeleteRenderbuffersEXT + public synchronized void removeRenderbuffersEXT(int n, int[] ids, int ids_offset) { + remove(getList(RENDERBUFFERS_EXT), n, ids, ids_offset); + } + + // glDeleteShader + public synchronized void removeShaderObject(int obj) { + remove(getList(SHADER_OBJECTS), obj, 1); + } + + // glDeleteTextures + public synchronized void removeTextures(int n, IntBuffer ids) { + remove(getList(TEXTURES), n, ids); + } + + // glDeleteTextures + public synchronized void removeTextures(int n, int[] ids, int ids_offset) { + remove(getList(TEXTURES), n, ids, ids_offset); + } + + // glDeleteVertexArraysAPPLE + public synchronized void removeVertexArraysAPPLE(int n, IntBuffer ids) { + remove(getList(VERTEX_ARRAYS_APPLE), n, ids); + } + + // glDeleteVertexArraysAPPLE + public synchronized void removeVertexArraysAPPLE(int n, int[] ids, int ids_offset) { + remove(getList(VERTEX_ARRAYS_APPLE), n, ids, ids_offset); + } + + // glDeleteVertexShaderEXT + public synchronized void removeVertexShaderEXT(int obj) { + remove(getList(VERTEX_SHADERS_EXT), obj, 1); + } + + //---------------------------------------------------------------------- + // Reference count maintenance and manual deletion + // + + public synchronized void transferAll(GLObjectTracker other) { + for (int i = 0; i < lists.length; i++) { + getList(i).addAll(other.lists[i]); + if (other.lists[i] != null) { + other.lists[i].clear(); + } + } + dirty = true; + } + + public synchronized void ref() { + ++refCount; + } + + public void unref(GLObjectTracker deletedObjectPool) { + boolean tryDelete = false; + synchronized (this) { + if (--refCount == 0) { + tryDelete = true; + } + } + if (tryDelete) { + // See whether we should try to do the work now or whether we + // have to postpone + GLContext cur = GLContext.getCurrent(); + if ((cur != null) && + (cur instanceof GLContextImpl)) { + GLContextImpl curImpl = (GLContextImpl) cur; + if (deletedObjectPool != null && + deletedObjectPool == curImpl.getDeletedObjectTracker()) { + // Should be safe to delete these objects now + try { + delete((GL2)curImpl.getGL()); + return; + } catch (GLException e) { + // Shouldn't happen, but if it does, transfer all objects + // to the deleted object pool hoping we can later clean + // them up + deletedObjectPool.transferAll(this); + throw(e); + } + } + } + // If we get here, we couldn't attempt to delete the objects + // right now; instead try to transfer them to the + // deletedObjectPool for later cleanup (FIXME: should consider + // throwing an exception if deletedObjectPool is null, since + // that shouldn't happen) + if (DEBUG) { + String s = null; + if (cur == null) { + s = "current context was null"; + } else if (!(cur instanceof GLContextImpl)) { + s = "current context was not a GLContextImpl"; + } else if (deletedObjectPool == null) { + s = "no current deletedObjectPool"; + } else if (deletedObjectPool != ((GLContextImpl) cur).getDeletedObjectTracker()) { + s = "deletedObjectTracker didn't match"; + if (((GLContextImpl) cur).getDeletedObjectTracker() == null) { + s += " (other was null)"; + } + } else { + s = "unknown reason"; + } + System.err.println("Deferred destruction of server-side OpenGL objects into " + deletedObjectPool + ": " + s); + } + + if (deletedObjectPool != null) { + deletedObjectPool.transferAll(this); + } + } + } + + public void clean(GL2 gl) { + if (dirty) { + try { + delete(gl); + dirty = false; + } catch (GLException e) { + // FIXME: not sure what to do here; probably a bad idea to be + // throwing exceptions during an otherwise-successful makeCurrent + } + } + } + + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // Kinds of sharable server-side OpenGL objects this class tracks + private static final int BUFFERS = 0; + private static final int BUFFERS_ARB = 1; + private static final int FENCES_APPLE = 2; + private static final int FENCES_NV = 3; + private static final int FRAGMENT_SHADERS_ATI = 4; + private static final int FRAMEBUFFERS_EXT = 5; + private static final int LISTS = 6; + private static final int OCCLUSION_QUERIES_NV = 7; + private static final int PROGRAM_AND_SHADER_OBJECTS_ARB = 8; + private static final int PROGRAM_OBJECTS = 9; + private static final int PROGRAMS_ARB = 10; + private static final int PROGRAMS_NV = 11; + private static final int QUERIES = 12; + private static final int QUERIES_ARB = 13; + private static final int RENDERBUFFERS_EXT = 14; + private static final int SHADER_OBJECTS = 15; + private static final int TEXTURES = 16; + private static final int VERTEX_ARRAYS_APPLE = 17; + private static final int VERTEX_SHADERS_EXT = 18; + private static final int NUM_OBJECT_TYPES = 19; + + static abstract class Deleter { + public abstract void delete(GL2 gl, int obj); + } + + static class ObjectList { + private static final int MIN_CAPACITY = 4; + + private int size; + private int capacity; + private int[] data; + private Deleter deleter; + private String name; + + public ObjectList(Deleter deleter) { + this.deleter = deleter; + clear(); + } + + public void add(int obj) { + if (size == capacity) { + int newCapacity = 2 * capacity; + int[] newData = new int[newCapacity]; + System.arraycopy(data, 0, newData, 0, size); + data = newData; + capacity = newCapacity; + } + + data[size++] = obj; + } + + public void addAll(ObjectList other) { + if (other == null) { + return; + } + for (int i = 0; i < other.size; i++) { + add(other.data[i]); + } + } + + public boolean remove(int value) { + for (int i = 0; i < size; i++) { + if (data[i] == value) { + if (i < size - 1) { + System.arraycopy(data, i+1, data, i, size - i - 1); + } + --size; + if ((size < capacity / 4) && + (capacity > MIN_CAPACITY)) { + int newCapacity = capacity / 4; + if (newCapacity < MIN_CAPACITY) { + newCapacity = MIN_CAPACITY; + } + int[] newData = new int[newCapacity]; + System.arraycopy(data, 0, newData, 0, size); + data = newData; + capacity = newCapacity; + } + return true; + } + } + return false; + } + + public void setName(String name) { + if (DEBUG) { + this.name = name; + } + } + + public void delete(GL2 gl) { + // Just in case we start throwing exceptions during deletion, + // make sure we make progress rather than going into an infinite + // loop + while (size > 0) { + int obj = data[size - 1]; + --size; + if (DEBUG) { + System.err.println("Deleting server-side OpenGL object " + obj + + ((name != null) ? (" (" + name + ")") : "")); + } + deleter.delete(gl, obj); + } + } + + public void clear() { + size = 0; + capacity = MIN_CAPACITY; + data = new int[capacity]; + } + } + + private ObjectList[] lists = new ObjectList[NUM_OBJECT_TYPES]; + private int refCount; + private boolean dirty; + + private void add(ObjectList list, int n, IntBuffer ids) { + int pos = ids.position(); + for (int i = 0; i < n; i++) { + list.add(ids.get(pos + i)); + } + } + + private void add(ObjectList list, int n, int[] ids, int ids_offset) { + for (int i = 0; i < n; i++) { + list.add(ids[i + ids_offset]); + } + } + + private void add(ObjectList list, int start, int n) { + for (int i = 0; i < n; i++) { + list.add(start + i); + } + } + + private void remove(ObjectList list, int n, IntBuffer ids) { + int pos = ids.position(); + for (int i = 0; i < n; i++) { + list.remove(ids.get(pos + i)); + } + } + + private void remove(ObjectList list, int n, int[] ids, int ids_offset) { + for (int i = 0; i < n; i++) { + list.remove(ids[i + ids_offset]); + } + } + + private void remove(ObjectList list, int start, int n) { + for (int i = 0; i < n; i++) { + list.remove(start + i); + } + } + + private ObjectList getList(int which) { + ObjectList list = lists[which]; + if (list == null) { + Deleter deleter = null; + String name = null; + // Figure out which deleter we need + switch (which) { + case BUFFERS: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteBuffers(1, new int[] { obj }, 0); + } + }; + name = "buffer"; + break; + case BUFFERS_ARB: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteBuffersARB(1, new int[] { obj }, 0); + } + }; + name = "ARB buffer"; + break; + case FENCES_APPLE: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteFencesAPPLE(1, new int[] { obj }, 0); + } + }; + name = "APPLE fence"; + break; + case FENCES_NV: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteFencesNV(1, new int[] { obj }, 0); + } + }; + name = "NV fence"; + break; + case FRAGMENT_SHADERS_ATI: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteFragmentShaderATI(obj); + } + }; + name = "ATI fragment shader"; + break; + case FRAMEBUFFERS_EXT: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteFramebuffersEXT(1, new int[] { obj }, 0); + } + }; + name = "EXT framebuffer"; + break; + case LISTS: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteLists(obj, 1); + } + }; + name = "display list"; + break; + case OCCLUSION_QUERIES_NV: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteOcclusionQueriesNV(1, new int[] { obj }, 0); + } + }; + name = "NV occlusion query"; + break; + case PROGRAM_AND_SHADER_OBJECTS_ARB: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteObjectARB(obj); + } + }; + name = "ARB program or shader object"; + break; + case PROGRAM_OBJECTS: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteProgram(obj); + } + }; + name = "program object"; + break; + case PROGRAMS_ARB: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteProgramsARB(1, new int[] { obj }, 0); + } + }; + name = "ARB program object"; + break; + case PROGRAMS_NV: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteProgramsNV(1, new int[] { obj }, 0); + } + }; + name = "NV program"; + break; + case QUERIES: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteQueries(1, new int[] { obj }, 0); + } + }; + name = "query"; + break; + case QUERIES_ARB: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteQueriesARB(1, new int[] { obj }, 0); + } + }; + name = "ARB query"; + break; + case RENDERBUFFERS_EXT: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteRenderbuffersEXT(1, new int[] { obj }, 0); + } + }; + name = "EXT renderbuffer"; + break; + case SHADER_OBJECTS: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteShader(obj); + } + }; + name = "shader object"; + break; + case TEXTURES: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteTextures(1, new int[] { obj }, 0); + } + }; + name = "texture"; + break; + case VERTEX_ARRAYS_APPLE: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteVertexArraysAPPLE(1, new int[] { obj }, 0); + } + }; + name = "APPLE vertex array"; + break; + case VERTEX_SHADERS_EXT: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteVertexShaderEXT(obj); + } + }; + name = "EXT vertex shader"; + break; + default: + throw new InternalError("Unexpected OpenGL object type " + which); + } + + list = new ObjectList(deleter); + list.setName(name); + lists[which] = list; + } + return list; + } + + private void delete(GL2 gl) { + for (int i = 0; i < lists.length; i++) { + ObjectList list = lists[i]; + if (list != null) { + list.delete(gl); + lists[i] = null; + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/GLUquadricImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/GLUquadricImpl.java new file mode 100644 index 000000000..d7e6a23c1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/GLUquadricImpl.java @@ -0,0 +1,1212 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** $Date: 2009-03-04 17:23:34 -0800 (Wed, 04 Mar 2009) $ $Revision: 1856 $ +** $Header$ +*/ + +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions 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 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * 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.impl.glu; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import com.jogamp.opengl.util.ImmModeSink; +import java.nio.*; + +/** + * GLUquadricImpl.java + * + * + * Created 22-dec-2003 (originally Quadric.java) + * @author Erik Duijs + * @author Kenneth Russell, Sven Gothel + */ + +public class GLUquadricImpl implements GLUquadric { + private boolean useGLSL; + private int drawStyle; + private int orientation; + private boolean textureFlag; + private int normals; + private boolean immModeSinkEnabled; + private boolean immModeSinkImmediate; + public int normalType; + public GL gl; + + public static final boolean USE_NORM = true; + public static final boolean USE_TEXT = false; + + private ImmModeSink immModeSink=null; + + public GLUquadricImpl(GL gl, boolean useGLSL) { + this.gl=gl; + this.useGLSL = useGLSL; + drawStyle = GLU.GLU_FILL; + orientation = GLU.GLU_OUTSIDE; + textureFlag = false; + normals = GLU.GLU_SMOOTH; + normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT; + immModeSinkImmediate=true; + immModeSinkEnabled=!gl.isGL2(); + replaceImmModeSink(); + } + + public void enableImmModeSink(boolean val) { + if(gl.isGL2()) { + immModeSinkEnabled=val; + } else { + immModeSinkEnabled=true; + } + if(null==immModeSink && immModeSinkEnabled) { + replaceImmModeSink(); + } + } + + public boolean isImmModeSinkEnabled() { + return immModeSinkEnabled; + } + + public void setImmMode(boolean val) { + if(immModeSinkEnabled) { + immModeSinkImmediate=val; + } else { + immModeSinkImmediate=true; + } + } + + public boolean getImmMode() { + return immModeSinkImmediate; + } + + public ImmModeSink replaceImmModeSink() { + if(!immModeSinkEnabled) return null; + + ImmModeSink res = immModeSink; + if(useGLSL) { + immModeSink = ImmModeSink.createGLSL (gl, GL.GL_STATIC_DRAW, 32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, normalType,// normal + USE_TEXT?2:0, GL.GL_FLOAT); // texture + } else { + immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, normalType,// normal + USE_TEXT?2:0, GL.GL_FLOAT); // texture + } + return res; + } + + public void resetImmModeSink(GL gl) { + if(immModeSinkEnabled) { + immModeSink.reset(gl); + } + } + + /** + * specifies the draw style for quadrics. + * + * The legal values are as follows: + * + * GLU.FILL: Quadrics are rendered with polygon primitives. The polygons + * are drawn in a counterclockwise fashion with respect to + * their normals (as defined with glu.quadricOrientation). + * + * GLU.LINE: Quadrics are rendered as a set of lines. + * + * GLU.SILHOUETTE: Quadrics are rendered as a set of lines, except that edges + * separating coplanar faces will not be drawn. + * + * GLU.POINT: Quadrics are rendered as a set of points. + * + * @param drawStyle The drawStyle to set + */ + public void setDrawStyle(int drawStyle) { + this.drawStyle = drawStyle; + } + + /** + * specifies what kind of normals are desired for quadrics. + * The legal values are as follows: + * + * GLU.NONE: No normals are generated. + * + * GLU.FLAT: One normal is generated for every facet of a quadric. + * + * GLU.SMOOTH: One normal is generated for every vertex of a quadric. This + * is the default. + * + * @param normals The normals to set + */ + public void setNormals(int normals) { + this.normals = normals; + } + + /** + * specifies what kind of orientation is desired for. + * The orientation values are as follows: + * + * GLU.OUTSIDE: Quadrics are drawn with normals pointing outward. + * + * GLU.INSIDE: Normals point inward. The default is GLU.OUTSIDE. + * + * Note that the interpretation of outward and inward depends on the quadric + * being drawn. + * + * @param orientation The orientation to set + */ + public void setOrientation(int orientation) { + this.orientation = orientation; + } + + /** + * specifies if texture coordinates should be generated for + * quadrics rendered with qobj. If the value of textureCoords is true, + * then texture coordinates are generated, and if textureCoords is false, + * they are not.. The default is false. + * + * The manner in which texture coordinates are generated depends upon the + * specific quadric rendered. + * + * @param textureFlag The textureFlag to set + */ + public void setTextureFlag(boolean textureFlag) { + this.textureFlag = textureFlag; + } + + /** + * Returns the drawStyle. + * @return int + */ + public int getDrawStyle() { + return drawStyle; + } + + /** + * Returns the normals. + * @return int + */ + public int getNormals() { + return normals; + } + + /** + * Returns the orientation. + * @return int + */ + public int getOrientation() { + return orientation; + } + + /** + * Returns the textureFlag. + * @return boolean + */ + public boolean getTextureFlag() { + return textureFlag; + } + + + /** + * draws a cylinder oriented along the z axis. The base of the + * cylinder is placed at z = 0, and the top at z=height. Like a sphere, a + * cylinder is subdivided around the z axis into slices, and along the z axis + * into stacks. + * + * Note that if topRadius is set to zero, then this routine will generate a + * cone. + * + * If the orientation is set to GLU.OUTSIDE (with glu.quadricOrientation), then + * any generated normals point away from the z axis. Otherwise, they point + * toward the z axis. + * + * If texturing is turned on (with glu.quadricTexture), then texture + * coordinates are generated so that t ranges linearly from 0.0 at z = 0 to + * 1.0 at z = height, and s ranges from 0.0 at the +y axis, to 0.25 at the +x + * axis, to 0.5 at the -y axis, to 0.75 at the -x axis, and back to 1.0 at the + * +y axis. + * + * @param baseRadius Specifies the radius of the cylinder at z = 0. + * @param topRadius Specifies the radius of the cylinder at z = height. + * @param height Specifies the height of the cylinder. + * @param slices Specifies the number of subdivisions around the z axis. + * @param stacks Specifies the number of subdivisions along the z axis. + */ + public void drawCylinder(GL gl, float baseRadius, float topRadius, float height, int slices, int stacks) { + + float da, r, dr, dz; + float x, y, z, nz, nsign; + int i, j; + + if (orientation == GLU.GLU_INSIDE) { + nsign = -1.0f; + } else { + nsign = 1.0f; + } + + da = 2.0f * PI / slices; + dr = (topRadius - baseRadius) / stacks; + dz = height / stacks; + nz = (baseRadius - topRadius) / height; + // Z component of normal vectors + + if (drawStyle == GLU.GLU_POINT) { + glBegin(gl, GL.GL_POINTS); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + + z = 0.0f; + r = baseRadius; + for (j = 0; j <= stacks; j++) { + glVertex3f(gl, (x * r), (y * r), z); + z += dz; + r += dr; + } + } + glEnd(gl); + } else if (drawStyle == GLU.GLU_LINE || drawStyle == GLU.GLU_SILHOUETTE) { + // Draw rings + if (drawStyle == GLU.GLU_LINE) { + z = 0.0f; + r = baseRadius; + for (j = 0; j <= stacks; j++) { + glBegin(gl, GL.GL_LINE_LOOP); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + glVertex3f(gl, (x * r), (y * r), z); + } + glEnd(gl); + z += dz; + r += dr; + } + } else { + // draw one ring at each end + if (baseRadius != 0.0) { + glBegin(gl, GL.GL_LINE_LOOP); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + glVertex3f(gl, (x * baseRadius), (y * baseRadius), 0.0f); + } + glEnd(gl); + glBegin(gl, GL.GL_LINE_LOOP); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + glVertex3f(gl, (x * topRadius), (y * topRadius), height); + } + glEnd(gl); + } + } + // draw length lines + glBegin(gl, GL.GL_LINES); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + glVertex3f(gl, (x * baseRadius), (y * baseRadius), 0.0f); + glVertex3f(gl, (x * topRadius), (y * topRadius), (height)); + } + glEnd(gl); + } else if (drawStyle == GLU.GLU_FILL) { + float ds = 1.0f / slices; + float dt = 1.0f / stacks; + float t = 0.0f; + z = 0.0f; + r = baseRadius; + for (j = 0; j < stacks; j++) { + float s = 0.0f; + glBegin(gl, immModeSink.GL_QUAD_STRIP); + for (i = 0; i <= slices; i++) { + if (i == slices) { + x = sin(0.0f); + y = cos(0.0f); + } else { + x = sin((i * da)); + y = cos((i * da)); + } + if (nsign == 1.0f) { + normal3f(gl, (x * nsign), (y * nsign), (nz * nsign)); + TXTR_COORD(gl, s, t); + glVertex3f(gl, (x * r), (y * r), z); + normal3f(gl, (x * nsign), (y * nsign), (nz * nsign)); + TXTR_COORD(gl, s, t + dt); + glVertex3f(gl, (x * (r + dr)), (y * (r + dr)), (z + dz)); + } else { + normal3f(gl, x * nsign, y * nsign, nz * nsign); + TXTR_COORD(gl, s, t); + glVertex3f(gl, (x * r), (y * r), z); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + TXTR_COORD(gl, s, t + dt); + glVertex3f(gl, (x * (r + dr)), (y * (r + dr)), (z + dz)); + } + s += ds; + } // for slices + glEnd(gl); + r += dr; + t += dt; + z += dz; + } // for stacks + } + } + + /** + * renders a disk on the z = 0 plane. The disk has a radius of + * outerRadius, and contains a concentric circular hole with a radius of + * innerRadius. If innerRadius is 0, then no hole is generated. The disk is + * subdivided around the z axis into slices (like pizza slices), and also + * about the z axis into rings (as specified by slices and loops, + * respectively). + * + * With respect to orientation, the +z side of the disk is considered to be + * "outside" (see glu.quadricOrientation). This means that if the orientation + * is set to GLU.OUTSIDE, then any normals generated point along the +z axis. + * Otherwise, they point along the -z axis. + * + * If texturing is turned on (with glu.quadricTexture), texture coordinates are + * generated linearly such that where r=outerRadius, the value at (r, 0, 0) is + * (1, 0.5), at (0, r, 0) it is (0.5, 1), at (-r, 0, 0) it is (0, 0.5), and at + * (0, -r, 0) it is (0.5, 0). + */ + public void drawDisk(GL gl, float innerRadius, float outerRadius, int slices, int loops) + { + float da, dr; + + /* Normal vectors */ + if (normals != GLU.GLU_NONE) { + if (orientation == GLU.GLU_OUTSIDE) { + glNormal3f(gl, 0.0f, 0.0f, +1.0f); + } + else { + glNormal3f(gl, 0.0f, 0.0f, -1.0f); + } + } + + da = 2.0f * PI / slices; + dr = (outerRadius - innerRadius) / loops; + + switch (drawStyle) { + case GLU.GLU_FILL: + { + /* texture of a gluDisk is a cut out of the texture unit square + * x, y in [-outerRadius, +outerRadius]; s, t in [0, 1] + * (linear mapping) + */ + float dtc = 2.0f * outerRadius; + float sa, ca; + float r1 = innerRadius; + int l; + for (l = 0; l < loops; l++) { + float r2 = r1 + dr; + if (orientation == GLU.GLU_OUTSIDE) { + int s; + glBegin(gl, immModeSink.GL_QUAD_STRIP); + for (s = 0; s <= slices; s++) { + float a; + if (s == slices) + a = 0.0f; + else + a = s * da; + sa = sin(a); + ca = cos(a); + TXTR_COORD(gl, 0.5f + sa * r2 / dtc, 0.5f + ca * r2 / dtc); + glVertex2f(gl, r2 * sa, r2 * ca); + TXTR_COORD(gl, 0.5f + sa * r1 / dtc, 0.5f + ca * r1 / dtc); + glVertex2f(gl, r1 * sa, r1 * ca); + } + glEnd(gl); + } + else { + int s; + glBegin(gl, immModeSink.GL_QUAD_STRIP); + for (s = slices; s >= 0; s--) { + float a; + if (s == slices) + a = 0.0f; + else + a = s * da; + sa = sin(a); + ca = cos(a); + TXTR_COORD(gl, 0.5f - sa * r2 / dtc, 0.5f + ca * r2 / dtc); + glVertex2f(gl, r2 * sa, r2 * ca); + TXTR_COORD(gl, 0.5f - sa * r1 / dtc, 0.5f + ca * r1 / dtc); + glVertex2f(gl, r1 * sa, r1 * ca); + } + glEnd(gl); + } + r1 = r2; + } + break; + } + case GLU.GLU_LINE: + { + int l, s; + /* draw loops */ + for (l = 0; l <= loops; l++) { + float r = innerRadius + l * dr; + glBegin(gl, GL.GL_LINE_LOOP); + for (s = 0; s < slices; s++) { + float a = s * da; + glVertex2f(gl, r * sin(a), r * cos(a)); + } + glEnd(gl); + } + /* draw spokes */ + for (s = 0; s < slices; s++) { + float a = s * da; + float x = sin(a); + float y = cos(a); + glBegin(gl, GL.GL_LINE_STRIP); + for (l = 0; l <= loops; l++) { + float r = innerRadius + l * dr; + glVertex2f(gl, r * x, r * y); + } + glEnd(gl); + } + break; + } + case GLU.GLU_POINT: + { + int s; + glBegin(gl, GL.GL_POINTS); + for (s = 0; s < slices; s++) { + float a = s * da; + float x = sin(a); + float y = cos(a); + int l; + for (l = 0; l <= loops; l++) { + float r = innerRadius * l * dr; + glVertex2f(gl, r * x, r * y); + } + } + glEnd(gl); + break; + } + case GLU.GLU_SILHOUETTE: + { + if (innerRadius != 0.0) { + float a; + glBegin(gl, GL.GL_LINE_LOOP); + for (a = 0.0f; a < 2.0 * PI; a += da) { + float x = innerRadius * sin(a); + float y = innerRadius * cos(a); + glVertex2f(gl, x, y); + } + glEnd(gl); + } + { + float a; + glBegin(gl, GL.GL_LINE_LOOP); + for (a = 0; a < 2.0f * PI; a += da) { + float x = outerRadius * sin(a); + float y = outerRadius * cos(a); + glVertex2f(gl, x, y); + } + glEnd(gl); + } + break; + } + default: + return; + } + } + + /** + * renders a partial disk on the z=0 plane. A partial disk is similar to a + * full disk, except that only the subset of the disk from startAngle + * through startAngle + sweepAngle is included (where 0 degrees is along + * the +y axis, 90 degrees along the +x axis, 180 along the -y axis, and + * 270 along the -x axis). + * + * The partial disk has a radius of outerRadius, and contains a concentric + * circular hole with a radius of innerRadius. If innerRadius is zero, then + * no hole is generated. The partial disk is subdivided around the z axis + * into slices (like pizza slices), and also about the z axis into rings + * (as specified by slices and loops, respectively). + * + * With respect to orientation, the +z side of the partial disk is + * considered to be outside (see gluQuadricOrientation). This means that if + * the orientation is set to GLU.GLU_OUTSIDE, then any normals generated point + * along the +z axis. Otherwise, they point along the -z axis. + * + * If texturing is turned on (with gluQuadricTexture), texture coordinates + * are generated linearly such that where r=outerRadius, the value at (r, 0, 0) + * is (1, 0.5), at (0, r, 0) it is (0.5, 1), at (-r, 0, 0) it is (0, 0.5), + * and at (0, -r, 0) it is (0.5, 0). + */ + public void drawPartialDisk(GL gl, + float innerRadius, + float outerRadius, + int slices, + int loops, + float startAngle, + float sweepAngle) { + int i, j, max; + float[] sinCache = new float[CACHE_SIZE]; + float[] cosCache = new float[CACHE_SIZE]; + float angle; + float x, y; + float sintemp, costemp; + float deltaRadius; + float radiusLow, radiusHigh; + float texLow = 0, texHigh = 0; + float angleOffset; + int slices2; + int finish; + + if (slices >= CACHE_SIZE) + slices = CACHE_SIZE - 1; + if (slices < 2 + || loops < 1 + || outerRadius <= 0.0f + || innerRadius < 0.0f + || innerRadius > outerRadius) { + //gluQuadricError(qobj, GLU.GLU_INVALID_VALUE); + System.err.println("PartialDisk: GLU_INVALID_VALUE"); + return; + } + + if (sweepAngle < -360.0f) + sweepAngle = 360.0f; + if (sweepAngle > 360.0f) + sweepAngle = 360.0f; + if (sweepAngle < 0) { + startAngle += sweepAngle; + sweepAngle = -sweepAngle; + } + + if (sweepAngle == 360.0f) { + slices2 = slices; + } else { + slices2 = slices + 1; + } + + /* Compute length (needed for normal calculations) */ + deltaRadius = outerRadius - innerRadius; + + /* Cache is the vertex locations cache */ + + angleOffset = startAngle / 180.0f * PI; + for (i = 0; i <= slices; i++) { + angle = angleOffset + ((PI * sweepAngle) / 180.0f) * i / slices; + sinCache[i] = sin(angle); + cosCache[i] = cos(angle); + } + + if (sweepAngle == 360.0f) { + sinCache[slices] = sinCache[0]; + cosCache[slices] = cosCache[0]; + } + + switch (normals) { + case GLU.GLU_FLAT : + case GLU.GLU_SMOOTH : + if (orientation == GLU.GLU_OUTSIDE) { + glNormal3f(gl, 0.0f, 0.0f, 1.0f); + } else { + glNormal3f(gl, 0.0f, 0.0f, -1.0f); + } + break; + default : + case GLU.GLU_NONE : + break; + } + + switch (drawStyle) { + case GLU.GLU_FILL : + if (innerRadius == .0f) { + finish = loops - 1; + /* Triangle strip for inner polygons */ + glBegin(gl, GL.GL_TRIANGLE_FAN); + if (textureFlag) { + glTexCoord2f(gl, 0.5f, 0.5f); + } + glVertex3f(gl, 0.0f, 0.0f, 0.0f); + radiusLow = outerRadius - deltaRadius * ((float) (loops - 1) / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + if (orientation == GLU.GLU_OUTSIDE) { + for (i = slices; i >= 0; i--) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } else { + for (i = 0; i <= slices; i++) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } + glEnd(gl); + } else { + finish = loops; + } + for (j = 0; j < finish; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + radiusHigh = outerRadius - deltaRadius * ((float) (j + 1) / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + texHigh = radiusHigh / outerRadius / 2; + } + + glBegin(gl, immModeSink.GL_QUAD_STRIP); + for (i = 0; i <= slices; i++) { + if (orientation == GLU.GLU_OUTSIDE) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + + if (textureFlag) { + glTexCoord2f(gl, texHigh * sinCache[i] + 0.5f, + texHigh * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusHigh * sinCache[i], + radiusHigh * cosCache[i], + 0.0f); + } else { + if (textureFlag) { + glTexCoord2f(gl, texHigh * sinCache[i] + 0.5f, + texHigh * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusHigh * sinCache[i], + radiusHigh * cosCache[i], + 0.0f); + + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } + glEnd(gl); + } + break; + case GLU.GLU_POINT : + glBegin(gl, GL.GL_POINTS); + for (i = 0; i < slices2; i++) { + sintemp = sinCache[i]; + costemp = cosCache[i]; + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + } + glEnd(gl); + break; + case GLU.GLU_LINE : + if (innerRadius == outerRadius) { + glBegin(gl, GL.GL_LINE_STRIP); + + for (i = 0; i <= slices; i++) { + if (textureFlag) { + glTexCoord2f(gl, sinCache[i] / 2 + 0.5f, cosCache[i] / 2 + 0.5f); + } + glVertex3f(gl, innerRadius * sinCache[i], innerRadius * cosCache[i], 0.0f); + } + glEnd(gl); + break; + } + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + glBegin(gl, GL.GL_LINE_STRIP); + for (i = 0; i <= slices; i++) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + glEnd(gl); + } + for (i = 0; i < slices2; i++) { + sintemp = sinCache[i]; + costemp = cosCache[i]; + glBegin(gl, GL.GL_LINE_STRIP); + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + glEnd(gl); + } + break; + case GLU.GLU_SILHOUETTE : + if (sweepAngle < 360.0f) { + for (i = 0; i <= slices; i += slices) { + sintemp = sinCache[i]; + costemp = cosCache[i]; + glBegin(gl, GL.GL_LINE_STRIP); + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + glEnd(gl); + } + } + for (j = 0; j <= loops; j += loops) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + glBegin(gl, GL.GL_LINE_STRIP); + for (i = 0; i <= slices; i++) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + glEnd(gl); + if (innerRadius == outerRadius) + break; + } + break; + default : + break; + } + } + + /** + * draws a sphere of the given radius centered around the origin. + * The sphere is subdivided around the z axis into slices and along the z axis + * into stacks (similar to lines of longitude and latitude). + * + * If the orientation is set to GLU.OUTSIDE (with glu.quadricOrientation), then + * any normals generated point away from the center of the sphere. Otherwise, + * they point toward the center of the sphere. + + * If texturing is turned on (with glu.quadricTexture), then texture + * coordinates are generated so that t ranges from 0.0 at z=-radius to 1.0 at + * z=radius (t increases linearly along longitudinal lines), and s ranges from + * 0.0 at the +y axis, to 0.25 at the +x axis, to 0.5 at the -y axis, to 0.75 + * at the -x axis, and back to 1.0 at the +y axis. + */ + public void drawSphere(GL gl, float radius, int slices, int stacks) { + // TODO + + float rho, drho, theta, dtheta; + float x, y, z; + float s, t, ds, dt; + int i, j, imin, imax; + boolean normals; + float nsign; + + normals = (this.normals != GLU.GLU_NONE); + + if (orientation == GLU.GLU_INSIDE) { + nsign = -1.0f; + } else { + nsign = 1.0f; + } + + drho = PI / stacks; + dtheta = 2.0f * PI / slices; + + if (drawStyle == GLU.GLU_FILL) { + if (!textureFlag) { + // draw +Z end as a triangle fan + glBegin(gl, GL.GL_TRIANGLE_FAN); + glNormal3f(gl, 0.0f, 0.0f, 1.0f); + glVertex3f(gl, 0.0f, 0.0f, nsign * radius); + for (j = 0; j <= slices; j++) { + theta = (j == slices) ? 0.0f : j * dtheta; + x = -sin(theta) * sin(drho); + y = cos(theta) * sin(drho); + z = nsign * cos(drho); + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + } + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + } + + ds = 1.0f / slices; + dt = 1.0f / stacks; + t = 1.0f; // because loop now runs from 0 + if (textureFlag) { + imin = 0; + imax = stacks; + } else { + imin = 1; + imax = stacks - 1; + } + + // draw intermediate stacks as quad strips + for (i = imin; i < imax; i++) { + rho = i * drho; + glBegin(gl, immModeSink.GL_QUAD_STRIP); + s = 0.0f; + for (j = 0; j <= slices; j++) { + theta = (j == slices) ? 0.0f : j * dtheta; + x = -sin(theta) * sin(rho); + y = cos(theta) * sin(rho); + z = nsign * cos(rho); + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + } + TXTR_COORD(gl, s, t); + glVertex3f(gl, x * radius, y * radius, z * radius); + x = -sin(theta) * sin(rho + drho); + y = cos(theta) * sin(rho + drho); + z = nsign * cos(rho + drho); + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + } + TXTR_COORD(gl, s, t - dt); + s += ds; + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + t -= dt; + } + + if (!textureFlag) { + // draw -Z end as a triangle fan + glBegin(gl, GL.GL_TRIANGLE_FAN); + glNormal3f(gl, 0.0f, 0.0f, -1.0f); + glVertex3f(gl, 0.0f, 0.0f, -radius * nsign); + rho = PI - drho; + s = 1.0f; + for (j = slices; j >= 0; j--) { + theta = (j == slices) ? 0.0f : j * dtheta; + x = -sin(theta) * sin(rho); + y = cos(theta) * sin(rho); + z = nsign * cos(rho); + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + s -= ds; + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + } + } else if ( + drawStyle == GLU.GLU_LINE + || drawStyle == GLU.GLU_SILHOUETTE) { + // draw stack lines + for (i = 1; + i < stacks; + i++) { // stack line at i==stacks-1 was missing here + rho = i * drho; + glBegin(gl, GL.GL_LINE_LOOP); + for (j = 0; j < slices; j++) { + theta = j * dtheta; + x = cos(theta) * sin(rho); + y = sin(theta) * sin(rho); + z = cos(rho); + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + } + // draw slice lines + for (j = 0; j < slices; j++) { + theta = j * dtheta; + glBegin(gl, GL.GL_LINE_STRIP); + for (i = 0; i <= stacks; i++) { + rho = i * drho; + x = cos(theta) * sin(rho); + y = sin(theta) * sin(rho); + z = cos(rho); + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + } + } else if (drawStyle == GLU.GLU_POINT) { + // top and bottom-most points + glBegin(gl, GL.GL_POINTS); + if (normals) + glNormal3f(gl, 0.0f, 0.0f, nsign); + glVertex3f(gl, 0.0f, 0.0f, radius); + if (normals) + glNormal3f(gl, 0.0f, 0.0f, -nsign); + glVertex3f(gl, 0.0f, 0.0f, -radius); + + // loop over stacks + for (i = 1; i < stacks - 1; i++) { + rho = i * drho; + for (j = 0; j < slices; j++) { + theta = j * dtheta; + x = cos(theta) * sin(rho); + y = sin(theta) * sin(rho); + z = cos(rho); + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + glVertex3f(gl, x * radius, y * radius, z * radius); + } + } + glEnd(gl); + } + } + + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static final float PI = (float)Math.PI; + private static final int CACHE_SIZE = 240; + + private final void glBegin(GL gl, int mode) { + if(immModeSinkEnabled) { + immModeSink.glBegin(mode); + } else { + gl.getGL2().glBegin(mode); + } + } + + private final void glEnd(GL gl) { + if(immModeSinkEnabled) { + immModeSink.glEnd(gl, immModeSinkImmediate); + } else { + gl.getGL2().glEnd(); + } + } + + private final void glVertex2f(GL gl, float x, float y) { + if(immModeSinkEnabled) { + immModeSink.glVertex2f(x, y); + } else { + gl.getGL2().glVertex2f(x, y); + } + } + + private final void glVertex3f(GL gl, float x, float y, float z) { + if(immModeSinkEnabled) { + immModeSink.glVertex3f(x, y, z); + } else { + gl.getGL2().glVertex3f(x, y, z); + } + } + + private final void glNormal3f_s(GL gl, float x, float y, float z) { + short a=(short)(x*0xFFFF); + short b=(short)(y*0xFFFF); + short c=(short)(z*0xFFFF); + if(immModeSinkEnabled) { + immModeSink.glNormal3s(a, b, c); + } else { + gl.getGL2().glNormal3s(a, b, c); + } + } + + private final void glNormal3f_b(GL gl, float x, float y, float z) { + byte a=(byte)(x*0xFF); + byte b=(byte)(y*0xFF); + byte c=(byte)(z*0xFF); + if(immModeSinkEnabled) { + immModeSink.glNormal3b(a, b, c); + } else { + gl.getGL2().glNormal3b(a, b, c); + } + } + + private final void glNormal3f(GL gl, float x, float y, float z) { + switch(normalType) { + case GL.GL_FLOAT: + if(immModeSinkEnabled) { + immModeSink.glNormal3f(x,y,z); + } else { + gl.getGL2().glNormal3f(x,y,z); + } + break; + case GL.GL_SHORT: + glNormal3f_s(gl, x, y, z); + break; + case GL.GL_BYTE: + glNormal3f_b(gl, x, y, z); + break; + } + } + + private final void glTexCoord2f(GL gl, float x, float y) { + if(immModeSinkEnabled) { + immModeSink.glTexCoord2f(x, y); + } else { + gl.getGL2().glTexCoord2f(x, y); + } + } + + /** + * Call glNormal3f after scaling normal to unit length. + * + * @param x + * @param y + * @param z + */ + private void normal3f(GL gl, float x, float y, float z) { + float mag; + + mag = (float)Math.sqrt(x * x + y * y + z * z); + if (mag > 0.00001F) { + x /= mag; + y /= mag; + z /= mag; + } + glNormal3f(gl, x, y, z); + } + + private final void TXTR_COORD(GL gl, float x, float y) { + if (textureFlag) glTexCoord2f(gl, x,y); + } + + private float sin(float r) { + return (float)Math.sin(r); + } + + private float cos(float r) { + return (float)Math.cos(r); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/Glue.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/Glue.java new file mode 100755 index 000000000..7c360c574 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/Glue.java @@ -0,0 +1,114 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu; + +/** + * + * @author Administrator + */ +public class Glue { + private static String[] __gluNurbsErrors = { + " ", + "spline order un-supported", + "too few knots", + "valid knot range is empty", + "decreasing knot sequence knot", + "knot multiplicity greater than order of spline", + "gluEndCurve() must follow gluBeginCurve()", + "gluBeginCurve() must precede gluEndCurve()", + "missing or extra geometric data", + "can't draw piecewise linear trimming curves", + "missing or extra domain data", + "missing or extra domain data", + "gluEndTrim() must precede gluEndSurface()", + "gluBeginSurface() must precede gluEndSurface()", + "curve of improper type passed as trim curve", + "gluBeginSurface() must precede gluBeginTrim()", + "gluEndTrim() must follow gluBeginTrim()", + "gluBeginTrim() must follow gluEndTrim()", + "invalid or missing trim curve", + "gluBeginTrim() must precede gluPwlCurve()", + "piecewise linear trimming curve referenced twice", + "piecewise linear trimming curve and nurbs curve mixed", + "improper usage of trim data type", + "nurbs curve referenced twice", + "nurbs curve and piecewise linear trimming curve mixed", + "nurbs surface referenced twice", + "invalid property", + "gluEndSurface() must follow gluBeginSurface()", + "intersecting or misoriented trim curve", + "intersecting trim curves", + "UNUSED", + "inconnected trim curves", + "unknown knot error", + "negative vertex count encountered", + "negative byte-stride encountered", + "unknown type descriptor", + "null control point reference", + "duplicate point on piecewise linear trimming curve" + } ; + + /** Creates a new instance of Glue */ + public Glue() { + } + + public static String __gluNURBSErrorString( int errno ) { + return( __gluNurbsErrors[ errno ] ); + } + + private static String[] __gluTessErrors = { + " ", + "gluTessBeginPolygon() must precede a gluTessEndPolygon", + "gluTessBeginContour() must precede a gluTessEndContour()", + "gluTessEndPolygon() must follow a gluTessBeginPolygon()", + "gluTessEndContour() must follow a gluTessBeginContour()", + "a coordinate is too large", + "need combine callback" + }; + + public static String __gluTessErrorString( int errno ) { + return( __gluTessErrors[ errno ] ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/error/Error.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/error/Error.java new file mode 100644 index 000000000..7c7e6b0d8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/error/Error.java @@ -0,0 +1,100 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.error; + +import javax.media.opengl.GL; +import javax.media.opengl.glu.GLU; +import com.jogamp.opengl.impl.glu.Glue; + +/** + * + * @author Administrator + */ +public class Error { + + private static String[] glErrorStrings = { + "invalid enumerant", + "invalid value", + "invalid operation", + "stack overflow", + "stack underflow", + "out of memory", + "invalid framebuffer operation" + }; + + private static String[] gluErrorStrings = { + "invalid enumerant", + "invalid value", + "out of memory", + "", + "invalid operation" + }; + + /** Creates a new instance of Error */ + public Error() { + } + + public static String gluErrorString( int errorCode ) { + if( errorCode == 0 ) { + return( "no error" ); + } + if( (errorCode >= GL.GL_INVALID_ENUM) && (errorCode <= GL.GL_INVALID_FRAMEBUFFER_OPERATION) ) { + return( glErrorStrings[ errorCode - GL.GL_INVALID_ENUM ] ); + } + if( errorCode == 0x8031 /* GL.GL_TABLE_TOO_LARGE */ ) { + return( "table too large" ); + } + if( (errorCode >= GLU.GLU_INVALID_ENUM) && (errorCode <= GLU.GLU_INVALID_OPERATION) ) { + return( gluErrorStrings[ errorCode - GLU.GLU_INVALID_ENUM ] ); + } +// if( (errorCode >= GLU.GLU_NURBS_ERROR1) && (errorCode <= GLU.GLU_NURBS_ERROR37) ) { +// return( gluErrorStrings[ errorCode - (GLU.GLU_NURBS_ERROR1 - 1) ] ); +// } + if( (errorCode >= GLU.GLU_TESS_ERROR1) && (errorCode <= GLU.GLU_TESS_ERROR8) ) { + return( Glue.__gluTessErrorString(errorCode - (GLU.GLU_TESS_ERROR1 - 1)) ); + } + return( "error ("+errorCode+")" ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2Backend.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2Backend.java new file mode 100755 index 000000000..42ddeea50 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2Backend.java @@ -0,0 +1,49 @@ +package com.jogamp.opengl.impl.glu.gl2.nurbs; +import com.jogamp.opengl.impl.glu.nurbs.*; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class responsible for rendering + * @author Tomas Hrasky + * + */ +public class GL2Backend extends Backend { + public GL2Backend() { + super(); + curveEvaluator = new GL2CurveEvaluator(); + surfaceEvaluator = new GL2SurfaceEvaluator(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2CurveEvaluator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2CurveEvaluator.java new file mode 100755 index 000000000..adb8c51d8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2CurveEvaluator.java @@ -0,0 +1,205 @@ +package com.jogamp.opengl.impl.glu.gl2.nurbs; +import com.jogamp.opengl.impl.glu.nurbs.*; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.gl2.GLUgl2; + +/** + * Class rendering curves with OpenGL + * @author Tomáš Hráský + * + */ +class GL2CurveEvaluator implements CurveEvaluator { + + /** + * Output triangles (for callback) or render curve + */ + private boolean output_triangles; + + /** + * OpenGL object + */ + private GL2 gl; + + /** + * Not used + */ + private int vertex_flag; + + /** + * Not used + */ + private int normal_flag; + + /** + * Not used + */ + private int color_flag; + + /** + * Not used + */ + private int texcoord_flag; + + /** + * Number of bezier arc - used for color distinguishing of arcs forming NURBS curve + */ + private int poradi; + + /** + * Makes new Evaluator + */ + public GL2CurveEvaluator() { + gl = GLUgl2.getCurrentGL2(); + } + + /** + * Pushes eval bit + */ + public void bgnmap1f() { + // DONE + if (output_triangles) { + vertex_flag = 0; + normal_flag = 0; + color_flag = 0; + texcoord_flag = 0; + } else { + gl.glPushAttrib(GL2.GL_EVAL_BIT); + } + + } + + /** + * Pops all OpenGL attributes + */ + public void endmap1f() { + // DONE + if (output_triangles) { + + } else { + gl.glPopAttrib(); + } + + } + + /** + * Initializes opengl evaluator + * @param type curve type + * @param ulo lowest u + * @param uhi highest u + * @param stride control point coords + * @param order curve order + * @param ps control points + */ + public void map1f(int type, float ulo, float uhi, int stride, int order, + CArrayOfFloats ps) { + if (output_triangles) { + // TODO code for callback (output_triangles probably indicates callback) + // System.out.println("TODO curveevaluator.map1f-output_triangles"); + } else { + gl.glMap1f(type, ulo, uhi, stride, order, ps.getArray(), ps + .getPointer()); + + // DEBUG - drawing bézier control points + // gl.glColor3d(.5,.5,.5); + // gl.glPointSize(5); + // gl.glBegin(GL2.GL_POINTS); + // float[] ctrlpoints=ps.getArray(); + // for(int i=ps.getPointer();i<ps.getPointer()+order;i++){ + // gl.glVertex3d(ctrlpoints[i * 4], ctrlpoints[i * 4 + 1],0); + // } + // gl.glEnd(); + } + + } + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) { + // DONE + gl.glEnable(type); + } + + /** + * Calls glMapGrid1f + * @param nu steps + * @param u1 low u + * @param u2 high u + */ + public void mapgrid1f(int nu, float u1, float u2) { + if (output_triangles) { + // System.out.println("TODO curveevaluator.mapgrid1f"); + } else + gl.glMapGrid1f(nu, u1, u2); + // // System.out.println("upravit NU"); + // gl.glMapGrid1f(50,u1,u2); + } + + /** + * Evaluates a curve using glEvalMesh1f + * @param style Backend.N_MESHFILL/N_MESHLINE/N_MESHPOINT + * @param from lowest param + * @param to highest param + */ + public void mapmesh1f(int style, int from, int to) { + /* //DEBUG drawing control points + this.poradi++; + if (poradi % 2 == 0) + gl.glColor3f(1, 0, 0); + else + gl.glColor3f(0, 1, 0); + */ + if (output_triangles) { + // TODO code for callback + // System.out.println("TODO openglcurveevaluator.mapmesh1f output_triangles"); + } else { + switch (style) { + case Backend.N_MESHFILL: + case Backend.N_MESHLINE: + gl.glEvalMesh1(GL2.GL_LINE, from, to); + break; + case Backend.N_MESHPOINT: + gl.glEvalMesh1(GL2.GL_POINT, from, to); + break; + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2SurfaceEvaluator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2SurfaceEvaluator.java new file mode 100755 index 000000000..393601ff7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2SurfaceEvaluator.java @@ -0,0 +1,217 @@ +package com.jogamp.opengl.impl.glu.gl2.nurbs; +import com.jogamp.opengl.impl.glu.nurbs.*; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.gl2.GLUgl2; + +/** + * Class rendering surfaces with OpenGL + * @author Tomas Hrasky + * + */ +class GL2SurfaceEvaluator implements SurfaceEvaluator { + + /** + * JOGL OpenGL object + */ + private GL2 gl; + + /** + * Output triangles (callback) + */ + private boolean output_triangles; + + /** + * Number of patch - used for distinguishing bezier plates forming NURBS surface with different colors + */ + private int poradi; + + /** + * Creates new evaluator + */ + public GL2SurfaceEvaluator() { + gl = GLUgl2.getCurrentGL2(); + } + + /** + * Pushes eval bit + */ + public void bgnmap2f() { + + if (output_triangles) { + // TODO outp triangles surfaceevaluator bgnmap2f + // System.out.println("TODO surfaceevaluator.bgnmap2f output triangles"); + } else { + gl.glPushAttrib(GL2.GL_EVAL_BIT); + // System.out.println("TODO surfaceevaluator.bgnmap2f glgetintegerv"); + } + + } + + /** + * Sets glPolygonMode + * @param style polygon mode (N_MESHFILL/N_MESHLINE/N_MESHPOINT) + */ + public void polymode(int style) { + if (!output_triangles) { + switch (style) { + default: + case NurbsConsts.N_MESHFILL: + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); + break; + case NurbsConsts.N_MESHLINE: + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE); + break; + case NurbsConsts.N_MESHPOINT: + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_POINT); + break; + } + } + + } + + /** + * Pops all attributes + */ + public void endmap2f() { + // TODO Auto-generated method stub + if (output_triangles) { + // System.out.println("TODO surfaceevaluator.endmap2f output triangles"); + } else { + gl.glPopAttrib(); + // TODO use LOD + } + } + + /** + * Empty method + * @param ulo + * @param uhi + * @param vlo + * @param vhi + */ + public void domain2f(float ulo, float uhi, float vlo, float vhi) { + // DONE + } + + /** + * Defines 2D mesh + * @param nu number of steps in u direction + * @param u0 lowest u + * @param u1 highest u + * @param nv number of steps in v direction + * @param v0 lowest v + * @param v1 highest v + */ + public void mapgrid2f(int nu, float u0, float u1, int nv, float v0, float v1) { + + if (output_triangles) { + // System.out.println("TODO openglsurfaceavaluator.mapgrid2f output_triangles"); + } else { + gl.glMapGrid2d(nu, u0, u1, nv, v0, v1); + } + + } + + /** + * Evaluates surface + * @param style surface style + * @param umin minimum U + * @param umax maximum U + * @param vmin minimum V + * @param vmax maximum V + */ + public void mapmesh2f(int style, int umin, int umax, int vmin, int vmax) { + if (output_triangles) { + // System.out.println("TODO openglsurfaceavaluator.mapmesh2f output_triangles"); + } else { + /* //DEBUG - draw control points + this.poradi++; + if (poradi % 2 == 0) + gl.glColor3f(1, 0, 0); + else if (poradi % 2 == 1) + gl.glColor3f(0, 1, 0); + */ + switch (style) { + case NurbsConsts.N_MESHFILL: + gl.glEvalMesh2(GL2.GL_FILL, umin, umax, vmin, vmax); + break; + case NurbsConsts.N_MESHLINE: + gl.glEvalMesh2(GL2.GL_LINE, umin, umax, vmin, vmax); + break; + case NurbsConsts.N_MESHPOINT: + gl.glEvalMesh2(GL2.GL_POINT, umin, umax, vmin, vmax); + break; + } + } + } + + /** + * Initializes evaluator + * @param type surface type + * @param ulo lowest u + * @param uhi highest u + * @param ustride number of objects between control points in u direction + * @param uorder surface order in u direction + * @param vlo lowest v + * @param vhi highest v + * @param vstride number of control points' coords + * @param vorder surface order in v direction + * @param pts control points + */ + public void map2f(int type, float ulo, float uhi, int ustride, int uorder, + float vlo, float vhi, int vstride, int vorder, CArrayOfFloats pts) { + // TODO Auto-generated method stub + if (output_triangles) { + // System.out.println("TODO openglsurfaceevaluator.map2f output_triangles"); + } else { + gl.glMap2f(type, ulo, uhi, ustride, uorder, vlo, vhi, vstride, + vorder, pts.getArray(), pts.getPointer()); + } + } + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) { + //DONE + gl.glEnable(type); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GLUgl2nurbsImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GLUgl2nurbsImpl.java new file mode 100755 index 000000000..13b68138c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GLUgl2nurbsImpl.java @@ -0,0 +1,862 @@ +package com.jogamp.opengl.impl.glu.gl2.nurbs; +import com.jogamp.opengl.impl.glu.nurbs.*; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import java.lang.reflect.Method; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLUnurbs; + +/** + * Base object for working with NURBS curves and surfaces + * + * @author Tomas Hrasky + * + */ +public class GLUgl2nurbsImpl implements GLUnurbs { + + /** + * Curve type - no type + */ + public static final int CT_NONE = 0; + + /** + * Curve type - NURBS curve + */ + public static final int CT_NURBSCURVE = 1; + + /** + * Curve type - picewise linear curve + */ + public static final int CT_NPWLCURVE = 2; + + /** + * Matrixes autoloading + */ + private boolean autoloadmode; + + /** + * Using callback + */ + private int callBackFlag; + + /** + * Object for error call backs + */ + private Object errorCallback; + + /** + * List of map definitions + */ + Maplist maplist; + + /** + * Indicates validity of data + */ + private int isDataValid; + + /** + * Are we in the middle of curve processing + */ + private int inCurve; + + /** + * Current curve + */ + private O_curve currentCurve; + + /** + * Are we in trim + */ + private boolean inTrim; + + /** + * Are we playbacking curve/surface rendering + */ + private boolean playBack; + + /** + * Next curve in linked list + */ + private O_curve nextCurve; + + /** + * Is curve modified + */ + private int isCurveModified; + + /** + * Object holding rendering settings + */ + private Renderhints renderhints; + + /** + * Display list + */ + private DisplayList dl; + + /** + * Object for subdividing curves and surfaces + */ + private Subdivider subdivider; + + /** + * Object responsible for rendering + */ + private Backend backend; + + /** + * Next picewise linear curve in linked list + */ + private O_pwlcurve nextPwlcurve; + + /** + * Next trimming NURBS curve in linked list + */ + private O_nurbscurve nextNurbscurve; + + /** + * Are we in the middle of surface processing + */ + private int inSurface; + + /** + * Are there any changes in trimming + */ + private boolean isTrimModified; + + /** + * Are there any changes in surface data + */ + private boolean isDataSurfaceModified; + + /** + * Nurber of trmims of processed surface + */ + private int numTrims; + + /** + * Current processed surface + */ + private O_surface currentSurface; + + /** + * Next trimming curve + */ + private O_trim nextTrim; + + /** + * Nextr surface in linked list + */ + private O_nurbssurface nextNurbssurface; + + /** + * Are there any changes in surface + */ + private boolean isSurfaceModified; + + /** + * Initializes default GLUgl2nurbs object + */ + public GLUgl2nurbsImpl() { + // DONE + maplist = new Maplist(backend); + renderhints = new Renderhints(); + subdivider = new Subdivider(); + // original code + + redefineMaps(); + + defineMap(GL2.GL_MAP2_NORMAL, 0, 3); + defineMap(GL2.GL_MAP1_NORMAL, 0, 3); + defineMap(GL2.GL_MAP2_TEXTURE_COORD_1, 0, 1); + defineMap(GL2.GL_MAP1_TEXTURE_COORD_1, 0, 1); + defineMap(GL2.GL_MAP2_TEXTURE_COORD_2, 0, 2); + defineMap(GL2.GL_MAP1_TEXTURE_COORD_2, 0, 2); + defineMap(GL2.GL_MAP2_TEXTURE_COORD_3, 0, 3); + defineMap(GL2.GL_MAP1_TEXTURE_COORD_3, 0, 3); + defineMap(GL2.GL_MAP2_TEXTURE_COORD_4, 1, 4); + defineMap(GL2.GL_MAP1_TEXTURE_COORD_4, 1, 4); + defineMap(GL2.GL_MAP2_VERTEX_4, 1, 4); + defineMap(GL2.GL_MAP1_VERTEX_4, 1, 4); + defineMap(GL2.GL_MAP2_VERTEX_3, 0, 3); + defineMap(GL2.GL_MAP1_VERTEX_3, 0, 3); + defineMap(GL2.GL_MAP2_COLOR_4, 0, 4); + defineMap(GL2.GL_MAP1_COLOR_4, 0, 4); + defineMap(GL2.GL_MAP2_INDEX, 0, 1); + defineMap(GL2.GL_MAP1_INDEX, 0, 1); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_SAMPLINGMETHOD, + (float) NurbsConsts.N_PATHLENGTH); + setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_SAMPLINGMETHOD, + (float) NurbsConsts.N_PATHLENGTH); + setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_SAMPLINGMETHOD, + (float) NurbsConsts.N_PATHLENGTH); + setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_SAMPLINGMETHOD, + (float) NurbsConsts.N_PATHLENGTH); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_PIXEL_TOLERANCE, + (float) 50.0); + setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_PIXEL_TOLERANCE, + (float) 50.0); + setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_PIXEL_TOLERANCE, + (float) 50.0); + setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_PIXEL_TOLERANCE, + (float) 50.0); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_ERROR_TOLERANCE, + (float) 0.50); + setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_ERROR_TOLERANCE, + (float) 0.50); + setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_ERROR_TOLERANCE, + (float) 0.50); + setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_ERROR_TOLERANCE, + (float) 0.50); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_S_STEPS, + (float) 100.0); + setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_S_STEPS, + (float) 100.0); + setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_S_STEPS, + (float) 100.0); + setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_S_STEPS, + (float) 100.0); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_SAMPLINGMETHOD, + NurbsConsts.N_PATHLENGTH); + + set_domain_distance_u_rate(100.0); + set_domain_distance_v_rate(100.0); + set_is_domain_distance_sampling(0); + + this.autoloadmode = true; + + this.callBackFlag = 0; + + this.errorCallback = null; + } + + /** + * Sets domain distance for dom.dist. sampling in u direction + * + * @param d + * distance + */ + private void set_domain_distance_u_rate(double d) { + // DONE + subdivider.set_domain_distance_u_rate(d); + } + + /** + * Sets domain distance for dom.dist. sampling in v direction + * + * @param d + * distance + */ + private void set_domain_distance_v_rate(double d) { + // DONE + subdivider.set_domain_distance_v_rate(d); + } + + /** + * Begins new NURBS curve + */ + public void bgncurve() { + // DONE + O_curve o_curve = new O_curve(); + thread("do_bgncurve", o_curve); + } + + /** + * Calls a method with given name and passes argumet + * + * @param name + * name of a method to be called + * @param arg + * parameter to be passed to called method + */ + private void thread(String name, Object arg) { + // DONE + Class partype[] = new Class[1]; + partype[0] = arg.getClass(); + Method m; + try { + m = this.getClass().getMethod(name, partype); + if (dl != null) { + dl.append(this, m, arg); + } else { + m.invoke(this, new Object[] { arg }); + } + } catch (Throwable e) { + e.printStackTrace(); + } + + } + + /** + * Calls a method with given name + * + * @param name + * name of a method to be called + */ + private void thread2(String name) { + // DONE + try { + Method m = this.getClass().getMethod(name, (Class[]) null); + if (dl != null) { + dl.append(this, m, null); + } else { + m.invoke(this, (Object[]) null); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + /** + * Begins a NURBS curve + * + * @param o_curve + * curve object + */ + public void do_bgncurve(O_curve o_curve) { + if (inCurve > 0) { + do_nurbserror(6); + endcurve(); + } + inCurve = 1; + currentCurve = o_curve; + + currentCurve.curvetype = CT_NONE; + + if (inTrim) { + if (!nextCurve.equals(o_curve)) { + isCurveModified = 1; + nextCurve = o_curve; + } + } else { + if (!playBack) + bgnrender(); + isDataValid = 1; + } + nextCurve = o_curve.next; + // kind of solution of union + nextPwlcurve = o_curve.o_pwlcurve; + nextNurbscurve = o_curve.o_nurbscurve; + } + + /** + * Begins new surface + * + * @param o_surface + * surface object + */ + public void do_bgnsurface(O_surface o_surface) { + // DONE + if (inSurface > 0) { + do_nurbserror(27); + endsurface(); + } + inSurface = 1; + if (!playBack) + bgnrender(); + + isTrimModified = false; + isDataSurfaceModified = false; + isDataValid = 1; + numTrims = 0; + currentSurface = o_surface; + nextTrim = o_surface.o_trim; + nextNurbssurface = o_surface.o_nurbssurface; + } + + /** + * End a curve + */ + public void endcurve() { + // DONE + thread2("do_endcurve"); + } + + /** + * Ends surface + */ + public void do_endsurface() { + // DONE + if (inTrim) { + do_nurbserror(12); + endtrim(); + } + + if (inSurface <= 0) { + do_nurbserror(13); + return; + } + + inSurface = 0; + + nextNurbssurface = null; + + if (isDataValid <= 0) { + return; + } + + if (nextTrim != null) { + isTrimModified = true; + nextTrim = null; + } + + // TODO errval ?? + if (numTrims > 0) { + // System.out.println("TODO glunurbs.do_endsurface - numtrims > 0"); + } + + subdivider.beginQuilts(new GL2Backend()); + for (O_nurbssurface n = currentSurface.o_nurbssurface; n != null; n = n.next) { + subdivider.addQuilt(n.bezier_patches); + } + subdivider.endQuilts(); + subdivider.drawSurfaces(); + if (!playBack) + endrender(); + + } + + /** + * Ends a curve + */ + public void do_endcurve() { + // DONE + // // System.out.println("do_endcurve"); + if (inCurve <= 0) { + do_nurbserror(7); + return; + } + inCurve = 0; + + nextCurve = null; + + if (currentCurve.curvetype == CT_NURBSCURVE) { + // nextNurbscurve = null; + // currentCurve.o_nurbscurve=null; + } else { + // nextPwlcurve = null; + // currentCurve.o_pwlcurve=null; + } + if (!inTrim) { + if (isDataValid <= 0) { + return; + } + // TODO errval? + if (currentCurve.curvetype == CT_NURBSCURVE) { + subdivider.beginQuilts(new GL2Backend()); + + for (O_nurbscurve n = currentCurve.o_nurbscurve; n != null; n = n.next) + subdivider.addQuilt(n.bezier_curves); + + subdivider.endQuilts(); + subdivider.drawCurves(); + if (!playBack) + endrender(); + } else { + if (!playBack) + endrender(); + do_nurbserror(9); + } + } + + } + + /** + * Method for handling error codes + * + * @param i + * error code + */ + private void do_nurbserror(int i) { + // TODO nurberror + // System.out.println("TODO nurbserror " + i); + } + + /** + * Begin rendering + */ + private void bgnrender() { + // DONE + if (autoloadmode) { + loadGLMatrices(); + } + } + + /** + * Load matrices from OpenGL state machine + */ + private void loadGLMatrices() { + // TODO Auto-generated method stub + // System.out.println("TODO glunurbs.loadGLMatrices"); + } + + /** + * End rendering + */ + private void endrender() { + // DONE + } + + /** + * Make a NURBS curve + * + * @param nknots + * number of knots in knot vector + * @param knot + * knot vector + * @param stride + * number of control points coordinates + * @param ctlarray + * control points + * @param order + * order of the curve + * @param realType + * type of the curve + */ + public void nurbscurve(int nknots, float[] knot, int stride, + float[] ctlarray, int order, int realType) { + // DONE + Mapdesc mapdesc = maplist.locate(realType); + if (mapdesc == null) { + do_nurbserror(35); + isDataValid = 0; + return; + } + if (ctlarray == null) { + do_nurbserror(36); + isDataValid = 0; + return; + } + if (stride < 0) { + do_nurbserror(34); + isDataValid = 0; + return; + } + Knotvector knots = new Knotvector(nknots, stride, order, knot); + + if (!do_check_knots(knots, "curve")) + return; + + O_nurbscurve o_nurbscurve = new O_nurbscurve(realType); + o_nurbscurve.bezier_curves = new Quilt(mapdesc); + CArrayOfFloats ctrlcarr = new CArrayOfFloats(ctlarray); + o_nurbscurve.bezier_curves.toBezier(knots, ctrlcarr, mapdesc + .getNCoords()); + thread("do_nurbscurve", o_nurbscurve); + } + + /** + * Check knot vector specification + * + * @param knots + * knot vector + * @param msg + * error message + * @return knot vector is / is not valid + */ + public boolean do_check_knots(Knotvector knots, String msg) { + // DONE + int status = knots.validate(); + if (status > 0) { + do_nurbserror(status); + if (renderhints.errorchecking != NurbsConsts.N_NOMSG) + knots.show(msg); + } + return (status > 0) ? false : true; + } + + /** + * Draw a curve + * + * @param o_nurbscurve + * NURBS curve object + */ + public void do_nurbscurve(O_nurbscurve o_nurbscurve) { + // DONE + + if (inCurve <= 0) { + bgncurve(); + inCurve = 2; + } + + if (o_nurbscurve.used) { + do_nurbserror(23); + isDataValid = 0; + return; + } else + o_nurbscurve.used = true; + + if (currentCurve.curvetype == CT_NONE) { + currentCurve.curvetype = CT_NURBSCURVE; + } else if (currentCurve.curvetype != CT_NURBSCURVE) { + do_nurbserror(24); + isDataValid = 0; + return; + } + + // it was necessary to overcome problem with pointer to pointer here + + // if(!o_nurbscurve.equals(nextNurbscurve)){ + if (!o_nurbscurve.equals(currentCurve.o_nurbscurve)) { + isCurveModified = 1; + currentCurve.o_nurbscurve = o_nurbscurve; + // nextNurbscurve=o_nurbscurve; + + } + + nextNurbscurve = o_nurbscurve.next; + + if (!currentCurve.equals(o_nurbscurve.owner)) { + isCurveModified = 1; + o_nurbscurve.owner = currentCurve; + } + + if (o_nurbscurve.owner == null) + isCurveModified = 1; + + if (inCurve == 2) + endcurve(); + } + + /** + * Draw NURBS surface + * + * @param o_nurbssurface + * NURBS surface object + */ + public void do_nurbssurface(O_nurbssurface o_nurbssurface) { + // DONE + if (inSurface <= 0) { + bgnsurface(); + inSurface = 2; + } + if (o_nurbssurface.used) { + do_nurbserror(25); + isDataValid = 0; + return; + } else + o_nurbssurface.used = true; + + if (!o_nurbssurface.equals(nextNurbscurve)) { + isSurfaceModified = true; + // nextNurbssurface=o_nurbssurface; + currentSurface.o_nurbssurface = o_nurbssurface; + } + + if (!currentSurface.equals(o_nurbssurface.owner)) { + isSurfaceModified = true; + o_nurbssurface.owner = currentSurface; + } + + nextNurbssurface = o_nurbssurface.next; + + if (inSurface == 2) + endsurface(); + } + + /** + * (Re)Inicialize maps + */ + public void redefineMaps() { + // DONE + maplist.initialize(); + } + + /** + * Define a map of given properties + * + * @param type + * map type + * @param rational + * is rational + * @param ncoords + * number of control point coordinates + */ + public void defineMap(int type, int rational, int ncoords) { + // DONE + maplist.define(type, rational, ncoords); + } + + /** + * Set NURBS property + * + * @param type + * property type + * @param tag + * property tag + * @param value + * property value + */ + public void setnurbsproperty(int type, int tag, float value) { + // DONE + Mapdesc mapdesc = maplist.locate(type); + if (mapdesc == null) { + do_nurbserror(35); + return; + } + if (!mapdesc.isProperty(tag)) { + do_nurbserror(26); + return; + } + Property prop = new Property(type, tag, value); + thread("do_setnurbsproperty2", prop); + } + + /** + * Set parameters of existing property + * + * @param prop + * property + */ + public void do_setnurbsproperty2(Property prop) { + Mapdesc mapdesc = maplist.find(prop.type); + mapdesc.setProperty(prop.tag, prop.value); + } + + /** + * Set given property to rendering hints + * + * @param prop + * property to be set + */ + public void do_setnurbsproperty(Property prop) { + // DONE + renderhints.setProperty(prop); + // TODO freeproperty? + } + + /** + * Sets wheteher we use domain distance sampling + * + * @param i + * domain distance sampling flag + */ + public void set_is_domain_distance_sampling(int i) { + // DONE + subdivider.set_is_domain_distance_sampling(i); + } + + /** + * Begin new surface + */ + public void bgnsurface() { + // DONE + O_surface o_surface = new O_surface(); + // TODO nuid + // System.out.println("TODO glunurbs.bgnsurface nuid"); + thread("do_bgnsurface", o_surface); + } + + /** + * End current surface + */ + public void endsurface() { + // DONE + thread2("do_endsurface"); + } + + /** + * End surface trimming + */ + private void endtrim() { + // TODO Auto-generated method stub + // System.out.println("TODO glunurbs.endtrim"); + } + + /** + * Make NURBS surface + * + * @param sknot_count + * number of knots in s direction + * @param sknot + * knot vector in s direction + * @param tknot_count + * number of knots in t direction + * @param tknot + * knot vector in t direction + * @param s_stride + * number of coords of control points in s direction + * @param t_stride + * number of coords of control points in t direction + * @param ctlarray + * control points + * @param sorder + * order of curve in s direction + * @param torder + * order of curve in t direction + * @param type + * NURBS surface type (rational,...) + */ + public void nurbssurface(int sknot_count, float[] sknot, int tknot_count, + float[] tknot, int s_stride, int t_stride, float[] ctlarray, + int sorder, int torder, int type) { + // DONE + Mapdesc mapdesc = maplist.locate(type); + if (mapdesc == null) { + do_nurbserror(35); + isDataValid = 0; + return; + } + if (s_stride < 0 || t_stride < 0) { + do_nurbserror(34); + isDataValid = 0; + return; + } + Knotvector sknotvector = new Knotvector(sknot_count, s_stride, sorder, + sknot); + if (!do_check_knots(sknotvector, "surface")) + return; + Knotvector tknotvector = new Knotvector(tknot_count, t_stride, torder, + tknot); + if (!do_check_knots(tknotvector, "surface")) + return; + + O_nurbssurface o_nurbssurface = new O_nurbssurface(type); + o_nurbssurface.bezier_patches = new Quilt(mapdesc); + + CArrayOfFloats ctrlarr = new CArrayOfFloats(ctlarray); + o_nurbssurface.bezier_patches.toBezier(sknotvector, tknotvector, + ctrlarr, mapdesc.getNCoords()); + thread("do_nurbssurface", o_nurbssurface); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/BuildMipmap.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/BuildMipmap.java new file mode 100644 index 000000000..501f5f585 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/BuildMipmap.java @@ -0,0 +1,1598 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLU; +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.impl.InternalBufferUtil; +import java.nio.*; +import java.io.*; + +/** + * + * @author Administrator + */ +public class BuildMipmap { + + private static final boolean DEBUG = Debug.debug("BuildMipmap"); + private static final boolean VERBOSE = Debug.verbose(); + + /** Creates a new instance of BuildMipmap */ + public BuildMipmap() { + } + + public static int gluBuild1DMipmapLevelsCore( GL gl, int target, int internalFormat, + int width, int widthPowerOf2, int format, int type, int userLevel, + int baseLevel, int maxLevel, ByteBuffer data ) { + int newwidth; + int level, levels; + ShortBuffer newImage = null; + int newImage_width; + ShortBuffer otherImage = null; + ShortBuffer imageTemp = null; + int memReq; + int maxsize; + int cmpts; + PixelStorageModes psm = new PixelStorageModes(); + + assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 ); + assert( width >= 1 ); + + newwidth = widthPowerOf2; + levels = Mipmap.computeLog( newwidth ); + + levels += userLevel; + + Mipmap.retrieveStoreModes( gl, psm ); + try { + newImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.image_size( width, 1, format, + GL2.GL_UNSIGNED_SHORT ) )).asShortBuffer(); + } catch( OutOfMemoryError ome ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + newImage_width = width; + + Image.fill_image( psm, width, 1, format, type, Mipmap.is_index( format ), data, newImage ); + cmpts = Mipmap.elements_per_group( format, type ); + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 2 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + + // if swap_bytes was set, swapping occurred in fill_image + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + + for( level = userLevel; level <= levels; level++ ) { + if( newImage_width == newwidth ) { + // user newimage for this level + if( baseLevel <= level && level <= maxLevel ) { + gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0, format, + GL2.GL_UNSIGNED_SHORT, newImage ); + } + } else { + if( otherImage == null ) { + memReq = Mipmap.image_size( newwidth, 1, format, GL2.GL_UNSIGNED_SHORT ); + try { + otherImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )).asShortBuffer(); + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + ScaleInternal.scale_internal( cmpts, newImage_width, 1, newImage, newwidth, 1, otherImage ); + // swap newImage and otherImage + imageTemp = otherImage; + otherImage = newImage; + newImage = imageTemp; + + newImage_width = newwidth; + if( baseLevel <= level && level <= maxLevel ) { + gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0, + format, GL2.GL_UNSIGNED_SHORT, newImage ); + } + } + if( newwidth > 1 ) { + newwidth /= 2; + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + + return( 0 ); + } + + public static int bitmapBuild2DMipmaps( GL gl, int target, int internalFormat, + int width, int height, int format, int type, ByteBuffer data ) { + int newwidth[] = new int[1]; + int newheight[] = new int[1]; + int level, levels; + ShortBuffer newImage = null; + int newImage_width; + int newImage_height; + ShortBuffer otherImage = null; + ShortBuffer tempImage = null; + int memReq; + int maxsize; + int cmpts; + PixelStorageModes psm = new PixelStorageModes(); + + Mipmap.retrieveStoreModes( gl, psm ); + + Mipmap.closestFit( gl, target, width, height, internalFormat, format, type, newwidth, newheight ); + + levels = Mipmap.computeLog( newwidth[0] ); + level = Mipmap.computeLog( newheight[0] ); + if( level > levels ) { + levels = level; + } + + try { + newImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.image_size( width, height, + format, GL2.GL_UNSIGNED_SHORT ) )).asShortBuffer(); + } catch( OutOfMemoryError ome ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + newImage_width = width; + newImage_height = height; + + Image.fill_image( psm, width, height, format, type, Mipmap.is_index( format ), data, newImage ); + + cmpts = Mipmap.elements_per_group( format, type ); + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 2 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + + // if swap_bytes is set, swapping occurred in fill_image + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + + for( level = 0; level < levels; level++ ) { + if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) { + newImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newImage_width, + newImage_height, 0, format, GL2.GL_UNSIGNED_SHORT, newImage ); + } else { + if( otherImage == null ) { + memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL2.GL_UNSIGNED_SHORT ); + try { + otherImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )).asShortBuffer(); + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + ScaleInternal.scale_internal( cmpts, newImage_width, newImage_height, + newImage, newwidth[0], newheight[0], otherImage ); + // swap newImage and otherImage + tempImage = otherImage; + otherImage = newImage; + newImage = tempImage; + + newImage_width = newwidth[0]; + newImage_height = newheight[0]; + newImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newImage_width, newImage_height, + 0, format, GL2.GL_UNSIGNED_SHORT, newImage ); + } + if( newheight[0] > 1 ) { + newwidth[0] /= 2; + } + if( newheight[0] > 1 ) { + newheight[0] /= 2; + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + + return( 0 ); + } + + public static int gluBuild2DMipmapLevelsCore( GL gl, int target, int internalFormat, + int width, int height, int widthPowerOf2, int heightPowerOf2, + int format, int type, int userLevel, int baseLevel, int maxLevel, + ByteBuffer data ) { // PointerWrapper data + int newwidth; + int newheight; + int level, levels; + int usersImage; + ByteBuffer srcImage = null; + ByteBuffer dstImage = null; + ByteBuffer tempImage = null; + int newImage_width; + int newImage_height; + short[] SWAP_IMAGE = null; + int memReq; + int maxsize; + int cmpts; + int mark=-1; + + boolean myswap_bytes; + int groups_per_line, element_size, group_size; + int rowsize, padding; + PixelStorageModes psm = new PixelStorageModes(); + + assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 ); + assert( width >= 1 && height >= 1 ); + + if( type == GL2.GL_BITMAP ) { + return( bitmapBuild2DMipmaps( gl, target, internalFormat, width, height, format, type, data ) ); + } + + newwidth = widthPowerOf2; + newheight = heightPowerOf2; + levels = Mipmap.computeLog( newwidth ); + level = Mipmap.computeLog( newheight ); + if( level > levels ) { + levels = level; + } + + levels += userLevel; + + Mipmap.retrieveStoreModes( gl, psm ); + myswap_bytes = psm.getUnpackSwapBytes(); + cmpts = Mipmap.elements_per_group( format, type ); + if( psm.getUnpackRowLength() > 0 ) { + groups_per_line = psm.getUnpackRowLength(); + } else { + groups_per_line = width; + } + + element_size = Mipmap.bytes_per_element( type ); + group_size = element_size * cmpts; + if( element_size == 1 ) { + myswap_bytes = false; + } + + rowsize = groups_per_line * group_size; + padding = ( rowsize % psm.getUnpackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getUnpackAlignment() - padding; + } + + mark = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size; + data.position( mark ); + + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + + level = userLevel; + + // already power of two square + if( width == newwidth && height == newheight ) { + // use usersImage for level userLevel + if( baseLevel <= level && level <= maxLevel ) { + data.rewind(); + gl.glTexImage2D( target, level, internalFormat, width, height, 0, format, type, data ); + } + if( levels == 0 ) { /* we're done. clean up and return */ + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( 0 ); + } + int nextWidth = newwidth / 2; + int nextHeight = newheight / 2; + + // clamp to 1 + if( nextWidth < 1 ) { + nextWidth = 1; + } + if( nextHeight < 1 ) { + nextHeight = 1; + } + memReq = Mipmap.image_size( nextWidth, nextHeight, format, type ); + + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + if( dstImage != null ) { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + HalveImage.halveImage_ubyte( cmpts, width, height, data, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_BYTE ): + HalveImage.halveImage_byte( cmpts, width, height, data, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_UNSIGNED_SHORT ): + HalveImage.halveImage_ushort( cmpts, width, height, data, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_SHORT ): + HalveImage.halveImage_short( cmpts, width, height, data, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT ): + HalveImage.halveImage_uint( cmpts, width, height, data, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_INT ): + HalveImage.halveImage_int( cmpts, width, height, data, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_FLOAT ): + HalveImage.halveImage_float( cmpts, width, height, data, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel( 3, new Extract332(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel( 3, new Extract233rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + HalveImage.halveImagePackedPixel( 3, new Extract565(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + HalveImage.halveImagePackedPixel( 3, new Extract565rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + HalveImage.halveImagePackedPixel( 4, new Extract4444(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract4444rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + HalveImage.halveImagePackedPixel( 4, new Extract5551(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract1555rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + HalveImage.halveImagePackedPixel( 4, new Extract8888(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract8888rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + HalveImage.halveImagePackedPixel( 4, new Extract1010102(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract2101010rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + default: + assert( false ); + break; + } + } + newwidth = width / 2; + newheight = height / 2; + // clamp to 1 + if( newwidth < 1 ) { + newwidth = 1; + } + if( newheight < 1 ) { + newheight = 1; + } + + myswap_bytes = false; + rowsize = newwidth * group_size; + memReq = Mipmap.image_size( newwidth, newheight, format, type ); + // swap srcImage and dstImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + // level userLevel+1 is in srcImage; level userLevel already saved + level = userLevel + 1; + } else { // user's image is not nice powerof2 size square + memReq = Mipmap.image_size( newwidth, newheight, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + data.position( mark ); + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + ScaleInternal.scale_internal_ubyte( cmpts, width, height, data, + newwidth, newheight, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_BYTE ): + ScaleInternal.scale_internal_byte( cmpts, width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_UNSIGNED_SHORT ): + ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth, + newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_SHORT ): + ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth, + newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT ): + ScaleInternal.scale_internal_uint( cmpts, width, height, data, newwidth, + newheight, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_INT ): + ScaleInternal.scale_internal_int( cmpts, width, height, data, newwidth, + newheight, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_FLOAT ): + ScaleInternal.scale_internal_float( cmpts, width, height, data, newwidth, + newheight, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + ScaleInternal.scaleInternalPackedPixel( 3, new Extract332(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + ScaleInternal.scaleInternalPackedPixel( 3, new Extract233rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + ScaleInternal.scaleInternalPackedPixel( 3, new Extract565(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + ScaleInternal.scaleInternalPackedPixel( 3, new Extract565rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract4444(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract4444rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract5551(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract1555rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract8888(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract8888rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract1010102(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract2101010rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + default: + assert( false ); + break; + } + myswap_bytes = false; + rowsize = newwidth * group_size; + // swap dstImage and srcImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + + if( levels != 0 ) { // use as little memory as possible + int nextWidth = newwidth / 2; + int nextHeight = newheight / 2; + if( nextWidth < 1 ) { + nextWidth = 1; + } + if( nextHeight < 1 ) { + nextHeight = 1; + } + + memReq = Mipmap.image_size( nextWidth, nextHeight, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + // level userLevel is in srcImage; nothing saved yet + level = userLevel; + } + + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + if( baseLevel <= level && level <= maxLevel ) { + srcImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage ); + if (DEBUG) { + System.err.println("GL Error(" + level + "): " + gl.glGetError() ); + if (VERBOSE) { + srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) ); + writeTargaFile("glu2DMipmapJ" + level + ".tga", + srcImage, newwidth, newheight); + srcImage.clear(); + } + } + } + + level++; // update current level for the loop + for( ; level <= levels; level++ ) { + srcImage.rewind(); + dstImage.rewind(); + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + HalveImage.halveImage_ubyte( cmpts, newwidth, newheight, srcImage, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_BYTE ): + HalveImage.halveImage_byte( cmpts, newwidth, newheight, srcImage, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_UNSIGNED_SHORT ): + HalveImage.halveImage_ushort( cmpts, newwidth, newheight, srcImage, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_SHORT ): + HalveImage.halveImage_short( cmpts, newwidth, newheight, srcImage, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT ): + HalveImage.halveImage_uint( cmpts, newwidth, newheight, srcImage, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_INT ): + HalveImage.halveImage_int( cmpts, newwidth, newheight, srcImage, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_FLOAT ): + HalveImage.halveImage_float( cmpts, newwidth, newheight, srcImage, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel( 3, new Extract332(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel( 3, new Extract233rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + HalveImage.halveImagePackedPixel( 3, new Extract565(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + HalveImage.halveImagePackedPixel( 3, new Extract565rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + HalveImage.halveImagePackedPixel( 4, new Extract4444(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract4444rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + HalveImage.halveImagePackedPixel( 4, new Extract5551(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract1555rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + HalveImage.halveImagePackedPixel( 4, new Extract8888(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract8888rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + HalveImage.halveImagePackedPixel( 4, new Extract1010102(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract2101010rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + default: + assert( false ); + break; + } + + // swap dstImage and srcImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + + if( newwidth > 1 ) { + newwidth /= 2; + rowsize /= 2; + } + if( newheight > 1 ) { + newheight /= 2; + } + // compute amount to pad per row if any + int rowPad = rowsize % psm.getUnpackAlignment(); + + // should row be padded + if( rowPad == 0 ) { + // call teximage with srcImage untouched since its not padded + if( baseLevel <= level && level <= maxLevel ) { + srcImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage ); + if (DEBUG) { + System.err.println("GL Error(" + level + "): " + gl.glGetError() ); + if (VERBOSE) { + srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) ); + writeTargaFile("glu2DMipmapJ" + level + ".tga", + srcImage, newwidth, newheight); + srcImage.clear(); + } + } + } + } else { + // compute length of new row in bytes, including padding + int newRowLength = rowsize + psm.getUnpackAlignment() - rowPad; + int ii, jj; + int dstTrav; + int srcTrav; + + // allocate new image for mipmap of size newRowLength x newheight + ByteBuffer newMipmapImage = null; + try { + newMipmapImage = ByteBuffer.allocateDirect( newRowLength * newheight ); + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + srcImage.rewind(); + // copy image from srcImage into newMipmapImage by rows + for( ii = 0; ii < newheight; ii++ ) { + newMipmapImage.position(newRowLength * ii); + for( jj = 0; jj < rowsize; jj++ ) { + newMipmapImage.put( srcImage.get() ); + } + } + + // and use this new image for mipmapping instead + if( baseLevel <= level && level <= maxLevel ) { + newMipmapImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, newMipmapImage ); + if (DEBUG) { + System.err.println("GL Error(" + level + " padded): " + gl.glGetError() ); + if (VERBOSE) { + writeTargaFile("glu2DMipmapJ" + level + ".tga", + newMipmapImage, newwidth, newheight); + } + } + } + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + + return( 0 ); + } + + public static int fastBuild2DMipmaps( GL gl, PixelStorageModes psm, int target, + int components, int width, int height, int format, int type, ByteBuffer data ) { + int[] newwidth = new int[1]; + int[] newheight = new int[1]; + int level, levels; + ByteBuffer newImage; + int newImage_width; + int newImage_height; + ByteBuffer otherImage; + ByteBuffer imageTemp; + int memReq; + int maxsize; + int cmpts; + + Mipmap.closestFit( gl, target, width, height, components, format, type, newwidth, + newheight ); + + levels = Mipmap.computeLog( newwidth[0] ); + level = Mipmap.computeLog( newheight[0] ); + if( level > levels ) { + levels = level; + } + + cmpts = Mipmap.elements_per_group( format, type ); + + otherImage = null; + // No need to copy the user data if its packed correctly. + // Make sure that later routines don't change that data. + + if( psm.getUnpackSkipRows() == 0 && psm.getUnpackSkipPixels() == 0 ) { + newImage = data; + newImage_width = width; + newImage_height = height; + } else { + int rowsize; + int group_per_line; + int elements_per_line; + int start; + int iter; + int iter2; + int i, j; + + try { + newImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.image_size( + width, height, format, GL2.GL_UNSIGNED_BYTE ) )); + } catch( OutOfMemoryError err ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + newImage_width = width; + newImage_height = height; + + // Abbreviated version of fill_image for the restricted case. + if( psm.getUnpackRowLength() > 0 ) { + group_per_line = psm.getUnpackRowLength(); + } else { + group_per_line = width; + } + rowsize = group_per_line * cmpts; + elements_per_line = width * cmpts; + start = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * cmpts; + + for( i = 0; i < height; i++ ) { + iter = start; + data.position( iter ); + for( j = 0; j < elements_per_line; j++ ) { + newImage.put( data.get() ); + } + start += rowsize; + } + } + + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 1 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + + for( level = 0; level <= levels; level++ ) { + if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) { + // use newImage for this level + newImage.rewind(); + gl.glTexImage2D( target, level, components, newImage_width, newImage_height, + 0, format, GL2.GL_UNSIGNED_BYTE, newImage ); + } else { + if( otherImage == null ) { + memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL2.GL_UNSIGNED_BYTE ); + try { + otherImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ; + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + // swap newImage and otherImage + imageTemp = otherImage; + otherImage = newImage; + newImage = imageTemp; + + newImage_width = newwidth[0]; + newImage_height = newheight[0]; + newImage.rewind(); + gl.glTexImage2D( target, level, components, newImage_width, newImage_height, + 0, format, GL2.GL_UNSIGNED_BYTE, newImage ); + } + if( newwidth[0] > 1 ) { + newwidth[0] /= 2; + } + if( newheight[0] > 1 ) { + newheight[0] /= 2; + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ; + + return( 0 ); + } + + public static int gluBuild3DMipmapLevelsCore( GL gl, int target, int internalFormat, + int width, int height, int depth, int widthPowerOf2, int heightPowerOf2, + int depthPowerOf2, int format, int type, int userLevel, int baseLevel, + int maxLevel, ByteBuffer data ) { + int newWidth; + int newHeight; + int newDepth; + int level, levels; + ByteBuffer usersImage; + ByteBuffer srcImage, dstImage, tempImage; + int newImageWidth; + int newImageHeight; + int newImageDepth; + int memReq; + int maxSize; + int cmpts; + int mark=-1; + + boolean myswapBytes; + int groupsPerLine, elementSize, groupSize; + int rowsPerImage, imageSize; + int rowSize, padding; + PixelStorageModes psm = new PixelStorageModes(); + + assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 ); + assert( width >= 1 && height >= 1 && depth >= 1 ); + assert( type != GL2.GL_BITMAP ); + + srcImage = dstImage = null; + + newWidth = widthPowerOf2; + newHeight = heightPowerOf2; + newDepth = depthPowerOf2; + levels = Mipmap.computeLog( newWidth ); + level = Mipmap.computeLog( newHeight ); + if( level > levels ) { + levels = level; + } + level = Mipmap.computeLog( newDepth ); + if( level > levels ) { + levels = level; + } + + levels += userLevel; + + Mipmap.retrieveStoreModes3D( gl, psm ); + myswapBytes = psm.getUnpackSwapBytes(); + cmpts = Mipmap.elements_per_group( format, type ); + if( psm.getUnpackRowLength() > 0 ) { + groupsPerLine = psm.getUnpackRowLength(); + } else { + groupsPerLine = width; + } + + elementSize = Mipmap.bytes_per_element( type ); + groupSize = elementSize * cmpts; + if( elementSize == 1 ) { + myswapBytes = false; + } + + // 3dstuff + if( psm.getUnpackImageHeight() > 0 ) { + rowsPerImage = psm.getUnpackImageHeight(); + } else { + rowsPerImage = height; + } + + rowSize = groupsPerLine * groupSize; + padding = ( rowSize % psm.getUnpackAlignment() ); + if( padding != 0 ) { + rowSize += psm.getUnpackAlignment() - padding; + } + + imageSize = rowsPerImage * rowSize; + + usersImage = ByteBuffer.wrap(data.array()); + mark = psm.getUnpackSkipRows() * rowSize + + psm.getUnpackSkipPixels() * groupSize + + psm.getUnpackSkipImages() * imageSize; + usersImage.position( mark ); + + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, 0 ); + + level = userLevel; + + if( width == newWidth && height == newHeight && depth == newDepth ) { + // use usersImage for level userlevel + if( baseLevel <= level && level <= maxLevel ) { + gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth, + 0, format, type, usersImage ); + } + if( levels == 0 ) { /* we're done. clean up and return */ + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( 0 ); + } + int nextWidth = newWidth / 2; + int nextHeight = newHeight / 2; + int nextDepth = newDepth / 2; + + // clamp to one + if( nextWidth < 1 ) { + nextWidth = 1; + } + if( nextHeight < 1 ) { + nextHeight = 1; + } + if( nextDepth < 1 ) { + nextDepth = 1; + } + memReq = Mipmap.imageSize3D( nextWidth, nextHeight, nextDepth, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + + if( dstImage != null ) { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUByte(), width, height, depth, + usersImage, dstImage, elementSize, + groupSize, rowSize, imageSize, myswapBytes ); + } else { + HalveImage.halveImage_ubyte( cmpts, width, height, usersImage, + dstImage, elementSize, rowSize, groupSize ); + } + break; + case( GL2.GL_BYTE ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSByte(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_byte( cmpts, width, height, usersImage, + dstImage, elementSize, rowSize, groupSize ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUShort(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_ushort( cmpts, width, height, usersImage, + dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_SHORT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSShort(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_short( cmpts, width, height, usersImage, + dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_UNSIGNED_INT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUInt(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_uint( cmpts, width, height, usersImage, + dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_INT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSInt(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_int( cmpts, width, height, usersImage, + dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_FLOAT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractFloat(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_float( cmpts, width, height, usersImage, + dstImage.asFloatBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel3D( 3, new Extract332(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel3D( 3, new Extract233rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + HalveImage.halveImagePackedPixel3D( 3, new Extract565(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + HalveImage.halveImagePackedPixel3D( 3, new Extract565rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract4444(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract4444rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract5551(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract1555rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract8888(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract8888rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract1010102(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract2101010rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + default: + assert( false ); + break; + } + } + newWidth = width / 2; + newHeight = height / 2; + newDepth = depth / 2; + // clamp to 1 + if( newWidth < 1 ) { + newWidth = 1; + } + if( newHeight < 1 ) { + newHeight = 1; + } + if( newDepth < 1 ) { + newDepth = 1; + } + + myswapBytes = false; + rowSize = newWidth * groupSize; + imageSize = rowSize * newHeight; + memReq = Mipmap.imageSize3D( newWidth, newHeight, newDepth, format, type ); + // swap srcImage and dstImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + + // level userLevel + 1 is in srcImage; level userLevel already saved + level = userLevel + 1; + } else { + memReq = Mipmap.imageSize3D( newWidth, newHeight, newDepth, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + + ScaleInternal.gluScaleImage3D( gl, format, width, height, depth, type, + usersImage, newWidth, newHeight, newDepth, type, dstImage ); + + myswapBytes = false; + rowSize = newWidth * groupSize; + imageSize = rowSize * newHeight; + // swap dstImage and srcImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + + if( levels != 0 ) { + int nextWidth = newWidth / 2; + int nextHeight = newHeight / 2; + int nextDepth = newDepth / 2; + if( nextWidth < 1 ) { + nextWidth = 1; + } + if( nextHeight < 1 ) { + nextHeight = 1; + } + if( nextDepth < 1 ) { + nextDepth = 1; + } + memReq = Mipmap.imageSize3D( nextWidth, nextHeight, nextDepth, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + // level userLevel is in srcImage; nothing saved yet + level = userLevel; + } + + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + if( baseLevel <= level && level <= maxLevel ) { + usersImage.position( mark ); + gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth, + 0, format, type, usersImage ); + } + level++; + for( ; level <= levels; level++ ) { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUByte(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_ubyte( cmpts, width, height, usersImage, + dstImage, elementSize, rowSize, groupSize ); + } + break; + case( GL2.GL_BYTE ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSByte(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_byte( cmpts, width, height, usersImage, + dstImage, elementSize, rowSize, groupSize ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUShort(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_ushort( cmpts, width, height, usersImage, + dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_SHORT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSShort(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_short( cmpts, width, height, usersImage, + dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_UNSIGNED_INT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUInt(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_uint( cmpts, width, height, usersImage, + dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_INT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSInt(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_int( cmpts, width, height, usersImage, + dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_FLOAT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractFloat(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_float( cmpts, width, height, usersImage, + dstImage.asFloatBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + HalveImage.halveImagePackedPixel3D( 3, new Extract332(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + HalveImage.halveImagePackedPixel3D( 3, new Extract233rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + HalveImage.halveImagePackedPixel3D( 3, new Extract565(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + HalveImage.halveImagePackedPixel3D( 3, new Extract565rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract4444(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract4444rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract5551(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract1555rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract8888(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract8888rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract1010102(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract2101010rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + default: + assert( false ); + break; + } + + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + + if( newWidth > 1 ) { + newWidth /= 2; + rowSize /= 2; + } + if( newHeight > 1 ) { + newHeight /= 2; + imageSize = rowSize * newHeight; + } + if( newDepth > 1 ) { + newDepth /= 2; + } + if( baseLevel <= level && level <= maxLevel ) { + usersImage.position( mark ); + gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth, + 0, format, type, usersImage ); + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( 0 ); + } + + private static final int TARGA_HEADER_SIZE = 18; + private static void writeTargaFile(String filename, ByteBuffer data, + int width, int height) { + try { + FileOutputStream fos = new FileOutputStream(new File(filename)); + ByteBuffer header = ByteBuffer.allocateDirect(TARGA_HEADER_SIZE); + header.put(0, (byte) 0).put(1, (byte) 0); + header.put(2, (byte) 2); // uncompressed type + header.put(12, (byte) (width & 0xFF)); // width + header.put(13, (byte) (width >> 8)); // width + header.put(14, (byte) (height & 0xFF)); // height + header.put(15, (byte) (height >> 8)); // height + header.put(16, (byte) 24); // pixel size + fos.write(header.array()); + fos.write(data.array()); + data.clear(); + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract.java new file mode 100644 index 000000000..be86585e7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract.java @@ -0,0 +1,56 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public interface Extract { + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ); + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1010102.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1010102.java new file mode 100644 index 000000000..7e172b1ce --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1010102.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract1010102 implements Extract { + + /** Creates a new instance of Extract1010102 */ + public Extract1010102() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + long uint = 0; + + if( isSwap ) { + uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() ); + } else { + uint = 0x00000000FFFFFFFF & packedPixel.getInt(); + } + + // 11111111,11000000,00000000,00000000 == 0xFFC00000 + // 00000000,00111111,11110000,00000000 == 0x003F0000 + // 00000000,00000000,00001111,11111100 == 0x00000FFC + // 00000000,00000000,00000000,00000011 == 0x00000003 + + extractComponents[0] = (float)( ( uint & 0xFFC00000 ) >> 22 ) / 1023.0f; + extractComponents[1] = (float)( ( uint & 0x003FF000 ) >> 12 ) / 1023.0f; + extractComponents[2] = (float)( ( uint & 0x00000FFC ) >> 2 ) / 1023.0f; + extractComponents[3] = (float)( ( uint & 0x00000003 ) ) / 3.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + long uint = (((int)((shoveComponents[0] * 1023) + 0.5f) << 22) & 0xFFC00000 ); + uint |= (((int)((shoveComponents[1] * 1023) + 0.5f) << 12) & 0x003FF000 ); + uint |= (((int)((shoveComponents[2] * 1023) + 0.5f) << 2) & 0x00000FFC ); + uint |= (((int)((shoveComponents[3] * 3) + 0.5f) ) & 0x00000003 ); + packedPixel.asIntBuffer().put( index, (int)uint ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1555rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1555rev.java new file mode 100644 index 000000000..37895096e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1555rev.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract1555rev implements Extract { + + /** Creates a new instance of Extract1555rev */ + public Extract1555rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 00000000,00011111 == 0x001F + // 00000011,11100000 == 0x03E0 + // 01111100,00000000 == 0x7C00 + // 10000000,00000000 == 0x8000 + + extractComponents[0] = (float)( ( ushort & 0x001F ) ) / 31.0f; + extractComponents[1] = (float)( ( ushort & 0x003E ) >> 5 ) / 31.0f; + extractComponents[2] = (float)( ( ushort & 0x7C00 ) >> 10) / 31.0f; + extractComponents[3] = (float)( ( ushort & 0x8000 ) >> 15); + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 00000000,00011111 == 0x001F + // 00000011,11100000 == 0x03E0 + // 01111100,00000000 == 0x7C00 + // 10000000,00000000 == 0x8000 + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) ) & 0x0000001F ); + ushort |= (((int)((shoveComponents[1] * 31) + 0.5f) << 5) & 0x000003E0 ); + ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) << 10) & 0x00007C00 ); + ushort |= (((int)((shoveComponents[3]) + 0.5f) << 15) & 0x00008000 ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract2101010rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract2101010rev.java new file mode 100644 index 000000000..077f3037b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract2101010rev.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract2101010rev implements Extract { + + /** Creates a new instance of Extract2101010 */ + public Extract2101010rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + long uint = 0; + + if( isSwap ) { + uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() ); + } else { + uint = 0x00000000FFFFFFFF & packedPixel.getInt(); + } + + // 11111111,11000000,00000000,00000000 == 0xFFC00000 + // 00000000,00111111,11110000,00000000 == 0x003F0000 + // 00000000,00000000,00001111,11111100 == 0x00000FFC + // 00000000,00000000,00000000,00000011 == 0x00000003 + + extractComponents[0] = (float)( ( uint & 0x000003FF ) ) / 1023.0f; + extractComponents[1] = (float)( ( uint & 0x000FFC00 ) >> 10 ) / 1023.0f; + extractComponents[2] = (float)( ( uint & 0x3FF00000 ) >> 20 ) / 1023.0f; + extractComponents[3] = (float)( ( uint & 0xC0000000 ) >> 30 ) / 3.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + long uint = (((int)((shoveComponents[0] * 1023) + 0.5f) ) & 0x000003FF ); + uint |= (((int)((shoveComponents[1] * 1023) + 0.5f) << 10) & 0x000FFC00 ); + uint |= (((int)((shoveComponents[2] * 1023) + 0.5f) << 20) & 0x3FF00000 ); + uint |= (((int)((shoveComponents[3] * 3) + 0.5f) << 30) & 0xC0000000 ); + packedPixel.asIntBuffer().put( index, (int)uint ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract233rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract233rev.java new file mode 100644 index 000000000..fa35c6fbc --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract233rev.java @@ -0,0 +1,85 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract233rev implements Extract { + + /** Creates a new instance of Extract223rev */ + public Extract233rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + // 11100000 == 0xe0 + // 00011100 == 0x1c + // 00000011 == 0x03 + byte ubyte = packedPixel.get(); + extractComponents[0] = (float)((ubyte & 0x07) ) / 7.0f; + extractComponents[1] = (float)((ubyte & 0x38) >> 3) / 7.0f; + extractComponents[2] = (float)((ubyte & 0xC0) >> 6) / 3.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11100000 == 0xE0 + // 00011100 == 0x1C + // 00000011 == 0x03 + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + byte b = (byte)( ( (int)( ( shoveComponents[0] * 7 ) + 0.5f ) ) & 0x07 ); + b |= (byte)( ( (int)( ( shoveComponents[1] * 7 ) + 0.5f ) << 3 ) & 0x38 ); + b |= (byte)( ( (int)( ( shoveComponents[2] * 3 ) + 0.5f ) << 6 ) & 0xC0 ); + packedPixel.position( index ); + packedPixel.put( b ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract332.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract332.java new file mode 100644 index 000000000..35936466c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract332.java @@ -0,0 +1,84 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract332 implements Extract { + + /** Creates a new instance of Extract332 */ + public Extract332() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + // 11100000 == 0xe0 + // 00011100 == 0x1c + // 00000011 == 0x03 + byte ubyte = packedPixel.get(); + extractComponents[0] = (float)((ubyte & 0xe0) >> 5) / 7.0f; + extractComponents[1] = (float)((ubyte & 0x1c) >> 2) / 7.0f; + extractComponents[2] = (float)((ubyte & 0x03)) / 3.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11100000 == 0xE0 + // 00011100 == 0x1C + // 00000011 == 0x03 + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + byte b = (byte)( ( (int)( ( shoveComponents[0] * 7 ) + 0.5f ) << 5 ) & 0xE0 ); + b |= (byte)( ( (int)( ( shoveComponents[1] * 7 ) + 0.5f ) << 2 ) & 0x1C ); + b |= (byte)( ( (int)( ( shoveComponents[2] * 3 ) + 0.5f ) ) & 0x03 ); + packedPixel.put( index, b ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444.java new file mode 100644 index 000000000..bac4f57aa --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444.java @@ -0,0 +1,96 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract4444 implements Extract { + + /** Creates a new instance of Extract4444 */ + public Extract4444() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + extractComponents[0] = (float)( ( ushort & 0xF000 ) >> 12 ) / 15.0f; + extractComponents[1] = (float)( ( ushort & 0x0F00 ) >> 8 ) / 15.0f; + extractComponents[2] = (float)( ( ushort & 0x00F0 ) >> 4 ) / 15.0f; + extractComponents[3] = (float)( ( ushort & 0x000F ) ) / 15.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 15) + 0.5f) << 12) & 0x0000F000 ); + ushort |= (((int)((shoveComponents[1] * 15) + 0.5f) << 8) & 0x00000F00 ); + ushort |= (((int)((shoveComponents[2] * 15) + 0.5f) << 4) & 0x000000F0 ); + ushort |= (((int)((shoveComponents[3] * 15) + 0.5f) ) & 0x0000000F ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444rev.java new file mode 100644 index 000000000..b1bea75e1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444rev.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract4444rev implements Extract { + + /** Creates a new instance of Extract4444rev */ + public Extract4444rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 00000000,00001111 == 0x000F + // 00000000,11110000 == 0x00F0 + // 00001111,00000000 == 0x0F00 + // 11110000,00000000 == 0xF000 + + extractComponents[0] = (float)( ( ushort & 0x000F ) ) / 15.0f; + extractComponents[1] = (float)( ( ushort & 0x00F0 ) >> 4 ) / 15.0f; + extractComponents[2] = (float)( ( ushort & 0x0F00 ) >> 8 ) / 15.0f; + extractComponents[3] = (float)( ( ushort & 0xF000 ) >> 12 ) / 15.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 15) + 0.5f) ) & 0x0000000F ); + ushort |= (((int)((shoveComponents[1] * 15) + 0.5f) << 4) & 0x000000F0 ); + ushort |= (((int)((shoveComponents[2] * 15) + 0.5f) << 8) & 0x00000F00 ); + ushort |= (((int)((shoveComponents[3] * 15) + 0.5f) << 12) & 0x0000F000 ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract5551.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract5551.java new file mode 100644 index 000000000..a6247844f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract5551.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract5551 implements Extract { + + /** Creates a new instance of Extract5551 */ + public Extract5551() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 11111000,00000000 == 0xF800 + // 00000111,11000000 == 0x07C0 + // 00000000,00111110 == 0x003E + // 00000000,00000001 == 0x0001 + + extractComponents[0] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f; + extractComponents[1] = (float)( ( ushort & 0x00F0 ) >> 6 ) / 31.0f; + extractComponents[2] = (float)( ( ushort & 0x0F00 ) >> 1 ) / 31.0f; + extractComponents[3] = (float)( ( ushort & 0xF000 ) ); + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) << 11) & 0x0000F800 ); + ushort |= (((int)((shoveComponents[1] * 31) + 0.5f) << 6) & 0x000007C0 ); + ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) << 1) & 0x0000003E ); + ushort |= (((int)((shoveComponents[3]) + 0.5f)) & 0x00000001 ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565.java new file mode 100644 index 000000000..624a4f3f2 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565.java @@ -0,0 +1,92 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract565 implements Extract { + + /** Creates a new instance of Extract565 */ + public Extract565() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 11111000,00000000 == 0xF800 + // 00000111,11100000 == 0x07E0 + // 00000000,00111111 == 0x001F + + extractComponents[0] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f; + extractComponents[1] = (float)( ( ushort & 0x07E0 ) >> 5 ) / 63.0f; + extractComponents[2] = (float)( ( ushort & 0x001F ) ) / 31.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11111000,00000000 == 0xF800 + // 00000111,11100000 == 0x07E0 + // 00000000,00111111 == 0x001F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) << 11) & 0x0000F800 ); + ushort |= (((int)((shoveComponents[1] * 63) + 0.5f) << 5) & 0x000007E0 ); + ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) ) & 0x0000001F ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565rev.java new file mode 100644 index 000000000..4ab6d7e98 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565rev.java @@ -0,0 +1,92 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract565rev implements Extract { + + /** Creates a new instance of Extract565rev */ + public Extract565rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 00000000,00011111 == 0x001F + // 00000111,11100000 == 0x07E0 + // 11111000,00000000 == 0xF800 + + extractComponents[0] = (float)( ( ushort & 0x001F ) ) / 31.0f; + extractComponents[1] = (float)( ( ushort & 0x07E0 ) >> 5 ) / 63.0f; + extractComponents[2] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 00000000,00111111 == 0x001F + // 00000111,11100000 == 0x07E0 + // 11111000,00000000 == 0xF800 + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) ) & 0x0000001F ); + ushort |= (((int)((shoveComponents[1] * 63) + 0.5f) << 5) & 0x000007E0 ); + ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) << 11) & 0x0000F800 ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888.java new file mode 100644 index 000000000..90d7e57c9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract8888 implements Extract { + + /** Creates a new instance of Extract8888 */ + public Extract8888() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + long uint = 0; + + if( isSwap ) { + uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() ); + } else { + uint = 0x00000000FFFFFFFF & packedPixel.getInt(); + } + + // 11111000,00000000 == 0xF800 + // 00000111,11000000 == 0x07C0 + // 00000000,00111110 == 0x003E + // 00000000,00000001 == 0x0001 + + extractComponents[0] = (float)( ( uint & 0xFF000000 ) >> 24 ) / 255.0f; + extractComponents[1] = (float)( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f; + extractComponents[2] = (float)( ( uint & 0x0000FF00 ) >> 8 ) / 255.0f; + extractComponents[3] = (float)( ( uint & 0x000000FF ) ) / 255.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + long uint = (((int)((shoveComponents[0] * 255) + 0.5f) << 24) & 0xFF000000 ); + uint |= (((int)((shoveComponents[1] * 255) + 0.5f) << 16) & 0x00FF0000 ); + uint |= (((int)((shoveComponents[2] * 255) + 0.5f) << 8) & 0x0000FF00 ); + uint |= (((int)((shoveComponents[3] * 255) + 0.5f) ) & 0x000000FF ); + packedPixel.asIntBuffer().put( index, (int)uint ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888rev.java new file mode 100644 index 000000000..10970573b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888rev.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract8888rev implements Extract { + + /** Creates a new instance of Extract8888rev */ + public Extract8888rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + long uint = 0; + + if( isSwap ) { + uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() ); + } else { + uint = 0x00000000FFFFFFFF & packedPixel.getInt(); + } + + // 11111000,00000000 == 0xF800 + // 00000111,11000000 == 0x07C0 + // 00000000,00111110 == 0x003E + // 00000000,00000001 == 0x0001 + + extractComponents[0] = (float)( ( uint & 0x000000FF ) ) / 255.0f; + extractComponents[1] = (float)( ( uint & 0x0000FF00 ) >> 8 ) / 255.0f; + extractComponents[2] = (float)( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f; + extractComponents[3] = (float)( ( uint & 0xFF000000 ) >> 24 ) / 255.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + long uint = (((int)((shoveComponents[0] * 255) + 0.5f) ) & 0x000000FF ); + uint |= (((int)((shoveComponents[1] * 255) + 0.5f) << 8) & 0x0000FF00 ); + uint |= (((int)((shoveComponents[2] * 255) + 0.5f) << 16) & 0x00FF0000 ); + uint |= (((int)((shoveComponents[3] * 255) + 0.5f) << 24) & 0xFF000000 ); + packedPixel.asIntBuffer().put( index, (int)uint ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractFloat.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractFloat.java new file mode 100644 index 000000000..c42799470 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractFloat.java @@ -0,0 +1,74 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractFloat implements ExtractPrimitive { + + /** Creates a new instance of ExtractFloat */ + public ExtractFloat() { + } + + public double extract( boolean isSwap, ByteBuffer data ) { + float f = 0; + if( isSwap ) { + f = Mipmap.GLU_SWAP_4_BYTES( data.getInt() ); + } else { + f = data.getInt(); + } + assert( f <= 1.0f ); + return( f ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 1.0); + data.asFloatBuffer().put( index, (float)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractPrimitive.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractPrimitive.java new file mode 100644 index 000000000..8b986d6d0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractPrimitive.java @@ -0,0 +1,56 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public interface ExtractPrimitive { + public double extract( boolean isSwap, ByteBuffer pointer ); + public void shove( double value, int index, ByteBuffer pointer ); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSByte.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSByte.java new file mode 100644 index 000000000..4f61015f4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSByte.java @@ -0,0 +1,69 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class ExtractSByte implements ExtractPrimitive { + + /** Creates a new instance of ExtractUByte */ + public ExtractSByte() { + } + + public double extract( boolean isSwap, ByteBuffer sbyte ) { + byte b = sbyte.get(); + assert( b <= 127 ); + return( b ); + } + + public void shove( double value, int index, ByteBuffer data ) { + data.position( index ); + data.put( (byte)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSInt.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSInt.java new file mode 100644 index 000000000..2d5ac5329 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSInt.java @@ -0,0 +1,76 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractSInt implements ExtractPrimitive { + + /** Creates a new instance of ExtractSInt */ + public ExtractSInt() { + } + + public double extract( boolean isSwap, ByteBuffer uint ) { + int i = 0; + if( isSwap ) { + i = Mipmap.GLU_SWAP_4_BYTES( uint.getInt() ); + } else { + i = uint.getInt(); + } + assert( i <= 0x7FFFFFFF ); + return( i ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < Integer.MAX_VALUE); + IntBuffer ib = data.asIntBuffer(); + ib.position( index ); + ib.put( (int)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSShort.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSShort.java new file mode 100644 index 000000000..8b8d50cbf --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSShort.java @@ -0,0 +1,76 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractSShort implements ExtractPrimitive { + + /** Creates a new instance of ExtractSShort */ + public ExtractSShort() { + } + + public double extract( boolean isSwap, ByteBuffer ushort ) { + short s = 0; + if( isSwap ) { + s = Mipmap.GLU_SWAP_2_BYTES( ushort.getShort() ); + } else { + s = ushort.getShort(); + } + assert( s <= 32767 ); + return( s ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 32768.0); + ShortBuffer sb = data.asShortBuffer(); + sb.position( index ); + sb.put( (short)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUByte.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUByte.java new file mode 100644 index 000000000..d33213f89 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUByte.java @@ -0,0 +1,70 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class ExtractUByte implements ExtractPrimitive { + + /** Creates a new instance of ExtractUByte */ + public ExtractUByte() { + } + + public double extract( boolean isSwap, ByteBuffer ubyte ) { + int i = 0x000000FF & ubyte.get(); + assert( i <= 255 ); + return( i ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 256.0); + data.position( index ); + data.put( (byte)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUInt.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUInt.java new file mode 100644 index 000000000..873668a43 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUInt.java @@ -0,0 +1,76 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractUInt implements ExtractPrimitive { + + /** Creates a new instance of ExtractUInt */ + public ExtractUInt() { + } + + public double extract( boolean isSwap, ByteBuffer uint ) { + long i = 0; + if( isSwap ) { + i = 0xFFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( uint.getInt() ); + } else { + i = 0xFFFFFFFF & uint.getInt(); + } + assert( i <= 0xFFFFFFFF ); + return( i ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 0xFFFFFFFF); + IntBuffer ib = data.asIntBuffer(); + ib.position( index ); + ib.put( (int)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUShort.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUShort.java new file mode 100644 index 000000000..86bbb95f1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUShort.java @@ -0,0 +1,76 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractUShort implements ExtractPrimitive { + + /** Creates a new instance of ExtracUShort */ + public ExtractUShort() { + } + + public double extract( boolean isSwap, ByteBuffer ushort ) { + int i = 0; + if( isSwap ) { + i = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( ushort.getShort() ); + } else { + i = 0x0000FFFF & ushort.getShort(); + } + assert( i <= 65535 ); + return( i ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 65536.0); + ShortBuffer sb = data.asShortBuffer(); + sb.position( index ); + sb.put( (short)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/HalveImage.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/HalveImage.java new file mode 100644 index 000000000..893d33c66 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/HalveImage.java @@ -0,0 +1,1533 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import java.nio.*; + +/** + * + * @author Administrator + */ +public class HalveImage { + + private static final int BOX2 = 2; + private static final int BOX4 = 4; + private static final int BOX8 = 8; + + public static void halveImage( int components, int width, int height, + ShortBuffer datain, ShortBuffer dataout ) { + int i, j, k; + int newwidth, newheight; + int delta; + int t = 0; + short temp = 0; + + newwidth = width / 2; + newheight = height /2; + delta = width * components; + + // Piece of cake + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.get(); + datain.position( t + components ); + temp += datain.get(); + datain.position( t + delta ); + temp += datain.get(); + datain.position( t + delta + components ); + temp +=datain.get(); + temp += 2; + temp /= 4; + dataout.put( temp ); + t++; + } + t += components; + } + t += delta; + } + } + + public static void halveImage_ubyte( int components, int width, int height, + ByteBuffer datain, ByteBuffer dataout, + int element_size, int ysize, int group_size ) { + int i, j, k; + int newwidth, newheight; + int s; + int t; + + // Handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_ubyte( components, width, height, datain, dataout, element_size, ysize, group_size ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + s = 0; + t = 0; + + int temp = 0; + // piece of cake + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = ( 0x000000FF & datain.get() ); + datain.position( t + group_size ); + temp += ( 0x000000FF & datain.get() ); + datain.position( t + ysize ); + temp += ( 0x000000FF & datain.get() ); + datain.position( t + ysize + group_size ); + temp += ( 0x000000FF & datain.get() ) + 2; + dataout.put( (byte)(temp / 4) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + + public static void halve1Dimage_ubyte( int components, int width, int height, + ByteBuffer datain, ByteBuffer dataout, + int element_size, int ysize, int group_size ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + int temp = 0; + + assert( width == 1 || height == 1 ); // Must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // widthxheight can't be 1x1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + datain.position( src ); + temp = ( 0x000000FF & datain.get() ); + datain.position( src + group_size ); + temp += ( 0x000000FF & datain.get() ); + temp /= 2; + dataout.put( (byte)temp ); + /* + dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) + + (0x000000FF & datain.setIndexInBytes( src + group_size ).getByte())) / 2 ) ); + */ + src += element_size; + //dataout.plusPlus(); + dest++; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { // 1 column + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + datain.position( src ); + temp = ( 0x000000FF & datain.get() ); + datain.position( src + ysize ); + temp += ( 0x000000FF & datain.get() ); + temp /= 2; + dataout.put( (byte)temp ); + /* + dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) + + (0x000000FF & datain.setIndexInBytes(src + ysize).getByte()) ) / 2 ) ); + */ + src += element_size; + //dataout.plusPlus(); + dest++; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + } + assert( src == ysize * height ); + assert( dest == components * element_size * halfWidth * halfHeight ); + } + + public static void halveImage_byte( int components, int width, int height, + ByteBuffer datain, ByteBuffer dataout, int element_size, + int ysize, int group_size ) { + int i, j, k; + int newwidth, newheight; + int s = 0; + int t = 0; + byte temp = (byte)0; + + // handle case where there is only 1 column + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); + halve1Dimage_byte( components, width, height, datain, dataout, element_size, + ysize, group_size ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.get(); + datain.position( t + group_size ); + temp += datain.get(); + datain.position( t + ysize ); + temp += datain.get(); + datain.position( t + ysize + group_size ); + temp += datain.get(); + temp += 2; + temp /= 4; + dataout.put( temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + + public static void halve1Dimage_byte( int components, int width, int height, + ByteBuffer datain, ByteBuffer dataout, + int element_size, int ysize, int group_size ) { + int halfWidth = width / 2; + int halfHeight = width / 2; + int src = 0; + int dest = 0; + int jj; + byte temp = (byte)0; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // widthxheight can't be 1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + datain.position( src ); + temp = datain.get(); + datain.position( src + group_size ); + temp += datain.get(); + temp /= 2; + dataout.put( temp ); + src += element_size; + dest++; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assert only + } else if( width == 1 ) { // 1 column + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); // widthxheight can't be 1 + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + datain.position( src ); + temp = datain.get(); + datain.position( src + ysize ); + temp += datain.get(); + temp /= 2; + src += element_size; + dest++; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == components * element_size * halfWidth * halfHeight ); + } + + public static void halveImage_ushort( int components, int width, int height, + ByteBuffer datain, ShortBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + int temp = 0; + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_ushort( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = ( 0x0000FFFF & datain.getShort() ); + datain.position( t + group_size ); + temp += ( 0x0000FFFF & datain.getShort() ); + datain.position( t + ysize ); + temp += ( 0x0000FFFF & datain.getShort() ); + datain.position( t + ysize + group_size ); + temp += ( 0x0000FFFF & datain.getShort() ); + dataout.put( (short)( ( temp + 2 ) / 4 ) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( t + group_size ); + temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( t + ysize ); + temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( t + ysize + group_size ); + temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + dataout.put( (short)( ( temp + 2 ) / 4 ) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_ushort( int components, int width, int height, + ByteBuffer datain, ShortBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // widthxheight can't be 1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < halfHeight; kk++ ) { + int[] ushort = new int[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( src + group_size ); + ushort[1] = (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + } else { + datain.position( src ); + ushort[0] = (0x0000FFFF & datain.getShort() ); + datain.position( src + group_size ); + ushort[1] = (0x0000FFFF & datain.getShort() ); + } + dataout.put( (short)( (ushort[0] + ushort[1]) / 2 ) ); + src += element_size; + dest += 2; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { // 1 column + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); // widthxheight can't be 1 + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + int[] ushort = new int[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( src + ysize ); + ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + } else { + datain.position( src ); + ushort[0] = ( 0x0000FFFF & datain.getShort() ); + datain.position( src + ysize ); + ushort[1] = ( 0x0000FFFF & datain.getShort() ); + } + dataout.put( (short)((ushort[0] + ushort[1]) / 2) ); + src += element_size; + dest += 2; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == components * element_size * halfWidth * halfHeight ); + } + + public static void halveImage_short( int components, int width, int height, + ByteBuffer datain, ShortBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + short temp = (short)0; + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_short( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.getShort(); + datain.position( t + group_size ); + temp += datain.getShort(); + datain.position( t + ysize ); + temp += datain.getShort(); + datain.position( t + ysize + group_size ); + temp += datain.getShort(); + temp += 2; + temp /= 4; + dataout.put( (short)temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + short b; + int buf; + datain.position( t ); + temp = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( t + group_size ); + temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( t + ysize ); + temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( t + ysize + group_size ); + temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + temp += 2; + temp /= 4; + dataout.put( temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_short( int components, int width, int height, + ByteBuffer datain, ShortBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // can't be 1x1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + short[] sshort = new short[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + sshort[0] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( src + group_size ); + sshort[1] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + } else { + datain.position( src ); + sshort[0] = datain.getShort(); + datain.position( src + group_size ); + sshort[1] = datain.getShort(); + } + dataout.put( (short)(( sshort[0] + sshort[1] ) / 2) ); + src += element_size; + dest += 2; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + short[] sshort = new short[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + sshort[0] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( src + ysize ); + sshort[1] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + } else { + datain.position( src ); + sshort[0] = datain.getShort(); + datain.position( src + ysize ); + sshort[1] = datain.getShort(); + } + dataout.put( (short)(( sshort[0] + sshort[1] ) / 2) ); + src += element_size; + dest += 2; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == ( components * element_size * halfWidth * halfHeight ) ); + } + + public static void halveImage_uint( int components, int width, int height, + ByteBuffer datain, IntBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + double temp = 0; + + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_uint( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = (0x000000007FFFFFFFL & datain.getInt() ); + datain.position( t + group_size ); + temp += (0x000000007FFFFFFFL & datain.getInt() ); + datain.position( t + ysize ); + temp += (0x000000007FFFFFFFL & datain.getInt() ); + datain.position( t + ysize + group_size ); + temp += (0x000000007FFFFFFFL & datain.getInt() ); + dataout.put( (int)( ( temp / 4 ) + 0.5 ) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + // need to cast to double to hold large unsigned ints + double buf; + datain.position( t ); + buf = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( t + group_size ); + buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( t + ysize ); + buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( t + ysize + group_size ); + buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + temp /= 4; + temp += 0.5; + dataout.put( (int)temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_uint( int components, int width, int height, + ByteBuffer datain, IntBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // widthxheight can't be 1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < halfHeight; kk++ ) { + long[] uint = new long[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( src + group_size ); + uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + } else { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() ); + datain.position( src + group_size ); + uint[1] = (0x00000000FFFFFFFF & datain.getInt() ); + } + dataout.put( (int)( ( uint[0] + uint[1] ) / 2.0 ) ); + src += element_size; + dest += 4; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { // 1 column + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); // widthxheight can't be 1 + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + long[] uint = new long[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( src + group_size ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + } else { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() ); + datain.position( src + ysize ); + uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() ); + } + dataout.put( (int)( ( uint[0] + uint[1] ) / 2.0 ) ); + src += element_size; + dest += 4; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == components * element_size * halfWidth * halfHeight ); + } + + public static void halveImage_int( int components, int width, int height, + ByteBuffer datain, IntBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + int temp = 0; + + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_int( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.getInt(); + datain.position( t + group_size ); + temp += datain.getInt(); + datain.position( t + ysize ); + temp += datain.getInt(); + datain.position( t + ysize + group_size ); + temp += datain.getInt(); + temp = (int)( ( temp / 4.0f ) + 0.5f ); + dataout.put( temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + long b; + float buf; + datain.position( t ); + b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + buf = b; + datain.position( t + group_size ); + b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + buf += b; + datain.position( t + ysize ); + b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + buf += b; + datain.position( t + ysize + group_size ); + b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + buf += b; + dataout.put( (int)( ( buf / 4.0f ) + 0.5f ) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_int( int components, int width, int height, + ByteBuffer datain, IntBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // can't be 1x1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + long[] uint = new long[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( src + group_size ); + uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + } else { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() ); + datain.position( src + group_size ); + uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() ); + } + dataout.put( (int)( ( (float)uint[0] + (float)uint[1] ) / 2.0f) ); + src += element_size; + dest += 4; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + long[] uint = new long[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( src + ysize ); + uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + } else { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() ); + datain.position( src + ysize ); + uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() ); + } + dataout.put( (int)(( (float)uint[0] + (float)uint[1] ) / 2.0f) ); + src += element_size; + dest += 4; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == ( components * element_size * halfWidth * halfHeight ) ); + } + + public static void halveImage_float( int components, int width, int height, + ByteBuffer datain, FloatBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + float temp = 0.0f; + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_float( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.getFloat(); + datain.position( t + group_size ); + temp += datain.getFloat(); + datain.position( t + ysize ); + temp += datain.getFloat(); + datain.position( t + ysize + group_size ); + temp /= 4.0f; + dataout.put( temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + float buf; + datain.position( t ); + buf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( t + group_size ); + buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( t + ysize ); + buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( t + ysize + group_size ); + buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + dataout.put( buf / 4.0f ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_float( int components, int width, int height, + ByteBuffer datain, FloatBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // can't be 1x1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + float[] sfloat = new float[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + sfloat[0] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( src + group_size ); + sfloat[1] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + } else { + datain.position( src ); + sfloat[0] = datain.getFloat(); + datain.position( src + group_size ); + sfloat[1] = datain.getFloat(); + } + dataout.put( (sfloat[0] + sfloat[1]) / 2.0f ); + src += element_size; + dest += 4; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + float[] sfloat = new float[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + sfloat[0] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( src + ysize ); + sfloat[1] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + } else { + datain.position( src ); + sfloat[0] = datain.getFloat(); + datain.position( src + ysize ); + sfloat[1] = datain.getFloat(); + } + dataout.put( ( sfloat[0] + sfloat[1] ) / 2.0f ); + src += element_size; + dest += 4; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == ( components * element_size * halfWidth * halfHeight ) ); + } + + public static void halveImagePackedPixel( int components, Extract extract, int width, + int height, ByteBuffer datain, ByteBuffer dataout, + int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) { + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); + halve1DimagePackedPixel( components, extract, width, height, datain, dataout, + pixelSizeInBytes, rowSizeInBytes, isSwap ); + return; + } + int ii, jj; + + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes ); + int outIndex = 0; + + for( ii = 0; ii < halfHeight; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + float totals[] = new float[4]; + float extractTotals[][] = new float[BOX4][4]; + int cc; + + datain.position( src ); + extract.extract( isSwap, datain, extractTotals[0] ); + datain.position( src + pixelSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[1] ); + datain.position( src + rowSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[2] ); + datain.position( src + rowSizeInBytes + pixelSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[3] ); + for( cc = 0; cc < components; cc++ ) { + int kk = 0; + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= BOX4; + } + extract.shove( totals, outIndex, dataout ); + outIndex++; + src += pixelSizeInBytes + pixelSizeInBytes; + } + // skip past pad bytes, if any, to get to next row + src += padBytes; + src += rowSizeInBytes; + } + assert( src == rowSizeInBytes * height ); + assert( outIndex == halfWidth * halfHeight ); + } + + public static void halve1DimagePackedPixel( int components, Extract extract, int width, + int height, ByteBuffer datain, ByteBuffer dataout, + int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int jj; + + assert( width == 1 || height == 1 ); + assert( width != height ); + + if( height == 1 ) { + int outIndex = 0; + + assert( width != 1 ); + halfHeight = 1; + + // one horizontal row with possible pad bytes + + for( jj = 0; jj < halfWidth; jj++ ) { + float[] totals = new float[4]; + float[][] extractTotals = new float[BOX2][4]; + int cc; + + datain.position( src ); + extract.extract( isSwap, datain, extractTotals[0] ); + datain.position( src + pixelSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[1] ); + for( cc = 0; cc < components; cc++ ) { + int kk = 0; + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX2; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= BOX2; + } + extract.shove( totals, outIndex, dataout ); + outIndex++; + // skip over to next group of 2 + src += pixelSizeInBytes + pixelSizeInBytes; + } + int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes ); + src += padBytes; + + assert( src == rowSizeInBytes ); + assert( outIndex == halfWidth * halfHeight ); + } else if( width == 1 ) { + int outIndex = 0; + + assert( height != 1 ); + halfWidth = 1; + // one vertical volumn with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + float[] totals = new float[4]; + float[][] extractTotals = new float[BOX2][4]; + int cc; + // average two at a time, instead of four + datain.position( src ); + extract.extract( isSwap, datain, extractTotals[0] ); + datain.position( src + rowSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[1] ); + for( cc = 0; cc < components; cc++ ) { + int kk = 0; + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX2; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= BOX2; + } + extract.shove( totals, outIndex, dataout ); + outIndex++; + // skip over to next group of 2 + src += rowSizeInBytes + rowSizeInBytes; + } + assert( src == rowSizeInBytes ); + assert( outIndex == halfWidth * halfHeight ); + } + } + + public static void halveImagePackedPixelSlice( int components, Extract extract, + int width, int height, int depth, ByteBuffer dataIn, + ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes, + int imageSizeInBytes, boolean isSwap ) { + int ii, jj; + int halfWidth = width / 2; + int halfHeight = height / 2; + int halfDepth = depth / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes ); + int outIndex = 0; + + assert( (width == 1 || height == 1) && depth >= 2 ); + + if( width == height ) { + assert( width == 1 && height == 1 ); + assert( depth >= 2 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + float totals[] = new float[4]; + float extractTotals[][] = new float[BOX2][4]; + int cc; + + dataIn.position( src ); + extract.extract( isSwap, dataIn, extractTotals[0] ); + dataIn.position( src + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[1] ); + + for( cc = 0; cc < components; cc++ ) { + int kk; + + // average only 2 pixels since a column + totals[cc]= 0.0f; + for( kk = 0; kk < BOX2; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= BOX2; + } // for cc + + extract.shove( totals, outIndex, dataOut ); + outIndex++; + // skip over to next group of 2 + src += imageSizeInBytes + imageSizeInBytes; + } // for ii + } else if( height == 1 ) { + assert( width != 1 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + float totals[] = new float[4]; + float extractTotals[][] = new float[BOX4][4]; + int cc; + + dataIn.position( src ); + extract.extract( isSwap, dataIn, extractTotals[0] ); + dataIn.position( src + pixelSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[1] ); + dataIn.position( src + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[2] ); + dataIn.position( src + pixelSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[3] ); + + for( cc = 0; cc < components; cc++ ) { + int kk; + + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc]+= extractTotals[kk][cc]; + } + totals[cc]/= (float)BOX4; + } + extract.shove( totals, outIndex, dataOut ); + outIndex++; + // skip over to next horizontal square of 4 + src += imageSizeInBytes + imageSizeInBytes; + } + } + } else if( width == 1 ) { + assert( height != 1 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + float totals[] = new float[4]; + float extractTotals[][] = new float[BOX4][4]; + int cc; + + dataIn.position( src ); + extract.extract( isSwap, dataIn, extractTotals[0] ); + dataIn.position( src + rowSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[1] ); + dataIn.position( src + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[2] ); + dataIn.position( src + rowSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[3] ); + + for( cc = 0; cc < components; cc++ ) { + int kk; + + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc]+= extractTotals[kk][cc]; + } + totals[cc]/= (float)BOX4; + } + extract.shove( totals, outIndex, dataOut ); + outIndex++; + // skip over to next horizontal square of 4 + src += imageSizeInBytes + imageSizeInBytes; + } + } + } + } + + public static void halveImageSlice( int components, ExtractPrimitive extract, int width, + int height, int depth, ByteBuffer dataIn, ByteBuffer dataOut, + int elementSizeInBytes, int groupSizeInBytes, int rowSizeInBytes, + int imageSizeInBytes, boolean isSwap ) { + int ii, jj; + int halfWidth = width / 2; + int halfHeight = height / 2; + int halfDepth = depth / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * groupSizeInBytes ); + int outIndex = 0; + + assert( (width == 1 || height == 1) && depth >= 2 ); + + if( width == height ) { + assert( width == 1 && height == 1 ); + assert( depth >= 2 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + int cc; + for( cc = 0; cc < components; cc++ ) { + double[] totals = new double[4]; + double[][] extractTotals = new double[BOX2][4]; + int kk; + + dataIn.position( src ); + extractTotals[0][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes ); + extractTotals[1][cc] = extract.extract( isSwap, dataIn ); + + // average 2 pixels since only a column + totals[cc] = 0.0f; + // totals[red] = extractTotals[0][red] + extractTotals[1][red]; + // totals[red] = red / 2; + for( kk = 0; kk < BOX2; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (double)BOX2; + + extract.shove( totals[cc], outIndex, dataOut ); + outIndex++; + src += elementSizeInBytes; + } // for cc + // skip over next group of 2 + src += rowSizeInBytes; + } // for ii + + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfDepth * components ); + } else if( height == 1 ) { + assert( width != 1 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + int cc; + for( cc = 0; cc < components; cc++ ) { + int kk; + double totals[] = new double[4]; + double extractTotals[][] = new double[BOX4][4]; + + dataIn.position( src ); + extractTotals[0][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + groupSizeInBytes ); + extractTotals[1][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes ); + extractTotals[2][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes + groupSizeInBytes ); + extractTotals[3][cc] = extract.extract( isSwap, dataIn ); + + // grab 4 pixels to average + totals[cc] = 0.0f; + // totals[red] = extractTotals[0][red] + extractTotals[1][red] + + // extractTotals[2][red] + extractTotals[3][red]; + // totals[red] /= (double)BOX4; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (double)BOX4; + + extract.shove( totals[cc], outIndex, dataOut ); + outIndex++; + src += elementSizeInBytes; + } // for cc + // skip over to next horizontal square of 4 + src += elementSizeInBytes; + } // for jj + src += padBytes; + src += rowSizeInBytes; + } // for ii + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfWidth * halfDepth * components ); + } else if( width == 1 ) { + assert( height != 1 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + for( jj = 0; jj < halfHeight; jj++ ) { + int cc; + for( cc = 0; cc < components; cc++ ) { + int kk; + double totals[] = new double[4]; + double extractTotals[][] = new double[BOX4][4]; + + dataIn.position( src ); + extractTotals[0][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes ); + extractTotals[1][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes ); + extractTotals[2][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes + groupSizeInBytes ); + extractTotals[3][cc] = extract.extract( isSwap, dataIn ); + + + // grab 4 pixels to average + totals[cc] = 0.0f; + // totals[red] = extractTotals[0][red] + extractTotals[1][red] + + // extractTotals[2][red] + extractTotals[3][red]; + // totals[red] /= (double)BOX4; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (double)BOX4; + + extract.shove( totals[cc], outIndex, dataOut ); + outIndex++; + src += elementSizeInBytes; + } // for cc + // skip over to next horizontal square of 4 + src += padBytes; + src += rowSizeInBytes; + } // for jj + src += imageSizeInBytes; + } // for ii + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfWidth * halfDepth * components ); + } + } + + public static void halveImage3D( int components, ExtractPrimitive extract, + int width, int height, int depth, ByteBuffer dataIn, ByteBuffer dataOut, + int elementSizeInBytes, int groupSizeInBytes, int rowSizeInBytes, + int imageSizeInBytes, boolean isSwap ) { + assert( depth > 1 ); + + // horizontal/vertical/onecolumn slice viewed from top + if( width == 1 || height == 1 ) { + assert( 1 <= depth ); + + halveImageSlice( components, extract, width, height, depth, dataIn, dataOut, + elementSizeInBytes, groupSizeInBytes, rowSizeInBytes, imageSizeInBytes, + isSwap ); + return; + } + + int ii, jj, dd; + + int halfWidth = width / 2; + int halfHeight = height / 2; + int halfDepth = depth / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * groupSizeInBytes ); + int outIndex = 0; + + for( dd = 0; dd < halfDepth; dd++ ) { + for( ii = 0; ii < halfHeight; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + int cc; + for( cc = 0; cc < components; cc++ ) { + int kk; + double totals[] = new double[4]; + double extractTotals[][] = new double[BOX8][4]; + + dataIn.position( src ); + extractTotals[0][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + groupSizeInBytes ); + extractTotals[1][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes ); + extractTotals[2][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes + groupSizeInBytes ); + extractTotals[3][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes ); + extractTotals[4][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + groupSizeInBytes + imageSizeInBytes ); + extractTotals[5][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes + imageSizeInBytes ); + extractTotals[6][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes + imageSizeInBytes + groupSizeInBytes ); + extractTotals[7][cc] = extract.extract( isSwap, dataIn ); + + totals[cc] = 0.0f; + + for( kk = 0; kk < BOX8; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (double)BOX8; + + extract.shove( totals[cc], outIndex, dataOut ); + outIndex++; + + src += elementSizeInBytes; + } // for cc + // skip over to next square of 4 + src += groupSizeInBytes; + } // for jj + // skip past pad bytes, if any, to get to next row + src += padBytes; + src += rowSizeInBytes; + } // for ii + src += imageSizeInBytes; + } // for dd + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfWidth * halfHeight * halfDepth * components ); + } + + public static void halveImagePackedPixel3D( int components, Extract extract, + int width, int height, int depth, ByteBuffer dataIn, + ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes, + int imageSizeInBytes, boolean isSwap ) { + if( depth == 1 ) { + assert( 1 <= width && 1 <= height ); + + halveImagePackedPixel( components, extract, width, height, dataIn, dataOut, + pixelSizeInBytes, rowSizeInBytes, isSwap ); + return; + } else if( width == 1 || height == 1 ) { // a horizontal or vertical slice viewed from top + assert( 1 <= depth ); + + halveImagePackedPixelSlice( components, extract, width, height, depth, dataIn, + dataOut, pixelSizeInBytes, rowSizeInBytes, imageSizeInBytes, isSwap ); + return; + } + int ii, jj, dd; + + int halfWidth = width / 2; + int halfHeight = height / 2; + int halfDepth = depth / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes ); + int outIndex = 0; + + for( dd = 0; dd < halfDepth; dd++ ) { + for( ii = 0; ii < halfHeight; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + float totals[] = new float[4]; // 4 is max components + float extractTotals[][] = new float[BOX8][4]; + int cc; + + dataIn.position( src ); + extract.extract( isSwap, dataIn, extractTotals[0] ); + dataIn.position( src + pixelSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[1] ); + dataIn.position( src + rowSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[2] ); + dataIn.position( src + rowSizeInBytes + pixelSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[3] ); + dataIn.position( src + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[4] ); + dataIn.position( src + pixelSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[5] ); + dataIn.position( src + rowSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[6] ); + dataIn.position( src + rowSizeInBytes + pixelSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[7] ); + + for( cc = 0; cc < components; cc++ ) { + int kk; + // grab 8 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX8; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (float)BOX8; + } + extract.shove( totals, outIndex, dataOut ); + outIndex++; + // skip over to next square of 4 + src += pixelSizeInBytes + pixelSizeInBytes; + } + // skip past pad bytes, if any, to get to next row + src += padBytes; + src += rowSizeInBytes; + } + src += imageSizeInBytes; + } + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfWidth * halfHeight * halfDepth ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Image.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Image.java new file mode 100644 index 000000000..b2aaad2f7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Image.java @@ -0,0 +1,1413 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Image { + + /** Creates a new instance of Image */ + public Image() { + } + + public static short getShortFromByteArray( byte[] array, int index ) { + short s; + s = (short)(array[index] << 8 ); + s |= (short)(0x00FF & array[index+1]); + return( s ); + } + + public static int getIntFromByteArray( byte[] array, int index ) { + int i; + i = ( array[index] << 24 ) & 0xFF000000; + i |= ( array[index+1] << 16 ) & 0x00FF0000; + i |= ( array[index+2] << 8 ) & 0x0000FF00; + i |= ( array[index+3] ) & 0x000000FF; + return( i ); + } + + public static float getFloatFromByteArray( byte[] array, int index ) { + int i = getIntFromByteArray( array, index ); + return( Float.intBitsToFloat(i) ); + } + + /* + * Extract array from user's data applying all pixel store modes. + * The internal format used is an array of unsigned shorts. + */ + public static void fill_image( PixelStorageModes psm, int width, int height, + int format, int type, boolean index_format, ByteBuffer userdata, + ShortBuffer newimage ) { + int components; + int element_size; + int rowsize; + int padding; + int groups_per_line; + int group_size; + int elements_per_line; + int start; + int iter = 0; + int iter2; + int i, j, k; + boolean myswap_bytes; + + // Create a Extract interface object + Extract extract = null; + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract = new Extract332(); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract = new Extract233rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract = new Extract565(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract = new Extract565rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract = new Extract4444(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract = new Extract4444rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract = new Extract5551(); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract = new Extract1555rev(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract = new Extract8888(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract = new Extract8888rev(); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract = new Extract1010102(); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract = new Extract2101010rev(); + break; + } + + myswap_bytes = psm.getUnpackSwapBytes(); + components = Mipmap.elements_per_group( format, type ); + if( psm.getUnpackRowLength() > 0 ) { + groups_per_line = psm.getUnpackRowLength(); + } else { + groups_per_line = width; + } + + // All formats except GL_BITMAP fall out trivially + if( type == GL2.GL_BITMAP ) { + int bit_offset; + int current_bit; + + rowsize = ( groups_per_line * components + 7 ) / 8; + padding = ( rowsize % psm.getUnpackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getUnpackAlignment() - padding; + } + start = psm.getUnpackSkipRows() * rowsize + ( psm.getUnpackSkipPixels() * components / 8 ); + elements_per_line = width * components; + iter2 = 0; + for( i = 0; i < height; i++ ) { + iter = start; + userdata.position( iter ); // **************************************** + bit_offset = (psm.getUnpackSkipPixels() * components) % 8; + for( j = 0; j < elements_per_line; j++ ) { + // retrieve bit + if( psm.getUnpackLsbFirst() ) { + userdata.position( iter ); + current_bit = ( userdata.get() & 0x000000FF ) & ( 1 << bit_offset );//userdata[iter] & ( 1 << bit_offset ); + } else { + current_bit = ( userdata.get() & 0x000000FF ) & ( 1 << ( 7 - bit_offset ) ); + } + if( current_bit != 0 ) { + if( index_format ) { + newimage.position( iter2 ); + newimage.put( (short)1 ); + } else { + newimage.position( iter2 ); + newimage.put( (short)65535 ); + } + } else { + newimage.position( iter2 ); + newimage.put( (short)0 ); + } + bit_offset++; + if( bit_offset == 8 ) { + bit_offset = 0; + iter++; + } + iter2++; + } + start += rowsize; + } + } else { + element_size = Mipmap.bytes_per_element( type ); + group_size = element_size * components; + if( element_size == 1 ) { + myswap_bytes = false; + } + + rowsize = groups_per_line * group_size; + padding = ( rowsize % psm.getUnpackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getUnpackAlignment() - padding; + } + start = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size; + elements_per_line = width * components; + + iter2 = 0; + for( i = 0; i < height; i++ ) { + iter = start; + userdata.position( iter ); //*************************************** + for( j = 0; j < elements_per_line; j++ ) { + Type_Widget widget = new Type_Widget(); + float[] extractComponents = new float[4]; + userdata.position( iter ); + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract.extract( false, userdata /*userdata[iter]*/, extractComponents ); + for( k = 0; k < 3; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract.extract( false, userdata /*userdata[iter]*/, extractComponents ); + for( k = 0; k < 3; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE ): + if( index_format ) { + newimage.put( iter2++, (short)( 0x000000FF & userdata.get() ) );//userdata[iter]; + } else { + newimage.put( iter2++, (short)( 0x000000FF & userdata.get()/*userdata[iter]*/ * 257 ) ); + } + break; + case( GL2.GL_BYTE ): + if( index_format ) { + newimage.put( iter2++, userdata.get() ); //userdata[iter]; + } else { + newimage.put( iter2++, (short)(userdata.get()/*userdata[iter]*/ * 516 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract.extract( myswap_bytes, userdata/*userdata[iter]*/, extractComponents ); + for( k = 0; k < 3; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 3; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + if( myswap_bytes ) { + widget.setUB1( userdata.get() ); + widget.setUB0( userdata.get() ); + } else { + widget.setUB0( userdata.get() ); + widget.setUB1( userdata.get() ); + } + if( type == GL2.GL_SHORT ) { + if( index_format ) { + newimage.put( iter2++, widget.getS0() ); + } else { + newimage.put( iter2++, (short)(widget.getS0() * 2) ); + } + } else { + newimage.put( iter2++, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_INT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_FLOAT ): + if( myswap_bytes ) { + widget.setUB3( userdata.get() ); + widget.setUB2( userdata.get() ); + widget.setUB1( userdata.get() ); + widget.setUB0( userdata.get() ); + } else { + widget.setUB0( userdata.get() ); + widget.setUB1( userdata.get() ); + widget.setUB2( userdata.get() ); + widget.setUB3( userdata.get() ); + } + if( type == GL2.GL_FLOAT ) { + if( index_format ) { + newimage.put( iter2++, (short)widget.getF() ); + } else { + newimage.put( iter2++, (short)(widget.getF() * 65535 ) ); + } + } else if( type == GL2.GL_UNSIGNED_INT ) { + if( index_format ) { + newimage.put( iter2++, (short)( widget.getUI() ) ); + } else { + newimage.put( iter2++, (short)( widget.getUI() >> 16 ) ); + } + } else { + if( index_format ) { + newimage.put( iter2++, (short)( widget.getI() ) ); + } else { + newimage.put( iter2++, (short)( widget.getI() >> 15 ) ); + } + } + break; + } + iter += element_size; + } // for j + start += rowsize; + // want iter pointing at start, not within, row for assertion purposes + iter = start; + } // for i + + // iterators should be one byte past end + if( !Mipmap.isTypePackedPixel( type ) ) { + assert( iter2 == ( width * height * components ) ); + } else { + assert( iter2 == ( width * height * Mipmap.elements_per_group( format, 0 ) ) ); + } + assert( iter == ( rowsize * height + psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size ) ); + } + } + + /* + * Insert array into user's data applying all pixel store modes. + * Theinternal format is an array of unsigned shorts. + * empty_image() because it is the opposet of fill_image(). + */ + public static void empty_image( PixelStorageModes psm, int width, int height, + int format, int type, boolean index_format, + ShortBuffer oldimage, ByteBuffer userdata ) { + + int components; + int element_size; + int rowsize; + int padding; + int groups_per_line; + int group_size; + int elements_per_line; + int start; + int iter = 0; + int iter2; + int i, j, k; + boolean myswap_bytes; + + // Create a Extract interface object + Extract extract = null; + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract = new Extract332(); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract = new Extract233rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract = new Extract565(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract = new Extract565rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract = new Extract4444(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract = new Extract4444rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract = new Extract5551(); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract = new Extract1555rev(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract = new Extract8888(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract = new Extract8888rev(); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract = new Extract1010102(); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract = new Extract2101010rev(); + break; + } + + myswap_bytes = psm.getPackSwapBytes(); + components = Mipmap.elements_per_group( format, type ); + if( psm.getPackRowLength() > 0 ) { + groups_per_line = psm.getPackRowLength(); + } else { + groups_per_line = width; + } + + // all formats except GL_BITMAP fall out trivially + if( type == GL2.GL_BITMAP ) { + int bit_offset; + int current_bit; + + rowsize = ( groups_per_line * components + 7 ) / 8; + padding = ( rowsize % psm.getPackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getPackAlignment() - padding; + } + start = psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * components / 8; + elements_per_line = width * components; + iter2 = 0; + for( i = 0; i < height; i++ ) { + iter = start; + bit_offset = ( psm.getPackSkipPixels() * components ) % 8; + for( j = 0; j < elements_per_line; j++ ) { + if( index_format ) { + current_bit = oldimage.get( iter2 ) & 1; + } else { + if( oldimage.get( iter2 ) < 0 ) { // must check for negative rather than 32767 + current_bit = 1; + } else { + current_bit = 0; + } + } + + if( current_bit != 0 ) { + if( psm.getPackLsbFirst() ) { + userdata.put( iter, (byte)( ( userdata.get( iter ) | ( 1 << bit_offset ) ) ) ); + } else { + userdata.put( iter, (byte)( ( userdata.get( iter ) | ( 7 - bit_offset ) ) ) ); + } + } else { + if( psm.getPackLsbFirst() ) { + //userdata[iter] &= ~( 1 << bit_offset ); + userdata.put( iter, (byte)( ( userdata.get( iter ) & ~( 1 << bit_offset ) ) ) ); + } else { + //userdata[iter] &= ~( 1 << ( 7 - bit_offset ) ); + userdata.put( iter, (byte)( ( userdata.get( iter ) & ~( 7 - bit_offset ) ) ) ); + } + } + + bit_offset++; + if( bit_offset == 8 ) { + bit_offset = 0; + iter++; + } + iter2++; + } + start += rowsize; + } + } else { + float shoveComponents[] = new float[4]; + + element_size = Mipmap.bytes_per_element( type ); + group_size = element_size * components; + if( element_size == 1 ) { + myswap_bytes = false; + } + + rowsize = groups_per_line * group_size; + padding = ( rowsize % psm.getPackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getPackAlignment() - padding; + } + start = psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * group_size; + elements_per_line = width * components; + + iter2 = 0; + for( i = 0; i < height; i++ ) { + iter = start; + for( j = 0; j < elements_per_line; j++ ) { + Type_Widget widget = new Type_Widget(); + + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, userdata ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldimage.get(iter2++) / 65535.0f; + } + extract.shove( shoveComponents, 0, userdata ); + break; + case( GL2.GL_UNSIGNED_BYTE ): + if( index_format ) { + //userdata[iter] = (byte)oldimage[iter2++]; + userdata.put( iter, (byte)oldimage.get(iter2++) ); + } else { + //userdata[iter] = (byte)( oldimage[iter2++] >> 8 ); + userdata.put( iter, (byte)( oldimage.get(iter2++) ) ); + } + break; + case( GL2.GL_BYTE ): + if( index_format ) { + //userdata[iter] = (byte)oldimage[iter2++]; + userdata.put( iter, (byte)oldimage.get(iter2++) ); + } else { + //userdata[iter] = (byte)( oldimage[iter2++] >> 9 ); + userdata.put( iter, (byte)( oldimage.get(iter2++) ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldimage.get(iter2++) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1,widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldimage.get(iter2++) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get(iter2++) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + if( type == GL2.GL_SHORT ) { + if( index_format ) { + widget.setS0( oldimage.get( iter2++ ) ); + } else { + widget.setS0( (short)(oldimage.get( iter2++ ) >> 1) ); + } + } else { + widget.setUS0( oldimage.get( iter2++ ) ); + } + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter+3] = widget.getUB0(); + //userdata[iter+2] = widget.getUB1(); + //userdata[iter+1] = widget.getUB2(); + //userdata[iter ] = widget.getUB3(); + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter+3] = widget.getUB0(); + //userdata[iter+2] = widget.getUB1(); + //userdata[iter+1] = widget.getUB2(); + //userdata[iter ] = widget.getUB3(); + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 2, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter+3] = widget.getUB0(); + //userdata[iter+2] = widget.getUB1(); + //userdata[iter+1] = widget.getUB2(); + //userdata[iter ] = widget.getUB3(); + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter+3] = widget.getUB0(); + //userdata[iter+2] = widget.getUB1(); + //userdata[iter+1] = widget.getUB2(); + //userdata[iter ] = widget.getUB3(); + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_INT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_FLOAT ): + if( type == GL2.GL_FLOAT ) { + if( index_format ) { + widget.setF( oldimage.get( iter2++ ) ); + } else { + widget.setF( oldimage.get( iter2++ ) / 65535.0f ); + } + } else if( type == GL2.GL_UNSIGNED_INT ) { + if( index_format ) { + widget.setUI( oldimage.get( iter2++ ) ); + } else { + widget.setUI( oldimage.get( iter2++ ) * 65537 ); + } + } else { + if( index_format ) { + widget.setI( oldimage.get( iter2++ ) ); + } else { + widget.setI( (oldimage.get( iter2++ ) * 65537) / 2 ); + } + } + if( myswap_bytes ) { + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.put( iter , widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + userdata.put( iter + 2, widget.getUB2() ); + userdata.put( iter + 3, widget.getUB3() ); + } + break; + } + iter += element_size; + } // for j + start += rowsize; + // want iter pointing at start, not within, row for assertion purposes + iter = start; + } // for i + // iterators should be one byte past end + if( !Mipmap.isTypePackedPixel( type ) ) { + assert( iter2 == width * height * components ); + } else { + assert( iter2 == width * height * Mipmap.elements_per_group( format, 0 ) ); + } + assert( iter == rowsize * height + psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * group_size ); + } + } + + public static void fillImage3D( PixelStorageModes psm, int width, int height, + int depth, int format, int type, boolean indexFormat, ByteBuffer userImage, + ShortBuffer newImage ) { + boolean myswapBytes; + int components; + int groupsPerLine; + int elementSize; + int groupSize; + int rowSize; + int padding; + int elementsPerLine; + int rowsPerImage; + int imageSize; + int start, rowStart; + int iter = 0; + int iter2 = 0; + int ww, hh, dd, k; + Type_Widget widget = new Type_Widget(); + float extractComponents[] = new float[4]; + + // Create a Extract interface object + Extract extract = null; + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract = new Extract332(); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract = new Extract233rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract = new Extract565(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract = new Extract565rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract = new Extract4444(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract = new Extract4444rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract = new Extract5551(); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract = new Extract1555rev(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract = new Extract8888(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract = new Extract8888rev(); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract = new Extract1010102(); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract = new Extract2101010rev(); + break; + } + + myswapBytes = psm.getUnpackSwapBytes(); + components = Mipmap.elements_per_group( format, type ); + if( psm.getUnpackRowLength() > 0 ) { + groupsPerLine = psm.getUnpackRowLength(); + } else { + groupsPerLine = width; + } + elementSize = Mipmap.bytes_per_element( type ); + groupSize = elementSize * components; + if( elementSize == 1 ) { + myswapBytes = false; + } + + // 3dstuff begin + if( psm.getUnpackImageHeight() > 0 ) { + rowsPerImage = psm.getUnpackImageHeight(); + } else { + rowsPerImage = height; + } + // 3dstuff end + + rowSize = groupsPerLine * groupSize; + padding = rowSize % psm.getUnpackAlignment(); + if( padding != 0 ) { + rowSize += psm.getUnpackAlignment() - padding; + } + + imageSize = rowsPerImage * rowSize; // 3dstuff + + start = psm.getUnpackSkipRows() * rowSize + + psm.getUnpackSkipPixels() * groupSize + + psm.getUnpackSkipImages() * imageSize; + elementsPerLine = width * components; + + iter2 = 0; + for( dd = 0; dd < depth; dd++ ) { + rowStart = start; + for( hh = 0; hh < height; hh++ ) { + iter = rowStart; + for( ww = 0; ww < elementsPerLine; ww++ ) { + + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + if( indexFormat ) { + newImage.put( iter2++, (short)(0x000000FF & userImage.get( iter ) ) ); + } else { + newImage.put( iter2++, (short)((0x000000FF & userImage.get( iter ) ) * 257 ) ); + } + break; + case( GL2.GL_BYTE ): + if( indexFormat ) { + newImage.put( iter2++, userImage.get( iter ) ); + } else { + newImage.put( iter2++, (short)(userImage.get( iter ) * 516 ) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + userImage.position( iter ); + extract.extract( false, userImage, extractComponents ); + for( k = 0; k < 3; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + userImage.position( iter ); + extract.extract( false, userImage, extractComponents ); + for( k = 0; k < 3; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + if( myswapBytes ) { + widget.setUB0( userImage.get( iter + 1 ) ); + widget.setUB1( userImage.get( iter ) ); + } else { + widget.setUB0( userImage.get( iter ) ); + widget.setUB1( userImage.get( iter + 1 ) ); + } + if( type == GL2.GL_SHORT ) { + if( indexFormat ) { + newImage.put( iter2++, widget.getUS0() ); + } else { + newImage.put( iter2++, (short)(widget.getUS0() * 2) ); + } + } else { + newImage.put( iter2++, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_INT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_FLOAT ): + if( myswapBytes ) { + widget.setUB0( userImage.get( iter + 3 ) ); + widget.setUB1( userImage.get( iter + 2 ) ); + widget.setUB2( userImage.get( iter + 1 ) ); + widget.setUB3( userImage.get( iter ) ); + } else { + widget.setUB0( userImage.get( iter ) ); + widget.setUB1( userImage.get( iter + 1 ) ); + widget.setUB2( userImage.get( iter + 2 ) ); + widget.setUB3( userImage.get( iter + 3 ) ); + } + if( type == GL2.GL_FLOAT ) { + if( indexFormat ) { + newImage.put( iter2++, (short)widget.getF() ); + } else { + newImage.put( iter2++, (short)( widget.getF() * 65535.0f ) ); + } + } else if( type == GL2.GL_UNSIGNED_INT ) { + if( indexFormat ) { + newImage.put( iter2++, (short)widget.getUI() ); + } else { + newImage.put( iter2++, (short)(widget.getUI() >> 16) ); + } + } else { + if( indexFormat ) { + newImage.put( iter2++, (short)widget.getI() ); + } else { + newImage.put( iter2++, (short)(widget.getI() >> 15) ); + } + } + break; + default: + assert( false ); + } + iter += elementSize; + } // for ww + rowStart += rowSize; + iter = rowStart; // for assert + } // for hh + start += imageSize; + }// for dd + + // iterators should be one byte past end + if( !Mipmap.isTypePackedPixel( type ) ) { + assert( iter2 == width * height * depth * components ); + } else { + assert( iter2 == width * height * depth * Mipmap.elements_per_group( format, 0 ) ); + } + assert( iter == rowSize * height * depth + psm.getUnpackSkipRows() * rowSize + + psm.getUnpackSkipPixels() * groupSize + + psm.getUnpackSkipImages() * imageSize ); + } + + public static void emptyImage3D( PixelStorageModes psm, int width, int height, int depth, + int format, int type, boolean indexFormat, ShortBuffer oldImage, ByteBuffer userImage ) { + boolean myswapBytes; + int components; + int groupsPerLine; + int elementSize; + int groupSize; + int rowSize; + int padding; + int start, rowStart, iter; + int elementsPerLine; + int iter2; + int ii, jj, dd, k; + int rowsPerImage; + int imageSize; + Type_Widget widget = new Type_Widget(); + float[] shoveComponents = new float[4]; + + // Create a Extract interface object + Extract extract = null; + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract = new Extract332(); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract = new Extract233rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract = new Extract565(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract = new Extract565rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract = new Extract4444(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract = new Extract4444rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract = new Extract5551(); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract = new Extract1555rev(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract = new Extract8888(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract = new Extract8888rev(); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract = new Extract1010102(); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract = new Extract2101010rev(); + break; + } + + iter = 0; + + myswapBytes = psm.getPackSwapBytes(); + components = Mipmap.elements_per_group( format, type ); + if( psm.getPackRowLength() > 0 ) { + groupsPerLine = psm.getPackRowLength(); + } else { + groupsPerLine = width; + } + + elementSize = Mipmap.bytes_per_element( type ); + groupSize = elementSize * components; + if( elementSize == 1 ) { + myswapBytes = false; + } + + // 3dstuff begin + if( psm.getPackImageHeight() > 0 ) { + rowsPerImage = psm.getPackImageHeight(); + } else { + rowsPerImage = height; + } + + // 3dstuff end + + rowSize = groupsPerLine * groupSize; + padding = rowSize % psm.getPackAlignment(); + if( padding != 0 ) { + rowSize += psm.getPackAlignment() - padding; + } + + imageSize = rowsPerImage * rowSize; + + start = psm.getPackSkipRows() * rowSize + + psm.getPackSkipPixels() * groupSize + + psm.getPackSkipImages() * imageSize; + elementsPerLine = width * components; + + iter2 = 0; + for( dd = 0; dd < depth; dd++ ) { + rowStart = start; + + for( ii = 0; ii < height; ii++ ) { + iter = rowStart; + + for( jj = 0; jj < elementsPerLine; jj++ ) { + + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + if( indexFormat ) { + userImage.put( iter, (byte)(oldImage.get( iter2++ ) ) ); + } else { + userImage.put( iter, (byte)(oldImage.get( iter2++ ) >> 8 ) ); + } + break; + case( GL2.GL_BYTE ): + if( indexFormat ) { + userImage.put( iter, (byte)(oldImage.get(iter2++) ) ); + } else { + userImage.put( iter, (byte)(oldImage.get(iter2++) >> 9) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, userImage ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, userImage ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.putShort( iter, widget.getUB1() ); + userImage.putShort( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + if( type == GL2.GL_SHORT ) { + if( indexFormat ) { + widget.setS0( (short)oldImage.get( iter2++ ) ); + } else { + widget.setS0( (short)(oldImage.get( iter2++ ) >> 1) ); + } + } else { + widget.setUS0( (short)oldImage.get( iter2++ ) ); + } + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.put( iter, widget.getUB0() ); + userImage.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB2() ); + userImage.put( iter , widget.getUB3() ); + } else { + userImage.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB2() ); + userImage.put( iter , widget.getUB3() ); + } else { + userImage.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB2() ); + userImage.put( iter ,widget.getUB3() ); + } else { + userImage.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB2() ); + userImage.put( iter + 1, widget.getUB1() ); + userImage.put( iter , widget.getUB0() ); + } else { + userImage.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_INT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_FLOAT ): + if( type == GL2.GL_FLOAT ) { + if( indexFormat ) { + widget.setF( oldImage.get( iter2++ ) ); + } else { + widget.setF( oldImage.get( iter2++ ) / 65535.0f ); + } + } else if( type == GL2.GL_UNSIGNED_INT ) { + if( indexFormat ) { + widget.setUI( oldImage.get( iter2++ ) ); + } else { + widget.setUI( oldImage.get( iter2++ ) * 65537 ); + } + } else { + if( indexFormat ) { + widget.setI( oldImage.get( iter2++ ) ); + } else { + widget.setI( ( oldImage.get( iter2++ ) * 65535 ) / 2 ); + } + } + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB2() ); + userImage.put( iter , widget.getUB3() ); + } else { + userImage.put( iter , widget.getUB0() ); + userImage.put( iter + 1, widget.getUB1() ); + userImage.put( iter + 2, widget.getUB2() ); + userImage.put( iter + 3, widget.getUB3() ); + } + break; + default: + assert( false ); + } + + iter += elementSize; + } // for jj + rowStart += rowSize; + } // for ii + start += imageSize; + } // for dd + + if( !Mipmap.isTypePackedPixel( type ) ) { + assert( iter2 == width * height * depth * components ); + } else { + assert( iter2 == width * height * depth * Mipmap.elements_per_group( format, 0 ) ); + } + assert( iter == rowSize * height * depth + + psm.getUnpackSkipRows() * rowSize + + psm.getUnpackSkipPixels() * groupSize + + psm.getUnpackSkipImages() * imageSize ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Mipmap.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Mipmap.java new file mode 100644 index 000000000..1c0707c57 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Mipmap.java @@ -0,0 +1,868 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.GLException; +import java.nio.*; +import com.jogamp.opengl.impl.InternalBufferUtil; + +/** + * + * @author Administrator + */ +public class Mipmap { + + /** Creates a new instance of Mipmap */ + public Mipmap() { + } + + public static int computeLog( int value ) { + int i = 0; + // Error + if( value == 0 ) { + return( -1 ); + } + for( ;; ) { + if( (value & 1) >= 1 ) { + if( value != 1 ) { + return( -1 ); + } + return( i ); + } + value = value >> 1; + i++; + } + } + + /* Compute the nearest power of 2 number. This algorithm is a little strange + * but it works quite well. + */ + public static int nearestPower( int value ) { + int i = 1; + // Error! + if( value == 0 ) { + return( -1 ); + } + for( ;; ) { + if( value == 1 ) { + return( i ); + } else if( value == 3 ) { + return( i * 4 ); + } + value = value >> 1; + i *= 2; + } + } + + public static short GLU_SWAP_2_BYTES( short s ) { + byte b = 0; + b = (byte)( s >>> 8 ); + s = (short)( s << 8 ); + s = (short)( s | (0x00FF & b) ); + return( s ); + } + + public static int GLU_SWAP_4_BYTES( int i ) { + int t = i << 24; + t |= 0x00FF0000 & ( i << 8 ); + t |= 0x0000FF00 & ( i >>> 8 ); + t |= 0x000000FF & ( i >>> 24 ); + return( t ); + } + + public static float GLU_SWAP_4_BYTES( float f ) { + int i = Float.floatToRawIntBits( f ); + float temp = Float.intBitsToFloat( i ); + return( temp ); + } + + public static int checkMipmapArgs( int internalFormat, int format, int type ) { + if( !legalFormat( format ) || !legalType( type ) ) { + return( GLU.GLU_INVALID_ENUM ); + } + if( format == GL2GL3.GL_STENCIL_INDEX ) { + return( GLU.GLU_INVALID_ENUM ); + } + if( !isLegalFormatForPackedPixelType( format, type ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + return( 0 ); + } + + public static boolean legalFormat( int format ) { + switch( format ) { + case( GL2.GL_COLOR_INDEX ): + case( GL2GL3.GL_STENCIL_INDEX ): + case( GL2GL3.GL_DEPTH_COMPONENT ): + case( GL2GL3.GL_RED ): + case( GL2GL3.GL_GREEN ): + case( GL2GL3.GL_BLUE ): + case( GL2GL3.GL_ALPHA ): + case( GL2GL3.GL_RGB ): + case( GL2GL3.GL_RGBA ): + case( GL2GL3.GL_LUMINANCE ): + case( GL2GL3.GL_LUMINANCE_ALPHA ): + case( GL2GL3.GL_BGR ): + case( GL2GL3.GL_BGRA ): + return( true ); + default: + return( false ); + } + } + + public static boolean legalType( int type ) { + switch( type ) { + case( GL2.GL_BITMAP ): + case( GL2GL3.GL_BYTE ): + case( GL2GL3.GL_UNSIGNED_BYTE ): + case( GL2GL3.GL_SHORT ): + case( GL2GL3.GL_UNSIGNED_SHORT ): + case( GL2GL3.GL_INT ): + case( GL2GL3.GL_UNSIGNED_INT ): + case( GL2GL3.GL_FLOAT ): + case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ): + return( true ); + default: + return( false ); + } + } + + public static boolean isTypePackedPixel( int type ) { + assert( legalType( type ) ); + + if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || + type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 || + type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV || + type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 || + type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) { + return( true ); + } + return( false ); + } + + public static boolean isLegalFormatForPackedPixelType( int format, int type ) { + // if not a packed pixel type then return true + if( isTypePackedPixel( type ) ) { + return( true ); + } + + // 3_3_2/2_3_3_REV & 5_6_5/5_6_5_REV are only compatible with RGB + if( (type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 || type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ) + & format != GL2GL3.GL_RGB ) { + return( false ); + } + + // 4_4_4_4/4_4_4_4_REV & 5_5_5_1/1_5_5_5_REV & 8_8_8_8/8_8_8_8_REV & + // 10_10_10_2/2_10_10_10_REV are only campatible with RGBA, BGRA & ARGB_EXT + if( ( type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 || + type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV || + type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 || + type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) && + (format != GL2GL3.GL_RGBA && format != GL2GL3.GL_BGRA) ) { + return( false ); + } + return( true ); + } + + public static boolean isLegalLevels( int userLevel, int baseLevel, int maxLevel, + int totalLevels ) { + if( (baseLevel < 0) || (baseLevel < userLevel) || (maxLevel < baseLevel) || + (totalLevels < maxLevel) ) { + return( false ); + } + return( true ); + } + + /* Given user requested textures size, determine if it fits. If it doesn't then + * halve both sides and make the determination again until it does fit ( for + * IR only ). + * Note that proxy textures are not implemented in RE* even though they + * advertise the texture extension. + * Note that proxy textures are implemented but not according to spec in IMPACT* + */ + public static void closestFit( GL gl, int target, int width, int height, int internalFormat, + int format, int type, int[] newWidth, int[] newHeight ) { + // Use proxy textures if OpenGL version >= 1.1 + if( Double.parseDouble( gl.glGetString( GL.GL_VERSION ).trim().substring( 0, 3 ) ) >= 1.1 ) { + int widthPowerOf2 = nearestPower( width ); + int heightPowerOf2 = nearestPower( height ); + int[] proxyWidth = new int[1]; + boolean noProxyTextures = false; + + // Some drivers (in particular, ATI's) seem to set a GL error + // when proxy textures are used even though this is in violation + // of the spec. Guard against this and interactions with the + // DebugGL by watching for GLException. + try { + do { + // compute level 1 width & height, clamping each at 1 + int widthAtLevelOne = ( ( width > 1 ) ? (widthPowerOf2 >> 1) : widthPowerOf2 ); + int heightAtLevelOne = ( ( height > 1 ) ? (heightPowerOf2 >> 1) : heightPowerOf2 ); + int proxyTarget; + + assert( widthAtLevelOne > 0 ); + assert( heightAtLevelOne > 0 ); + + // does width x height at level 1 & all their mipmaps fit? + if( target == GL2GL3.GL_TEXTURE_2D || target == GL2GL3.GL_PROXY_TEXTURE_2D ) { + proxyTarget = GL2GL3.GL_PROXY_TEXTURE_2D; + gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne, + heightAtLevelOne, 0, format, type, null ); + } else if( (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_X) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_X) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Y) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Z) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ) { + proxyTarget = GL2GL3.GL_PROXY_TEXTURE_CUBE_MAP; + gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne, + heightAtLevelOne, 0, format, type, null ); + } else { + assert( target == GL2GL3.GL_TEXTURE_1D || target == GL2GL3.GL_PROXY_TEXTURE_1D ); + proxyTarget = GL2GL3.GL_PROXY_TEXTURE_1D; + gl.getGL2GL3().glTexImage1D( proxyTarget, 1, internalFormat, widthAtLevelOne, + 0, format, type, null ); + } + if(gl.isGL2GL3()) { + gl.getGL2GL3().glGetTexLevelParameteriv( proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0 ); + } else { + proxyWidth[0] = 0; + } + // does it fit? + if( proxyWidth[0] == 0 ) { // nope, so try again with theses sizes + if( widthPowerOf2 == 1 && heightPowerOf2 == 1 ) { + /* A 1x1 texture couldn't fit for some reason so break out. This + * should never happen. But things happen. The disadvantage with + * this if-statement is that we will never be aware of when this + * happens since it will silently branch out. + */ + noProxyTextures = true; + break; + } + widthPowerOf2 = widthAtLevelOne; + heightPowerOf2 = heightAtLevelOne; + } + // else it does fit + } while( proxyWidth[0] == 0 ); + } catch (GLException e) { + noProxyTextures = true; + } + // loop must terminate + // return the width & height at level 0 that fits + if( !noProxyTextures ) { + newWidth[0] = widthPowerOf2; + newHeight[0] = heightPowerOf2; + return; + } + } + int[] maxsize = new int[1]; + gl.glGetIntegerv( GL2GL3.GL_MAX_TEXTURE_SIZE, maxsize , 0); + // clamp user's texture sizes to maximum sizes, if necessary + newWidth[0] = nearestPower( width ); + if( newWidth[0] > maxsize[0] ) { + newWidth[0] = maxsize[0]; + } + newHeight[0] = nearestPower( height ); + if( newHeight[0] > maxsize[0] ) { + newHeight[0] = maxsize[0]; + } + } + + public static void closestFit3D( GL gl, int target, int width, int height, int depth, + int internalFormat, int format, int type, int[] newWidth, int[] newHeight, + int[] newDepth ) { + int widthPowerOf2 = nearestPower( width ); + int heightPowerOf2 = nearestPower( height ); + int depthPowerOf2 = nearestPower( depth ); + int[] proxyWidth = new int[1]; + + do { + // compute level 1 width & height & depth, clamping each at 1 + int widthAtLevelOne = (widthPowerOf2 > 1) ? widthPowerOf2 >> 1 : widthPowerOf2; + int heightAtLevelOne = (heightPowerOf2 > 1) ? heightPowerOf2 >> 1 : heightPowerOf2; + int depthAtLevelOne = (depthPowerOf2 > 1) ? depthPowerOf2 >> 1 : depthPowerOf2; + int proxyTarget = 0; + assert( widthAtLevelOne > 0 ); + assert( heightAtLevelOne > 0 ); + assert( depthAtLevelOne > 0 ); + + // does width x height x depth at level 1 & all their mipmaps fit? + if( target == GL2GL3.GL_TEXTURE_3D || target == GL2GL3.GL_PROXY_TEXTURE_3D ) { + proxyTarget = GL2GL3.GL_PROXY_TEXTURE_3D; + gl.getGL2GL3().glTexImage3D( proxyTarget, 1, internalFormat, widthAtLevelOne, + heightAtLevelOne, depthAtLevelOne, 0, format, type, null ); + } + if(gl.isGL2GL3()) { + gl.getGL2GL3().glGetTexLevelParameteriv( proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0 ); + } else { + proxyWidth[0] = 0; + } + // does it fit + if( proxyWidth[0] == 0 ) { + if( widthPowerOf2 == 1 && heightPowerOf2 == 1 && depthPowerOf2 == 1 ) { + newWidth[0] = newHeight[0] = newDepth[0] = 1; + return; + } + widthPowerOf2 = widthAtLevelOne; + heightPowerOf2 = heightAtLevelOne; + depthPowerOf2 = depthAtLevelOne; + } + } while( proxyWidth[0] == 0 ); + // loop must terminate + + // return the width & height at level 0 that fits + newWidth[0] = widthPowerOf2; + newHeight[0] = heightPowerOf2; + newDepth[0] = depthPowerOf2; + } + + public static int elements_per_group( int format, int type ) { + // Return the number of elements per grtoup of a specified gromat + + // If the type is packedpixels then answer is 1 + if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || + type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 || + type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV || + type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 || + type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) { + return( 1 ); + } + + // Types are not packed pixels so get elements per group + switch( format ) { + case( GL2GL3.GL_RGB ): + case( GL2GL3.GL_BGR ): + return( 3 ); + case( GL2GL3.GL_LUMINANCE_ALPHA ): + return( 2 ); + case( GL2GL3.GL_RGBA ): + case( GL2GL3.GL_BGRA ): + return( 4 ); + default: + return( 1 ); + } + } + + public static int bytes_per_element( int type ) { + // return the number of bytes per element, based on the element type + + switch( type ) { + case( GL2.GL_BITMAP ): + case( GL2GL3.GL_BYTE ): + case( GL2GL3.GL_UNSIGNED_BYTE ): + case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ): + return( 1 ); + case( GL2GL3.GL_SHORT ): + case( GL2GL3.GL_UNSIGNED_SHORT ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + return( 2 ); + case( GL2GL3.GL_INT ): + case( GL2GL3.GL_UNSIGNED_INT ): + case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ): + case( GL2GL3.GL_FLOAT ): + return( 4 ); + default: + return( 4 ); + } + } + + public static boolean is_index( int format ) { + return( format == GL2.GL_COLOR_INDEX || format == GL2GL3.GL_STENCIL_INDEX ); + } + + /* Compute memory required for internal packed array of data of given type and format. */ + + public static int image_size( int width, int height, int format, int type ) { + int bytes_per_row; + int components; + + assert( width > 0 ); + assert( height > 0 ); + components = elements_per_group( format, type ); + if( type == GL2.GL_BITMAP ) { + bytes_per_row = (width + 7) / 8; + } else { + bytes_per_row = bytes_per_element( type ) * width; + } + return( bytes_per_row * height * components ); + } + + public static int imageSize3D( int width, int height, int depth, int format, int type ) { + int components = elements_per_group( format, type ); + int bytes_per_row = bytes_per_element( type ) * width; + + assert( width > 0 && height > 0 && depth > 0 ); + assert( type != GL2.GL_BITMAP ); + + return( bytes_per_row * height * depth * components ); + } + + public static void retrieveStoreModes( GL gl, PixelStorageModes psm ) { + int[] a = new int[1]; + gl.glGetIntegerv( GL2GL3.GL_UNPACK_ALIGNMENT, a, 0); + psm.setUnpackAlignment( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_ROW_LENGTH, a, 0); + psm.setUnpackRowLength( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_ROWS, a, 0); + psm.setUnpackSkipRows( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_PIXELS, a, 0); + psm.setUnpackSkipPixels( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0); + psm.setUnpackLsbFirst( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0); + psm.setUnpackSwapBytes( ( a[0] == 1 ) ); + + gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0); + psm.setPackAlignment( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0); + psm.setPackRowLength( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_ROWS, a, 0); + psm.setPackSkipRows( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_PIXELS, a, 0); + psm.setPackSkipPixels( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0); + psm.setPackLsbFirst( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0); + psm.setPackSwapBytes( ( a[0] == 1 ) ); + } + + public static void retrieveStoreModes3D( GL gl, PixelStorageModes psm ) { + int[] a = new int[1]; + gl.glGetIntegerv( GL2GL3.GL_UNPACK_ALIGNMENT, a, 0); + psm.setUnpackAlignment( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_ROW_LENGTH, a, 0); + psm.setUnpackRowLength( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_ROWS, a, 0); + psm.setUnpackSkipRows( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_PIXELS, a, 0); + psm.setUnpackSkipPixels( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0); + psm.setUnpackLsbFirst( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0); + psm.setUnpackSwapBytes( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_IMAGES, a, 0); + psm.setUnpackSkipImages( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_IMAGE_HEIGHT, a, 0); + psm.setUnpackImageHeight( a[0] ); + + gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0); + psm.setPackAlignment( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0); + psm.setPackRowLength( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_ROWS, a, 0); + psm.setPackSkipRows( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_PIXELS, a, 0 ); + psm.setPackSkipPixels( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0 ); + psm.setPackLsbFirst( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0 ); + psm.setPackSwapBytes( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_IMAGES, a, 0 ); + psm.setPackSkipImages( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_IMAGE_HEIGHT, a, 0 ); + psm.setPackImageHeight( a[0] ); + } + + public static int gluScaleImage( GL gl, int format, int widthin, int heightin, + int typein, ByteBuffer datain, int widthout, int heightout, + int typeout, ByteBuffer dataout ) { + int datainPos = datain.position(); + int dataoutPos = dataout.position(); + try { + + int components; + ByteBuffer beforeimage; + ByteBuffer afterimage; + PixelStorageModes psm = new PixelStorageModes(); + + if( (widthin == 0) || (heightin == 0) || (widthout == 0) || (heightout == 0) ) { + return( 0 ); + } + if( (widthin < 0) || (heightin < 0) || (widthout < 0) || (heightout < 0) ) { + return( GLU.GLU_INVALID_VALUE ); + } + if( !legalFormat( format ) || !legalType( typein ) || !legalType( typeout ) ) { + return( GLU.GLU_INVALID_ENUM ); + } + if( !isLegalFormatForPackedPixelType( format, typein ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + if( !isLegalFormatForPackedPixelType( format, typeout ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + beforeimage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( image_size( widthin, heightin, format, GL2GL3.GL_UNSIGNED_SHORT ) )); + afterimage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( image_size( widthout, heightout, format, GL2GL3.GL_UNSIGNED_SHORT ) )); + if( beforeimage == null || afterimage == null ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + + retrieveStoreModes( gl, psm ); + Image.fill_image( psm, widthin, heightin, format, typein, is_index( format ), datain, beforeimage.asShortBuffer() ); + components = elements_per_group( format, 0 ); + ScaleInternal.scale_internal( components, widthin, heightin, beforeimage.asShortBuffer(), widthout, heightout, afterimage.asShortBuffer() ); + Image.empty_image( psm, widthout, heightout, format, typeout, is_index( format ), afterimage.asShortBuffer(), dataout ); + + return( 0 ); + } finally { + datain.position(datainPos); + dataout.position(dataoutPos); + } + } + + public static int gluBuild1DMipmapLevels( GL gl, int target, int internalFormat, + int width, int format, int type, int userLevel, int baseLevel, + int maxLevel, ByteBuffer data ) { + int dataPos = data.position(); + try { + + int levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + levels = computeLog( width ); + + levels += userLevel; + if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) { + return( GLU.GLU_INVALID_VALUE ); + } + + return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat, width, + width, format, type, userLevel, baseLevel, maxLevel, data ) ); + } finally { + data.position(dataPos); + } + } + + public static int gluBuild1DMipmaps( GL gl, int target, int internalFormat, int width, + int format, int type, ByteBuffer data ) { + int dataPos = data.position(); + + try { + int[] widthPowerOf2 = new int[1]; + int levels; + int[] dummy = new int[1]; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + closestFit( gl, target, width, 1, internalFormat, format, type, widthPowerOf2, dummy ); + levels = computeLog( widthPowerOf2[0] ); + + return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat, + width, widthPowerOf2[0], format, type, 0, 0, levels, data ) ); + } finally { + data.position(dataPos); + } + } + + + public static int gluBuild2DMipmapLevels( GL gl, int target, int internalFormat, + int width, int height, int format, int type, int userLevel, + int baseLevel, int maxLevel, Object data ) { + int dataPos = 0; + + int level, levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 || height < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + levels = computeLog( width ); + level = computeLog( height ); + if( level > levels ) { + levels = level; + } + + levels += userLevel; + if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) { + return( GLU.GLU_INVALID_VALUE ); + } + + //PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data ); + ByteBuffer buffer = null; + if( data instanceof ByteBuffer ) { + buffer = (ByteBuffer)data; + dataPos = buffer.position(); + } else if( data instanceof byte[] ) { + byte[] array = (byte[])data; + buffer = ByteBuffer.allocateDirect(array.length); + buffer.put(array); + } else if( data instanceof short[] ) { + short[] array = (short[])data; + buffer = ByteBuffer.allocateDirect( array.length * 2 ); + ShortBuffer sb = buffer.asShortBuffer(); + sb.put( array ); + } else if( data instanceof int[] ) { + int[] array = (int[])data; + buffer = ByteBuffer.allocateDirect( array.length * 4 ); + IntBuffer ib = buffer.asIntBuffer(); + ib.put( array ); + } else if( data instanceof float[] ) { + float[] array = (float[])data; + buffer = ByteBuffer.allocateDirect( array.length * 4 ); + FloatBuffer fb = buffer.asFloatBuffer(); + fb.put( array ); + } + + try { + return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat, + width, height, width, height, format, type, userLevel, baseLevel, + maxLevel, buffer ) ); + } finally { + buffer.position(dataPos); + } + } + + + public static int gluBuild2DMipmaps( GL gl, int target, int internalFormat, + int width, int height, int format, int type, Object data ) { + int dataPos = 0; + + int[] widthPowerOf2 = new int[1]; + int[] heightPowerOf2 = new int[1]; + int level, levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 || height < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + closestFit( gl, target, width, height, internalFormat, format, type, + widthPowerOf2, heightPowerOf2 ); + + levels = computeLog( widthPowerOf2[0] ); + level = computeLog( heightPowerOf2[0] ); + if( level > levels ) { + levels = level; + } + + //PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data ); + ByteBuffer buffer = null; + if( data instanceof ByteBuffer ) { + buffer = (ByteBuffer)data; + dataPos = buffer.position(); + } else if( data instanceof byte[] ) { + byte[] array = (byte[])data; + buffer = ByteBuffer.allocateDirect(array.length); + buffer.put(array); + } else if( data instanceof short[] ) { + short[] array = (short[])data; + buffer = ByteBuffer.allocateDirect( array.length * 2 ); + ShortBuffer sb = buffer.asShortBuffer(); + sb.put( array ); + } else if( data instanceof int[] ) { + int[] array = (int[])data; + buffer = ByteBuffer.allocateDirect( array.length * 4 ); + IntBuffer ib = buffer.asIntBuffer(); + ib.put( array ); + } else if( data instanceof float[] ) { + float[] array = (float[])data; + buffer = ByteBuffer.allocateDirect( array.length * 4 ); + FloatBuffer fb = buffer.asFloatBuffer(); + fb.put( array ); + } + + try { + return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat, + width, height, widthPowerOf2[0], heightPowerOf2[0], format, type, 0, + 0, levels, buffer ) ); + } finally { + buffer.position(dataPos); + } + } + + + public static int gluBuild3DMipmaps( GL gl, int target, int internalFormat, + int width, int height, int depth, int format, int type, ByteBuffer data ) { + int dataPos = data.position(); + try { + + int[] widthPowerOf2 = new int[1]; + int[] heightPowerOf2 = new int[1]; + int[] depthPowerOf2 = new int[1]; + int level, levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 || height < 1 || depth < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + if( type == GL2.GL_BITMAP ) { + return( GLU.GLU_INVALID_ENUM ); + } + + closestFit3D( gl, target, width, height, depth, internalFormat, format, + type, widthPowerOf2, heightPowerOf2, depthPowerOf2 ); + + levels = computeLog( widthPowerOf2[0] ); + level = computeLog( heightPowerOf2[0] ); + if( level > levels ) { + levels = level; + } + level = computeLog( depthPowerOf2[0] ); + if( level > levels ) { + levels = level; + } + + return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width, + height, depth, widthPowerOf2[0], heightPowerOf2[0], depthPowerOf2[0], + format, type, 0, 0, levels, data ) ); + } finally { + data.position(dataPos); + } + } + + public static int gluBuild3DMipmapLevels( GL gl, int target, int internalFormat, + int width, int height, int depth, int format, int type, int userLevel, + int baseLevel, int maxLevel, ByteBuffer data ) { + int dataPos = data.position(); + try { + int level, levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 || height < 1 || depth < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + if( type == GL2.GL_BITMAP ) { + return( GLU.GLU_INVALID_ENUM ); + } + + levels = computeLog( width ); + level = computeLog( height ); + if( level > levels ) { + levels = level; + } + level = computeLog( depth ); + if( level > levels ) { + levels = level; + } + + levels += userLevel; + if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) { + return( GLU.GLU_INVALID_VALUE ); + } + + return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width, + height, depth, width, height, depth, format, type, userLevel, + baseLevel, maxLevel, data ) ); + } finally { + data.position(dataPos); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/PixelStorageModes.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/PixelStorageModes.java new file mode 100644 index 000000000..43b5c5691 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/PixelStorageModes.java @@ -0,0 +1,426 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +/** + * + * @author Administrator + */ +public class PixelStorageModes { + + /** + * Holds value of property packAlignment. + */ + private int packAlignment; + + /** + * Holds value of property packRowLength. + */ + private int packRowLength; + + /** + * Holds value of property packSkipRows. + */ + private int packSkipRows; + + /** + * Holds value of property packSkipPixels. + */ + private int packSkipPixels; + + /** + * Holds value of property packLsbFirst. + */ + private boolean packLsbFirst; + + /** + * Holds value of property packSwapBytes. + */ + private boolean packSwapBytes; + + /** + * Holds value of property packSkipImages. + */ + private int packSkipImages; + + /** + * Holds value of property packImageHeight. + */ + private int packImageHeight; + + /** + * Holds value of property unpackAlignment. + */ + private int unpackAlignment; + + /** + * Holds value of property unpackRowLength. + */ + private int unpackRowLength; + + /** + * Holds value of property unpackSkipRows. + */ + private int unpackSkipRows; + + /** + * Holds value of property unpackSkipPixels. + */ + private int unpackSkipPixels; + + /** + * Holds value of property unpackLsbFirst. + */ + private boolean unpackLsbFirst; + + /** + * Holds value of property unpackSwapBytes. + */ + private boolean unpackSwapBytes; + + /** + * Holds value of property unpackSkipImages. + */ + private int unpackSkipImages; + + /** + * Holds value of property unpackImageHeight. + */ + private int unpackImageHeight; + + /** Creates a new instance of PixelStorageModes */ + public PixelStorageModes() { + } + + /** + * Getter for property packAlignment. + * @return Value of property packAlignment. + */ + public int getPackAlignment() { + + return this.packAlignment; + } + + /** + * Setter for property packAlignment. + * @param packAlignment New value of property packAlignment. + */ + public void setPackAlignment(int packAlignment) { + + this.packAlignment = packAlignment; + } + + /** + * Getter for property packRowLength. + * @return Value of property packRowLength. + */ + public int getPackRowLength() { + + return this.packRowLength; + } + + /** + * Setter for property packRowLength. + * @param packRowLength New value of property packRowLength. + */ + public void setPackRowLength(int packRowLength) { + + this.packRowLength = packRowLength; + } + + /** + * Getter for property packSkipRows. + * @return Value of property packSkipRows. + */ + public int getPackSkipRows() { + + return this.packSkipRows; + } + + /** + * Setter for property packSkipRows. + * @param packSkipRows New value of property packSkipRows. + */ + public void setPackSkipRows(int packSkipRows) { + + this.packSkipRows = packSkipRows; + } + + /** + * Getter for property packSkipPixels. + * @return Value of property packSkipPixels. + */ + public int getPackSkipPixels() { + + return this.packSkipPixels; + } + + /** + * Setter for property packSkipPixels. + * @param packSkipPixels New value of property packSkipPixels. + */ + public void setPackSkipPixels(int packSkipPixels) { + + this.packSkipPixels = packSkipPixels; + } + + /** + * Getter for property packLsbFirst. + * @return Value of property packLsbFirst. + */ + public boolean getPackLsbFirst() { + + return this.packLsbFirst; + } + + /** + * Setter for property packLsbFirst. + * @param packLsbFirst New value of property packLsbFirst. + */ + public void setPackLsbFirst(boolean packLsbFirst) { + + this.packLsbFirst = packLsbFirst; + } + + /** + * Getter for property packSwapBytes. + * @return Value of property packSwapBytes. + */ + public boolean getPackSwapBytes() { + + return this.packSwapBytes; + } + + /** + * Setter for property packSwapBytes. + * @param packSwapBytes New value of property packSwapBytes. + */ + public void setPackSwapBytes(boolean packSwapBytes) { + + this.packSwapBytes = packSwapBytes; + } + + /** + * Getter for property packSkipImages. + * @return Value of property packSkipImages. + */ + public int getPackSkipImages() { + + return this.packSkipImages; + } + + /** + * Setter for property packSkipImages. + * @param packSkipImages New value of property packSkipImages. + */ + public void setPackSkipImages(int packSkipImages) { + + this.packSkipImages = packSkipImages; + } + + /** + * Getter for property packImageHeight. + * @return Value of property packImageHeight. + */ + public int getPackImageHeight() { + + return this.packImageHeight; + } + + /** + * Setter for property packImageHeight. + * @param packImageHeight New value of property packImageHeight. + */ + public void setPackImageHeight(int packImageHeight) { + + this.packImageHeight = packImageHeight; + } + + /** + * Getter for property unpackAlignment. + * @return Value of property unpackAlignment. + */ + public int getUnpackAlignment() { + + return this.unpackAlignment; + } + + /** + * Setter for property unpackAlignment. + * @param unpackAlignment New value of property unpackAlignment. + */ + public void setUnpackAlignment(int unpackAlignment) { + + this.unpackAlignment = unpackAlignment; + } + + /** + * Getter for property unpackRowLength. + * @return Value of property unpackRowLength. + */ + public int getUnpackRowLength() { + + return this.unpackRowLength; + } + + /** + * Setter for property unpackRowLength. + * @param unpackRowLength New value of property unpackRowLength. + */ + public void setUnpackRowLength(int unpackRowLength) { + + this.unpackRowLength = unpackRowLength; + } + + /** + * Getter for property unpackSkipRows. + * @return Value of property unpackSkipRows. + */ + public int getUnpackSkipRows() { + + return this.unpackSkipRows; + } + + /** + * Setter for property unpackSkipRows. + * @param unpackSkipRows New value of property unpackSkipRows. + */ + public void setUnpackSkipRows(int unpackSkipRows) { + + this.unpackSkipRows = unpackSkipRows; + } + + /** + * Getter for property unpackSkipPixels. + * @return Value of property unpackSkipPixels. + */ + public int getUnpackSkipPixels() { + + return this.unpackSkipPixels; + } + + /** + * Setter for property unpackSkipPixels. + * @param unpackSkipPixels New value of property unpackSkipPixels. + */ + public void setUnpackSkipPixels(int unpackSkipPixels) { + + this.unpackSkipPixels = unpackSkipPixels; + } + + /** + * Getter for property unpackLsbFirst. + * @return Value of property unpackLsbFirst. + */ + public boolean getUnpackLsbFirst() { + + return this.unpackLsbFirst; + } + + /** + * Setter for property unpackLsbFirst. + * @param unpackLsbFirst New value of property unpackLsbFirst. + */ + public void setUnpackLsbFirst(boolean unpackLsbFirst) { + + this.unpackLsbFirst = unpackLsbFirst; + } + + /** + * Getter for property unpackSwapBytes. + * @return Value of property unpackSwapBytes. + */ + public boolean getUnpackSwapBytes() { + + return this.unpackSwapBytes; + } + + /** + * Setter for property unpackSwapBytes. + * @param unpackSwapBytes New value of property unpackSwapBytes. + */ + public void setUnpackSwapBytes(boolean unpackSwapBytes) { + + this.unpackSwapBytes = unpackSwapBytes; + } + + /** + * Getter for property unpackSkipImages. + * @return Value of property unpackSkipImages. + */ + public int getUnpackSkipImages() { + + return this.unpackSkipImages; + } + + /** + * Setter for property unpackSkipImages. + * @param unpackSkipImages New value of property unpackSkipImages. + */ + public void setUnpackSkipImages(int unpackSkipImages) { + + this.unpackSkipImages = unpackSkipImages; + } + + /** + * Getter for property unpackImageHeight. + * @return Value of property unpackImageHeight. + */ + public int getUnpackImageHeight() { + + return this.unpackImageHeight; + } + + /** + * Setter for property unpackImageHeight. + * @param unpackImageHeight New value of property unpackImageHeight. + */ + public void setUnpackImageHeight(int unpackImageHeight) { + + this.unpackImageHeight = unpackImageHeight; + } + + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ScaleInternal.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ScaleInternal.java new file mode 100644 index 000000000..f0bb7fb33 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ScaleInternal.java @@ -0,0 +1,2447 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLU; +import java.nio.*; +import com.jogamp.opengl.impl.InternalBufferUtil; + +/** + * + * @author Administrator + */ +public class ScaleInternal { + + public static final float UINT_MAX = (float)(0x00000000FFFFFFFF); + + public static void scale_internal( int components, int widthin, int heightin, + ShortBuffer datain, int widthout, int heightout, ShortBuffer dataout ) { + float x, lowx, highx, convx, halfconvx; + float y, lowy, highy, convy, halfconvy; + float xpercent, ypercent; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, yint, xint, xindex, yindex; + int temp; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage( components, widthin, heightin, datain, dataout ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + halfconvx = convx / 2; + halfconvy = convy / 2; + for( i = 0; i < heightout; i++ ) { + y = convy * ( i + 0.5f ); + if( heightin > heightout ) { + highy = y + halfconvy; + lowy = y - halfconvy; + } else { + highy = y + 0.5f; + lowy = y - 0.5f; + } + for( j = 0; j < widthout; j++ ) { + x = convx * ( j + 0.5f ); + if( widthin > widthout ) { + highx = x + halfconvx; + lowx = x - halfconvx; + } else { + highx = x + 0.5f; + lowx = x - 0.5f; + } + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + area = 0.0f; + + y = lowy; + yint = (int)Math.floor( y ); + while( y < highy ) { + yindex = ( yint + heightin ) % heightin; + if( highy < yint + 1 ) { + ypercent = highy - y; + } else { + ypercent = yint + 1 - y; + } + + x = lowx; + xint = (int)Math.floor( x ); + + while( x < highx ) { + xindex = ( xint + widthin ) % widthin; + if( highx < xint + 1 ) { + xpercent = highx -x; + } else { + xpercent = xint + 1 - x; + } + + percent = xpercent * ypercent; + area += percent; + temp = ( xindex + ( yindex * widthin) ) * components; + for( k = 0; k < components; k++ ) { + totals[k] += datain.get( temp + k ) * percent; + } + + xint++; + x = xint; + } + yint++; + y = yint; + } + + temp = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + // totals[] should be rounded in the case of enlarging an RGB + // ramp when the type is 332 or 4444 + dataout.put( temp + k, (short)((totals[k] + 0.5f) / area) ); + } + } + } + } + + public static void scale_internal_ubyte( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + ByteBuffer dataout, int element_size, int ysize, int group_size ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_ubyte( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * y_percent; + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * y_percent; + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + float f = 0.0f; + datain.position( left ); + f = ( 0x000000FF & datain.get() ) * ( 1.0f - lowx_float ); + datain.position( right ); + f += ( 0x000000FF & datain.get() ) * highx_float; + totals[k] += f; + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * x_percent; + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * y_percent; + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ); + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (byte)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_byte( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + ByteBuffer dataout, int element_size, int ysize, + int group_size ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_byte( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * y_percent; + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * y_percent; + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + float f = 0.0f; + datain.position( left ); + f = datain.get() * ( 1 - lowx_float ); + datain.position( right ); + f += datain.get() * highx_float; + totals[k] += f; + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * x_percent; + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * y_percent; + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get(); + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (byte)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_ushort( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + ShortBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_ushort( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & ((int)Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort() ) * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & ((int)Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * y_percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort()) * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & (Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort()) * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort() ) * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * y_percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort()) * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort()) * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + float f = (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES(datain.getShort())) * ( 1 - lowx_float ); + datain.position( right ); + f += ((0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES(datain.getShort())) * highx_float); + totals[k] += f; + } else { + datain.position( left ); + float f = ((0x0000FFFF & datain.getShort()) * ( 1 - lowx_float )); + datain.position( right ); + f += ((0x0000FFFF & datain.getShort()) * highx_float); + totals[k] += f; + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() )) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * x_percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() )) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * y_percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort())); + } else { + totals[k] += (0x0000FFFF & datain.getShort()); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (short)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_short( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + ShortBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + int swapbuf; // unsigned buffer + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_short( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getShort() * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getShort() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * ( 1 - lowx_float ); + datain.position( right ); + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * highx_float; + } else { + datain.position( left ); + totals[k] += datain.getShort() * ( 1 - lowx_float ); + datain.position( right ); + totals[k] += datain.getShort() * highx_float; + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort()); + totals[k] += swapbuf * x_percent; + } else { + totals[k] += datain.getShort() * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getShort() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf; + } else { + totals[k] += datain.getShort(); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (short)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_uint( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + IntBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_uint( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * y_percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * y_percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + totals[k] += ((0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES(datain.getInt())) * ( 1 - lowx_float )); + datain.position( right ); + totals[k] += ((0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES(datain.getInt())) * highx_float); + } else { + datain.position( left ); + totals[k] += ((0x00000000FFFFFFFF & datain.getInt()) * ( 1 - lowx_float )); + datain.position( right ); + totals[k] += ((0x00000000FFFFFFFF & datain.getInt()) * highx_float); + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * x_percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * y_percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + long tempInt0 = ( 0xFFFFFFFFL & datain.getInt( temp_index ) ); + datain.position( temp_index ); + long tempInt1 = ( 0xFFFFFFFFL & datain.getInt() ); + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())); + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + float value = 0.0f; + for( k = 0; k < components; k++ ) { + value = totals[k] / area; + dataout.position( outindex + k ); + if( value >= UINT_MAX ) { + dataout.put( (int)value ); + } else { + dataout.put( (int)(totals[k] / area) ); + } + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_int( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + IntBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + long swapbuf; // unsigned buffer + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_int( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getInt() * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getInt() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * ( 1 - lowx_float ); + datain.position( right ); + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * highx_float; + } else { + datain.position( left ); + totals[k] += (datain.getInt() * ( 1 - lowx_float )); + datain.position( right ); + totals[k] += (datain.getInt() * highx_float); + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * x_percent; + } else { + totals[k] += datain.getInt() * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getInt() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf; + } else { + totals[k] += datain.getInt(); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (int)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_float( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + FloatBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + float swapbuf; // unsigned buffer + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_float( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getFloat() * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getFloat() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * ( 1 - lowx_float ); + datain.position( right ); + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * highx_float; + } else { + datain.position( left ); + totals[k] += (datain.getFloat() * ( 1 - lowx_float )); + datain.position( right ); + totals[k] += (datain.getFloat() * highx_float); + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * x_percent; + } else { + totals[k] += datain.getFloat() * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getFloat() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf; + } else { + totals[k] += datain.getFloat(); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scaleInternalPackedPixel( int components, Extract extract, + int widthIn, int heightIn, ByteBuffer dataIn, int widthOut, + int heightOut, ByteBuffer dataOut, int pixelSizeInBytes, + int rowSizeInBytes, boolean isSwap ) { + float x, convx; + float y, convy; + float percent; + + // max components in a format is 4, so + float[] totals = new float[4]; + float[] extractTotals = new float[4]; + float[] extractMoreTotals = new float[4]; + float[] shoveTotals = new float[4]; + + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outIndex = 0; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( widthIn == widthOut * 2 && heightIn == heightOut * 2 ) { + HalveImage.halveImagePackedPixel( components, extract, widthIn, heightIn, dataIn, dataOut, + pixelSizeInBytes, rowSizeInBytes, isSwap ); + return; + } + convy = (float)heightIn / (float)heightOut; + convx = (float)widthIn / (float)widthOut; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convx_float; + + for( i = 0; i < heightOut; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightIn) + highy_int = heightIn - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthOut; j++ ) { + // ok now apply box filter to box that goes from( lowx, lowy ) + // to ( highx, highy ) on input data into this pixel on output data + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // calculate that value for pixels in the 1st row + xindex = lowx_int * pixelSizeInBytes; + if( (highy_int > lowy_int) && (highx_int > lowx_int) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * rowSizeInBytes; + percent = y_percent * ( 1 - lowx_float ); + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += pixelSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * y_percent; + } + } + temp += pixelSizeInBytes; + right = temp; + percent = y_percent * highx_float; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + // calculate the value for pixels in the last row + + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += pixelSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * y_percent; + } + } + temp += pixelSizeInBytes; + percent = y_percent * highx_float; + dataIn.position( temp ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + + // calculate the value for pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += rowSizeInBytes; + right += rowSizeInBytes; + dataIn.position( left ); + extract.extract( isSwap, dataIn, extractTotals ); + dataIn.position( right ); + extract.extract( isSwap, dataIn, extractMoreTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += ( extractTotals[k] * ( 1 - lowx_float ) + extractMoreTotals[k] * highx_float ); + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float ) * x_percent; + temp = xindex + lowy_int * rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * x_percent; + } + } + percent = x_percent * highy_float; + temp += rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + lowy_int * rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += pixelSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * y_percent; + } + } + temp += pixelSizeInBytes; + percent = y_percent * highx_float; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + lowy_int * rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + } + + // this is for the pixels in the body + temp0 = xindex + pixelSizeInBytes + ( lowy_int + 1 ) * rowSizeInBytes; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + temp += pixelSizeInBytes; + } + temp0 += rowSizeInBytes; + } + + outIndex = ( j + ( i * widthOut ) ); + for( k = 0; k < components; k++ ) { + shoveTotals[k] = totals[k] / area; + } + extract.shove( shoveTotals, outIndex, dataOut ); + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthIn - 1) { + int delta = (highx_int - widthIn + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + assert( outIndex == ( widthOut * heightOut - 1) ); + } + + public static void scaleInternal3D( int components, int widthIn, int heightIn, + int depthIn, ShortBuffer dataIn, int widthOut, int heightOut, + int depthOut, ShortBuffer dataOut ) { + float x, lowx, highx, convx, halfconvx; + float y, lowy, highy, convy, halfconvy; + float z, lowz, highz, convz, halfconvz; + float xpercent, ypercent, zpercent; + float percent; + // max compnents in a format is 4 + float[] totals = new float[4]; + float volume; + int i, j, d, k, zint, yint, xint, xindex, yindex, zindex; + int temp; + + lowy = highy = lowx = highx = 0.0f; + + convz = (float)depthIn / depthOut; + convy = (float)heightIn / heightOut; + convx = (float)widthIn / widthOut; + halfconvz = convz / 2.0f; + halfconvy = convy / 2.0f; + halfconvx = convx / 2.0f; + for( d = 0; d < depthOut; d++ ) { + z = convz * ( d + 0.5f ); + if( depthIn > depthOut ) { + highz = z + halfconvz; + lowz = z - halfconvz; + } else { + highz = z + 0.5f; + lowz = z - 0.5f; + } + for( i = 0; i < heightOut; i++ ) { + y = convy * ( i + 0.5f ); + if( heightIn > heightOut ) { + highz = y + halfconvy; + lowz = y - halfconvy; + } else { + highz = y + 0.5f; + lowz = y - 0.5f; + } + for( j = 0; j < widthOut; j++ ) { + x = convx * ( j + 0.5f ); + if( depthIn > depthOut ) { + highz = x + halfconvx; + lowz = x - halfconvx; + } else { + highz = x + 0.5f; + lowz = x - 0.5f; + } + + // Ok, now apply box filter to box that goes from ( lowx, lowy, lowz ) + // to ( highx, highy, highz ) on input data into this pixel on output data + + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + volume = 0.0f; + + z = lowz; + zint = (int)(Math.floor( z ) ); + while( z < highz ) { + zindex = ( zint + depthIn ) % depthIn; + if( highz < zint + 1 ) { + zpercent = highz - z; + } else { + zpercent = zint + 1 - z; + } + + y = lowy; + yint = (int)(Math.floor( y ) ); + while( y < highy ) { + yindex = ( yint + heightIn ) % heightIn; + if( highy < yint + 1 ) { + ypercent = highy - y; + } else { + ypercent = yint + 1 - y; + } + + x = lowx; + xint = (int)(Math.floor( x ) ); + + while( x < highx ) { + xindex = (xint + widthIn ) % widthIn; + if( highx < xint + 1 ) { + xpercent = highx - x; + } else { + xpercent = xint + 1 - x; + } + + percent = xpercent * ypercent * zpercent; + volume += percent; + + temp = (xindex + ( yindex *widthIn) + (zindex * widthIn *heightIn)) * components; + for( k = 0; k < components; k++ ) { + assert( 0 <= (temp+k) && (temp+k) < (widthIn * heightIn * depthIn * components) ); + totals[k] += dataIn.get( temp + k ) * percent; + } + xint++; + x = xint; + } // while x + yint++; + y = yint; + } // while y + zint++; + z = zint; + } // while z + + temp = ( j + ( i * widthOut ) + (d * widthOut * heightOut ) ) * components; + for( k = 0; k < components; k++ ) { + // totals should be rounded in the case of enlarging an rgb ramp when the type is 332 or 4444 + assert( 0 <= ( temp + k ) && ( temp + k ) < (widthOut * heightOut* depthOut * components) ); + dataOut.put( temp + k, (short)((totals[k] + 0.5f) / volume ) ); + } + } + } + } + } + + public static int gluScaleImage3D( GL gl, int format, int widthIn, int heightIn, + int depthIn, int typeIn, ByteBuffer dataIn, int widthOut, int heightOut, + int depthOut, int typeOut, ByteBuffer dataOut ) { + int components; + ShortBuffer beforeImage, afterImage; + PixelStorageModes psm = new PixelStorageModes(); + + if( widthIn == 0 || heightIn == 0 || depthIn == 0 || + widthOut == 0 || heightOut == 0 || depthOut == 0 ) { + return( 0 ); + } + + if( widthIn < 0 || heightIn < 0 || depthIn < 0 || + widthOut < 0 || heightOut < 0 || depthOut < 0 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + if( !Mipmap.legalFormat(format) || !Mipmap.legalType(typeIn) || + !Mipmap.legalType(typeOut) || typeIn == GL2.GL_BITMAP || + typeOut == GL2.GL_BITMAP ) { + return( GLU.GLU_INVALID_ENUM ); + } + + if( !Mipmap.isLegalFormatForPackedPixelType( format, typeIn ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + + if( !Mipmap.isLegalFormatForPackedPixelType( format, typeOut ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + + try { + beforeImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.imageSize3D( widthIn, + heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) )).asShortBuffer(); + afterImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.imageSize3D( widthIn, + heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) )).asShortBuffer(); + } catch( OutOfMemoryError err ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + Mipmap.retrieveStoreModes3D( gl, psm ); + + Image.fillImage3D( psm, widthIn, heightIn, depthIn, format, typeIn, + Mipmap.is_index( format ), dataIn, beforeImage ); + components = Mipmap.elements_per_group( format, 0 ); + ScaleInternal.scaleInternal3D( components, widthIn, heightIn, depthIn, + beforeImage, widthOut, heightOut, depthOut, afterImage ); + Image.emptyImage3D( psm, widthOut, heightOut, depthOut, format, typeOut, + Mipmap.is_index( format ), afterImage, dataOut ); + + return( 0 ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Type_Widget.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Type_Widget.java new file mode 100644 index 000000000..b329840ef --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Type_Widget.java @@ -0,0 +1,224 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Type_Widget { + + ByteBuffer buffer; + + /** Creates a new instance of Type_Widget */ + public Type_Widget() { + buffer = ByteBuffer.allocateDirect( 4 ); + } + + public void setUB0( byte b ) { + buffer.position( 0 ); + buffer.put( b ); + } + + public byte getUB0() { + buffer.position( 0 ); + return( buffer.get() ); + } + + public void setUB1( byte b ) { + buffer.position( 1 ); + buffer.put( b ); + } + + public byte getUB1() { + buffer.position( 1 ); + return( buffer.get() ); + } + + public void setUB2( byte b ) { + buffer.position( 2 ); + buffer.put( b ); + } + + public byte getUB2() { + buffer.position( 2 ); + return( buffer.get() ); + } + + public void setUB3( byte b ) { + buffer.position( 3 ); + buffer.put( b ); + } + + public byte getUB3() { + buffer.position( 3 ); + return( buffer.get() ); + } + + public void setUS0( short s ) { + buffer.position( 0 ); + buffer.putShort( s ); + } + + public short getUS0() { + buffer.position( 0 ); + return( buffer.getShort() ); + } + + public void setUS1( short s ) { + buffer.position( 2 ); + buffer.putShort( s ); + } + + public short getUS1() { + buffer.position( 2 ); + return( buffer.getShort() ); + } + + public void setUI( int i ) { + buffer.position( 0 ); + buffer.putInt( i ); + } + + public int getUI() { + buffer.position( 0 ); + return( buffer.getInt() ); + } + + public void setB0( byte b ) { + buffer.position( 0 ); + buffer.put( b ); + } + + public byte getB0() { + buffer.position( 0 ); + return( buffer.get() ); + } + + public void setB1( byte b ) { + buffer.position( 1 ); + buffer.put( b ); + } + + public byte getB1() { + buffer.position( 1 ); + return( buffer.get() ); + } + + public void setB2( byte b ) { + buffer.position( 2 ); + buffer.put( b ); + } + + public byte getB2() { + buffer.position( 2 ); + return( buffer.get() ); + } + + public void setB3( byte b ) { + buffer.position( 3 ); + buffer.put( b ); + } + + public byte getB3() { + buffer.position( 3 ); + return( buffer.get() ); + } + + public void setS0( short s ) { + buffer.position( 0 ); + buffer.putShort( s ); + } + + public short getS0() { + buffer.position( 0 ); + return( buffer.getShort() ); + } + + public void setS1( short s ) { + buffer.position( 2 ); + buffer.putShort( s ); + } + + public short getS1() { + buffer.position( 2 ); + return( buffer.getShort() ); + } + + public void setI( int i ) { + buffer.position( 0 ); + buffer.putInt( i ); + } + + public int getI() { + buffer.position( 0 ); + return( buffer.getInt() ); + } + + public void setF( float f ) { + buffer.position( 0 ); + buffer.putFloat( f ); + } + + public float getF() { + buffer.position( 0 ); + return( buffer.getFloat() ); + } + + public ByteBuffer getBuffer() { + buffer.rewind(); + return( buffer ); + } + + public static void main( String args[] ) { + Type_Widget t = new Type_Widget(); + t.setI( 1000000 ); + + System.out.println("int: " + Integer.toHexString( t.getI() ) ); + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Arc.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Arc.java new file mode 100755 index 000000000..9ee2494a1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Arc.java @@ -0,0 +1,258 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +*/ + +/** + * Trimming arc + * @author Tomas Hrasky + * + */ +public class Arc { + /** + * Corresponding picewise-linear arc + */ + public PwlArc pwlArc; + + /** + * Arc type + */ + private long type; + + /** + * Arc link in linked list + */ + public Arc link; + + /** + * Previous arc + */ + Arc prev; + + /** + * Next arc + */ + Arc next; + + /** + * Corresponding berizer type arc + */ + private BezierArc bezierArc; + + /** + * Makes new arc at specified side + * + * @param side + * which side doeas this arc form + */ + public Arc(int side) { + bezierArc = null; + pwlArc = null; + type = 0; + setside(side); + // nuid=_nuid + } + + /** + * Sets side the arc is at + * + * @param side + * arc side + */ + private void setside(int side) { + // DONE + clearside(); + type |= side << 8; + } + + /** + * Unsets side + */ + private void clearside() { + // DONE + type &= ~(0x7 << 8); + } + + // this one replaces enum arc_side + /** + * Side not specified + */ + public static final int ARC_NONE = 0; + + /** + * Arc on right + */ + public static final int ARC_RIGHT = 1; + + /** + * Arc on top + */ + public static final int ARC_TOP = 2; + + /** + * Arc on left + */ + public static final int ARC_LEFT = 3; + + /** + * Arc on bottom + */ + public static final int ARC_BOTTOM = 4; + + /** + * Bezier type flag + */ + private static final long BEZIER_TAG = 1 << 13; + + /** + * Arc type flag + */ + private static final long ARC_TAG = 1 << 3; + + /** + * Tail type tag + */ + private static final long TAIL_TAG = 1 << 6; + + /** + * Appends arc to the list + * + * @param jarc + * arc to be append + * @return this + */ + public Arc append(Arc jarc) { + // DONE + if (jarc != null) { + next = jarc.next; + prev = jarc; + next.prev = this; + prev.next = this; + } else { + next = this; + prev = this; + } + + return this; + } + + /** + * Unused + * + * @return true + */ + public boolean check() { + return true; + } + + /** + * Sets bezier type flag + */ + public void setbezier() { + // DONE + type |= BEZIER_TAG; + + } + + /** + * Returns tail of linked list coords + * + * @return tail coords + */ + public float[] tail() { + // DONE + return pwlArc.pts[0].param; + } + + /** + * Returns head of linked list coords + * + * @return head coords + */ + public float[] head() { + // DONE + return next.pwlArc.pts[0].param; + } + + /** + * Returns whether arc is marked with arc_tag + * + * @return is arc marked with arc_tag + */ + public boolean ismarked() { + // DONE + return ((type & ARC_TAG) > 0) ? true : false; + } + + /** + * Cleans arc_tag flag + */ + public void clearmark() { + // DONE + type &= (~ARC_TAG); + } + + /** + * Sets arc_tag flag + */ + public void setmark() { + // DONE + type |= ARC_TAG; + } + + /** + * sets tail tag + */ + public void setitail() { + // DONE + type |= TAIL_TAG; + } + + /** + * Returns whether arc is marked tail + * + * @return is tail + */ + public boolean getitail() { + return false; + } + + /** + * Unsets tail tag + */ + public void clearitail() { + // DONE + type &= (~TAIL_TAG); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcSdirSorter.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcSdirSorter.java new file mode 100755 index 000000000..3955e3176 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcSdirSorter.java @@ -0,0 +1,63 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for sorting list of Arcs + * @author Tomas Hrasky + * + */ +public class ArcSdirSorter { + + /** + * Makes new ArcSdirSorter with Subdivider + * @param subdivider subdivider + */ + public ArcSdirSorter(Subdivider subdivider) { + //TODO + // System.out.println("TODO arcsdirsorter.constructor"); + } + + /** + * Sorts list of arcs + * @param list arc list to be sorted + * @param count size of list + */ + public void qsort(CArrayOfArcs list, int count) { + // TODO + // System.out.println("TODO arcsdirsorter.qsort"); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTdirSorter.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTdirSorter.java new file mode 100755 index 000000000..098ba97b7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTdirSorter.java @@ -0,0 +1,60 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for sorting list of Arcs + * @author Tomas Hrasky + * + */ +public class ArcTdirSorter { + /** + * Makes new ArcSdirSorter with Subdivider + * @param subdivider subdivider + */ + public ArcTdirSorter(Subdivider subdivider) { + // TODO Auto-generated constructor stub + // System.out.println("TODO arcTsorter.konstruktor"); + } + /** + * Sorts list of arcs + * @param list arc list to be sorted + * @param count size of list + */ + public void qsort(CArrayOfArcs list, int count) { + // TODO Auto-generated method stub + // System.out.println("TODO arcTsorter.qsort"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTesselator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTesselator.java new file mode 100755 index 000000000..edfb8905f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTesselator.java @@ -0,0 +1,90 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for arc tesselation + * @author Tomas Hrasky + * + */ +public class ArcTesselator { + + /** + * Makes given arc an bezier arc + * @param arc arc to work with + * @param s1 minimum s param + * @param s2 maximum s param + * @param t1 minimum t param + * @param t2 maximum s param + */ + public void bezier(Arc arc, float s1, float s2, float t1, float t2) { + // DONE + TrimVertex[] p = new TrimVertex[2]; + p[0] = new TrimVertex(); + p[1] = new TrimVertex(); + arc.pwlArc = new PwlArc(2, p); + p[0].param[0] = s1; + p[0].param[1] = s2; + p[1].param[0] = t1; + p[1].param[1] = t2; + arc.setbezier(); + } + + /** + * Empty method + * @param newright arc to work with + * @param s first tail + * @param t2 second tail + * @param t1 third tail + * @param f stepsize + */ + public void pwl_right(Arc newright, float s, float t1, float t2, float f) { + // TODO Auto-generated method stub + // System.out.println("TODO arctesselator.pwl_right"); + } + + /** + * Empty method + * @param newright arc to work with + * @param s first tail + * @param t2 second tail + * @param t1 third tail + * @param f stepsize + */ + public void pwl_left(Arc newright, float s, float t2, float t1, float f) { + // TODO Auto-generated method stub + // System.out.println("TODO arctesselator.pwl_left"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Backend.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Backend.java new file mode 100755 index 000000000..39097720c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Backend.java @@ -0,0 +1,217 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class responsible for rendering + * @author Tomas Hrasky + * + */ +public abstract class Backend { + + /** + * Fill surface + */ + public static final int N_MESHFILL = 0; + + /** + * Draw surface as wire model + */ + public static final int N_MESHLINE = 1; + + /** + * Draw surface with points + */ + public static final int N_MESHPOINT = 2; + + /** + * Object rendering curves + */ + protected CurveEvaluator curveEvaluator; + + /** + * Object rendering surfaces + */ + protected SurfaceEvaluator surfaceEvaluator; + + /** + * Makes new backend + */ + public Backend() { + // curveEvaluator = new OpenGLCurveEvaluator(); + // surfaceEvaluator = new OpenGLSurfaceEvaluator(); + } + + /** + * Begin a curve + */ + public void bgncurv() { + // DONE + curveEvaluator.bgnmap1f(); + + } + + /** + * End a curve + */ + public void endcurv() { + // DONE + curveEvaluator.endmap1f(); + + } + + /** + * Make cuve with given parameters + * @param type curve type + * @param ps control points + * @param stride control points coordinates number + * @param order order of curve + * @param ulo smallest u + * @param uhi highest u + */ + public void curvpts(int type, CArrayOfFloats ps, int stride, int order, + float ulo, float uhi) { + // DONE + curveEvaluator.map1f(type, ulo, uhi, stride, order, ps); + curveEvaluator.enable(type); + } + + /** + * Draw curve + * @param u1 smallest u + * @param u2 highest u + * @param nu number of pieces + */ + public void curvgrid(float u1, float u2, int nu) { + // DONE + curveEvaluator.mapgrid1f(nu, u1, u2); + + } + + /** + * Evaluates curve mesh + * @param from low param + * @param n step + */ + public void curvmesh(int from, int n) { + // DONE + curveEvaluator.mapmesh1f(N_MESHFILL, from, from + n); + } + + /** + * Begin surface + * @param wiretris use triangles + * @param wirequads use quads + */ + public void bgnsurf(int wiretris, int wirequads) { + // DONE + surfaceEvaluator.bgnmap2f(); + + if (wiretris > 0) + surfaceEvaluator.polymode(NurbsConsts.N_MESHLINE); + else + surfaceEvaluator.polymode(NurbsConsts.N_MESHFILL); + } + + /** + * End surface + */ + public void endsurf() { + // DONE + surfaceEvaluator.endmap2f(); + } + + /** + * Empty method + * @param ulo low u param + * @param uhi hig u param + * @param vlo low v param + * @param vhi high v param + */ + public void patch(float ulo, float uhi, float vlo, float vhi) { + // DONE + surfaceEvaluator.domain2f(ulo, uhi, vlo, vhi); + } + + /** + * Draw surface + * @param u0 lowest u + * @param u1 highest u + * @param nu number of pieces in u direction + * @param v0 lowest v + * @param v1 highest v + * @param nv number of pieces in v direction + */ + public void surfgrid(float u0, float u1, int nu, float v0, float v1, int nv) { + // DONE + surfaceEvaluator.mapgrid2f(nu, u0, u1, nv, v0, v1); + + } + + /** + * Evaluates surface mesh + * @param u u param + * @param v v param + * @param n step in u direction + * @param m step in v direction + */ + public void surfmesh(int u, int v, int n, int m) { + // System.out.println("TODO backend.surfmesh wireframequads"); + // TODO wireframequads + surfaceEvaluator.mapmesh2f(NurbsConsts.N_MESHFILL, u, u + n, v, v + m); + } + + /** + * Make surface + * @param type surface type + * @param pts control points + * @param ustride control points coordinates in u direction + * @param vstride control points coordinates in v direction + * @param uorder surface order in u direction + * @param vorder surface order in v direction + * @param ulo lowest u + * @param uhi hightest u + * @param vlo lowest v + * @param vhi hightest v + */ + public void surfpts(int type, CArrayOfFloats pts, int ustride, int vstride, + int uorder, int vorder, float ulo, float uhi, float vlo, float vhi) { + // DONE + surfaceEvaluator.map2f(type, ulo, uhi, ustride, uorder, vlo, vhi, + vstride, vorder, pts); + surfaceEvaluator.enable(type); + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/BezierArc.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/BezierArc.java new file mode 100755 index 000000000..d9b390b67 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/BezierArc.java @@ -0,0 +1,44 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomas Hrasky + * + */ +public class BezierArc { + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Bin.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Bin.java new file mode 100755 index 000000000..61316f348 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Bin.java @@ -0,0 +1,155 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding trimming arcs + * @author Tomas Hrasky + * + */ +public class Bin { + + /** + * Head of linked list of arcs + */ + private Arc head; + + /** + * Current arc + */ + private Arc current; + + /** + * Indicates whether there are any Arcs in linked list + * @return true if there are any Arcs in linked list + */ + public boolean isnonempty() { + // DONE + return this.head != null ? true : false; + } + + /** + * Adds and arc to linked list + * @param jarc added arc + */ + public void addarc(Arc jarc) { + // DONE + // if (head == null) + // head = jarc; + // else { + jarc.link = head; + head = jarc; + // } + + } + + /** + * Returns number of arcs in linked list + * @return number of arcs + */ + public int numarcs() { + // DONE + int count = 0; + for (Arc jarc = firstarc(); jarc != null; jarc = nextarc()) + count++; + return count; + } + + /** + * Removes first arc in list + * @return new linked list head + */ + public Arc removearc() { + // DONE + Arc jarc = head; + if (jarc != null) + head = jarc.link; + return jarc; + + } + + /** + * Consolidates linked list + */ + public void adopt() { + // DONE + markall(); + + Arc orphan; + while ((orphan = removearc()) != null) { + for (Arc parent = orphan.next; !parent.equals(orphan); parent = parent.next) { + if (!parent.ismarked()) { + orphan.link = parent.link; + parent.link = orphan; + orphan.clearmark(); + break; + } + } + } + + } + + /** + * Marks all arc in linked list + */ + private void markall() { + // DONE + for (Arc jarc = firstarc(); jarc != null; jarc = nextarc()) + jarc.setmark(); + } + + /** + * Returns first arc in linked list + * @return first arc in linked list + */ + private Arc firstarc() { + // DONE + current = head; + return nextarc(); + } + + /** + * Returns next arc in linked list + * @return next arc + * + */ + private Arc nextarc() { + // DONE + Arc jarc = current; + if (jarc != null) + current = jarc.link; + return jarc; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Breakpt.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Breakpt.java new file mode 100755 index 000000000..b5b88ad96 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Breakpt.java @@ -0,0 +1,59 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding break point parameters + * + * @author Tomas Hrasky + * + */ +public class Breakpt { + + /** + * Breakpoint multiplicity + */ + public int multi; + + /** + * Breakpint value + */ + public float value; + + /** + * Breakpoint deficit (how many times it has to be added) + */ + public int def; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfArcs.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfArcs.java new file mode 100755 index 000000000..0646e1d9f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfArcs.java @@ -0,0 +1,194 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfArcs { + /** + * Underlaying array + */ + private Arc[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Don't check for array borders? + */ + private boolean noCheck = true; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfArcs(Arc[] array, int pointer) { + this.array = array; + // this.pointer=pointer; + setPointer(pointer); + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfArcs(CArrayOfArcs carray) { + this.array = carray.array; + // this.pointer=carray.pointer; + setPointer(carray.pointer); + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param ctlarray + * underlaying array + */ + public CArrayOfArcs(Arc[] ctlarray) { + this.array = ctlarray; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Arc get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + // pointer++; + setPointer(pointer + 1); + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Arc f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Arc get(int i) { + return array[i]; + } + + /** + * Returns array element at specified index relatively to pointer + * + * @param i + * relative index + * @return element at relative index + */ + public Arc getRelative(int i) { + return array[pointer + i]; + } + + /** + * Sets value of element at specified index relatively to pointer + * + * @param i + * relative index + * @param value + * value to be set + */ + public void setRelative(int i, Arc value) { + array[pointer + i] = value; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + // pointer-=i; + setPointer(pointer - i); + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + if (!noCheck && pointer > array.length) + throw new IllegalArgumentException("Pointer " + pointer + + " out of bounds " + array.length); + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + // pointer+=i; + setPointer(pointer + i); + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + // pointer--; + setPointer(pointer - 1); + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public Arc[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(Arc[] array) { + this.array = array; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfBreakpts.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfBreakpts.java new file mode 100755 index 000000000..e47fdf966 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfBreakpts.java @@ -0,0 +1,130 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfBreakpts { + /** + * Underlaying array + */ + private Breakpt[] pole; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfBreakpts(Breakpt[] array, int pointer) { + this.pole = array; + this.pointer = pointer; + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfBreakpts(CArrayOfBreakpts carray) { + this.pole = carray.pole; + this.pointer = carray.pointer; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Breakpt get() { + return pole[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + pointer++; + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Breakpt f) { + pole[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Breakpt get(int i) { + return pole[i]; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + pointer -= i; + + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + pointer += i; + + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + pointer--; + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfFloats.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfFloats.java new file mode 100755 index 000000000..60cef9919 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfFloats.java @@ -0,0 +1,195 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfFloats { + + /** + * Underlaying array + */ + private float[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Don't check for array borders? + */ + private boolean noCheck = true; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfFloats(float[] array, int pointer) { + this.array = array; + // this.pointer=pointer; + setPointer(pointer); + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfFloats(CArrayOfFloats carray) { + this.array = carray.array; + // this.pointer=carray.pointer; + setPointer(carray.pointer); + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param ctlarray + * underlaying array + */ + public CArrayOfFloats(float[] ctlarray) { + this.array = ctlarray; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public float get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + // pointer++; + setPointer(pointer + 1); + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(float f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public float get(int i) { + return array[i]; + } + + /** + * Returns array element at specified index relatively to pointer + * + * @param i + * relative index + * @return element at relative index + */ + public float getRelative(int i) { + return array[pointer + i]; + } + + /** + * Sets value of element at specified index relatively to pointer + * + * @param i + * relative index + * @param value + * value to be set + */ + public void setRelative(int i, float value) { + array[pointer + i] = value; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + // pointer-=i; + setPointer(pointer - i); + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + if (!noCheck && pointer > array.length) + throw new IllegalArgumentException("Pointer " + pointer + + " out of bounds " + array.length); + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + // pointer+=i; + setPointer(pointer + i); + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + // pointer--; + setPointer(pointer - 1); + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public float[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(float[] array) { + this.array = array; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java new file mode 100755 index 000000000..ef16a8204 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java @@ -0,0 +1,160 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfQuiltspecs { + /** + * Underlaying array + */ + private Quiltspec[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfQuiltspecs(Quiltspec[] array, int pointer) { + this.array = array; + this.pointer = pointer; + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfQuiltspecs(CArrayOfQuiltspecs carray) { + this.array = carray.array; + this.pointer = carray.pointer; + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param array + * underlaying array + */ + public CArrayOfQuiltspecs(Quiltspec[] array) { + this.array = array; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Quiltspec get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + pointer++; + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Quiltspec f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Quiltspec get(int i) { + return array[i]; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + pointer -= i; + + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + pointer += i; + + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + pointer--; + + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public Quiltspec[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(Quiltspec[] array) { + this.array = array; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curve.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curve.java new file mode 100755 index 000000000..fb1a5acea --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curve.java @@ -0,0 +1,238 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding curve definition + * @author Tomáš Hráský + * + */ +public class Curve { + + /** + * Maximum coordinates per control point + */ + private static final int MAXCOORDS = 5; + + /** + * Max curve order + */ + private static final int MAXORDER = 24; + + /** + * Next curve in linked list + */ + public Curve next; + + /** + * OpenGL maps + */ + private Mapdesc mapdesc; + + /** + * Does the curve need sampling + */ + private boolean needsSampling; + + /** + * Culling + */ + private int cullval; + + /** + * Number of coords + */ + private int stride; + + /** + * Curve order + */ + private int order; + + /** + * Holds conversion range borders + */ + private float[] range; + + /** + * Subdivision stepsize + */ + public float stepsize; + + /** + * Minimal subdivision stepsize + */ + private float minstepsize; + + /** + * Sampling points + */ + float[] spts; + + /** + * Makes new Curve + * + * @param geo + * @param pta + * @param ptb + * @param c + * next curve in linked list + */ + public Curve(Quilt geo, float[] pta, float[] ptb, Curve c) { + + spts = new float[MAXORDER * MAXCOORDS]; + + mapdesc = geo.mapdesc; + + next = c; + needsSampling = mapdesc.isRangeSampling() ? true : false; + + cullval = mapdesc.isCulling() ? Subdivider.CULL_ACCEPT + : Subdivider.CULL_TRIVIAL_REJECT; + order = geo.qspec.get(0).order; + stride = MAXCOORDS; + + // CArrayOfFloats ps = geo.cpts; + CArrayOfFloats ps = new CArrayOfFloats(geo.cpts.getArray(), 0); + CArrayOfQuiltspecs qs = geo.qspec; + ps.raisePointerBy(qs.get().offset); + ps.raisePointerBy(qs.get().index * qs.get().order * qs.get().stride); + + if (needsSampling) { + mapdesc.xformSampling(ps, qs.get().order, qs.get().stride, spts, + stride); + } + if (cullval == Subdivider.CULL_ACCEPT) { + // System.out.println("TODO curve.Curve-cullval"); + // mapdesc.xformCulling(ps,qs.get().order,qs.get().stride,cpts,stride); + } + + range = new float[3]; + range[0] = qs.get().breakpoints[qs.get().index]; + range[1] = qs.get().breakpoints[qs.get().index + 1]; + range[2] = range[1] - range[0]; + // TODO it is necessary to solve problem with "this" pointer here + if (range[0] != pta[0]) { + // System.out.println("TODO curve.Curve-range0"); + // Curve lower=new Curve(this,pta,0); + // lower.next=next; + // this=lower; + } + if (range[1] != ptb[0]) { + // System.out.println("TODO curve.Curve-range1"); + // Curve lower=new Curve(this,ptb,0); + } + } + + /** + * Checks culling type + * @return Subdivider.CULL_ACCEPT + */ + public int cullCheck() { + if (cullval == Subdivider.CULL_ACCEPT) { + // System.out.println("TODO curve.cullval"); + // cullval=mapdesc.cullCheck(cpts,order,stride); + } + // TODO compute cullval and return the computed value + // return cullval; + return Subdivider.CULL_ACCEPT; + } + + /** + * Computes subdivision step size + */ + public void getStepSize() { + minstepsize = 0; + if (mapdesc.isConstantSampling()) { + setstepsize(mapdesc.maxrate); + } else if (mapdesc.isDomainSampling()) { + setstepsize(mapdesc.maxrate * range[2]); + } else { + assert (order <= MAXORDER); + + float tmp[][] = new float[MAXORDER][MAXCOORDS]; + + int tstride = (MAXORDER); + + int val = 0; + // mapdesc.project(spts,stride,tmp,tstride,order); + + // System.out.println("TODO curve.getsptepsize mapdesc.project"); + + if (val == 0) { + setstepsize(mapdesc.maxrate); + } else { + float t = mapdesc.getProperty(NurbsConsts.N_PIXEL_TOLERANCE); + if (mapdesc.isParametricDistanceSampling()) { + // System.out.println("TODO curve.getstepsize - parametric"); + } else if (mapdesc.isPathLengthSampling()) { + // System.out.println("TODO curve.getstepsize - pathlength"); + } else { + setstepsize(mapdesc.maxrate); + } + } + + } + + } + + /** + * Sets maximum subdivision step size + * @param max maximum subdivision step size + */ + private void setstepsize(float max) { + // DONE + stepsize = (max >= 1) ? (range[2] / max) : range[2]; + minstepsize = stepsize; + } + + /** + * Clamps the curve + */ + public void clamp() { + // DONE + if (stepsize < minstepsize) + stepsize = mapdesc.clampfactor * minstepsize; + } + + /** + * Tells whether curve needs subdivision + * + * @return curve needs subdivison + */ + public boolean needsSamplingSubdivision() { + return (stepsize < minstepsize); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CurveEvaluator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CurveEvaluator.java new file mode 100755 index 000000000..c27ffd4c4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CurveEvaluator.java @@ -0,0 +1,86 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class rendering curves with OpenGL + * @author Tomáš Hráský + * + */ +public interface CurveEvaluator { + /** + * Pushes eval bit + */ + public void bgnmap1f(); + + /** + * Pops all OpenGL attributes + */ + public void endmap1f() ; + + /** + * Initializes opengl evaluator + * @param type curve type + * @param ulo lowest u + * @param uhi highest u + * @param stride control point coords + * @param order curve order + * @param ps control points + */ + public void map1f(int type, float ulo, float uhi, int stride, int order, + CArrayOfFloats ps) ; + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) ; + + /** + * Calls glMapGrid1f + * @param nu steps + * @param u1 low u + * @param u2 high u + */ + public void mapgrid1f(int nu, float u1, float u2) ; + + /** + * Evaluates a curve using glEvalMesh1f + * @param style Backend.N_MESHFILL/N_MESHLINE/N_MESHPOINT + * @param from lowest param + * @param to highest param + */ + public void mapmesh1f(int style, int from, int to) ; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curvelist.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curvelist.java new file mode 100755 index 000000000..fc3018833 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curvelist.java @@ -0,0 +1,121 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for woking with linked list of curves + * @author Tomas Hrasky + * + */ +public class Curvelist { + + /** + * Head of linked list + */ + private Curve curve; + + /** + * Holds conversion range borders + */ + float[] range; + + /** + * Subdivision step size + */ + public float stepsize; + + /** + * Do curves need subdivision? + */ + private boolean needsSubdivision; + + /** + * Makes new instance on top of specified lis of Quilts + * @param qlist underlaying list of quilts + * @param pta range start + * @param ptb range end + */ + public Curvelist(Quilt qlist, float[] pta, float[] ptb) { + // DONE + curve = null; + range = new float[3]; + + for (Quilt q = qlist; q != null; q = q.next) { + curve = new Curve(q, pta, ptb, curve); + } + range[0] = pta[0]; + range[1] = ptb[0]; + range[2] = range[1] - range[0]; + } + + /** + * Compute step size + */ + public void getstepsize() { + // DONE + stepsize = range[2]; + Curve c; + for (c = curve; c != null; c = c.next) { + c.getStepSize(); + c.clamp(); + stepsize = (c.stepsize < stepsize) ? c.stepsize : stepsize; + if (c.needsSamplingSubdivision()) + break; + } + needsSubdivision = (c != null) ? true : false; + + } + + /** + * Indicates whether curves need subdivision + * @return curves need subdivision + */ + public boolean needsSamplingSubdivision() { + // DONE + return needsSubdivision; + } + + /** + * Checks for culling + * @return Subdivider.CULL_TRIVIAL_REJECT or Subdivider.CULL_ACCEPT + */ + public int cullCheck() { + // DONE + for (Curve c = curve; c != null; c = c.next) + if (c.cullCheck() == Subdivider.CULL_TRIVIAL_REJECT) + return Subdivider.CULL_TRIVIAL_REJECT; + return Subdivider.CULL_ACCEPT; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/DisplayList.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/DisplayList.java new file mode 100755 index 000000000..39a3a28f4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/DisplayList.java @@ -0,0 +1,56 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import java.lang.reflect.Method; + +/** + * Display list + * @author Tomas Hrasky + * + */ +public class DisplayList { + + /** + * Append action to the display list + * @param src source object to invoke method on + * @param m invoked method + * @param arg method argument + */ + public void append(Object src, Method m, Object arg) { + // TODO Auto-generated method stub + // System.out.println("TODO displaylist append"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Flist.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Flist.java new file mode 100755 index 000000000..00757ed7e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Flist.java @@ -0,0 +1,130 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import java.util.Arrays; + +/** + * List of breakpoints + * @author Tomas Hrasky + * + */ +public class Flist { + + /** + * Data elements end index + * + */ + public int end; + + /** + *Data elements start index + */ + public int start; + + /** + * Breakpoint values + */ + public float[] pts; + + /** + * Number of array fields + */ + private int npts; + + /** + * Grows list + * @param maxpts maximum desired size + */ + public void grow(int maxpts) { + // DONE + if (npts < maxpts) { + // npts=2*maxpts; + npts = maxpts; + pts = new float[npts]; + } + start = 0; + end = 0; + } + + /** + * Removes duplicate array elemnts + */ + public void filter() { + // INFO the aim of this method is to remove duplicates from array + + Arrays.sort(pts); + + start = 0; + + int j = 0; + + for (int i = 1; i < end; i++) { + if (pts[i] == pts[i - j - 1]) + j++; + pts[i - j] = pts[i]; + } + + end -= j; + + } + + /** + * Sets start and and to real start and end of array elements + * @param from start from + * @param to end at + */ + public void taper(float from, float to) { + // DONE + + while (pts[start] != from) { + start++; + } + + while (pts[end - 1] != to) { + end--; + } + + } + + /** + * Adds breakpoint value + * @param f value + */ + public void add(float f) { + //DONE + pts[end++] = f; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotspec.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotspec.java new file mode 100755 index 000000000..9251aa231 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotspec.java @@ -0,0 +1,557 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Knot vector specification + * + * @author Tomas Hrasky + * + */ +public class Knotspec { + + /** + * Begin of input knots + */ + public CArrayOfFloats inkbegin; + + /** + * End of input knots + */ + public CArrayOfFloats inkend; + + /** + * Stride before knot operations + */ + public int prestride; + + /** + * Curve order + */ + public int order; + + /** + * Next knot specification in linked list (used in surfaces) + */ + public Knotspec next; + + /** + * Last knot + */ + public CArrayOfFloats klast; + + /** + * First knot + */ + CArrayOfFloats kfirst; + + /** + * Beginning of breakpoints + */ + CArrayOfBreakpts bbegin; + + /** + * End of breakpoints + */ + CArrayOfBreakpts bend; + + /** + * Considered left end knot + */ + CArrayOfFloats kleft; + + /** + * Considered right end knot + */ + CArrayOfFloats kright; + + /** + * Offset before knot operations + */ + int preoffset; + + /** + * Control points array Length after knot operations + */ + int postwidth; + + /** + * Beginning of coeficients array + */ + private CArrayOfFloats sbegin; + + /** + * Beginning of output knots + */ + private CArrayOfFloats outkbegin; + + /** + * End of output knots + */ + private CArrayOfFloats outkend; + + /** + * Control points aray length before knot operations + */ + int prewidth; + + /** + * Offset after knot operations + */ + int postoffset; + + /** + * Number of control points' coordinates after knot operations + */ + public int poststride; + + /** + * Number of control points' coordinates + */ + public int ncoords; + + /** + * Tell whether knotspec has already benn transformed + */ + public boolean istransformed; + + /** + * Knotspec to be transformed + */ + public Knotspec kspectotrans; + + /** + * Finds knot border of knot insertion and required multiplicities + */ + public void preselect() { + // DONE + float kval; + + klast = new CArrayOfFloats(inkend); + klast.lessenPointerBy(order); + for (kval = klast.get(); klast.getPointer() != inkend.getPointer(); klast + .pp()) { + if (!Knotvector.identical(klast.get(), kval)) + break; + } + + kfirst = new CArrayOfFloats(inkbegin); + kfirst.raisePointerBy(order - 1); + for (kval = kfirst.get(); kfirst.getPointer() != inkend.getPointer(); kfirst + .pp()) { + if (!Knotvector.identical(kfirst.get(), kval)) + break; + } + + CArrayOfFloats k = new CArrayOfFloats(kfirst); + k.mm(); + + for (; k.getPointer() >= inkbegin.getPointer(); k.mm()) + if (!Knotvector.identical(kval, k.get())) + break; + k.pp(); + + Breakpt[] bbeginArray = new Breakpt[(klast.getPointer() - kfirst + .getPointer()) + 1]; + for (int i = 0; i < bbeginArray.length; i++) + bbeginArray[i] = new Breakpt(); + bbegin = new CArrayOfBreakpts(bbeginArray, 0); + bbegin.get().multi = kfirst.getPointer() - k.getPointer(); + bbegin.get().value = kval; + + bend = new CArrayOfBreakpts(bbegin); + kleft = new CArrayOfFloats(kfirst); + kright = new CArrayOfFloats(kfirst); + + } + + /** + * Perpares knotspec for transformation + */ + public void select() { + // DONE + breakpoints(); + knots(); + factors(); + + preoffset = kleft.getPointer() - (inkbegin.getPointer() + order); + postwidth = ((bend.getPointer() - bbegin.getPointer()) * order); + prewidth = (outkend.getPointer() - outkbegin.getPointer()) - order; + postoffset = (bbegin.get().def > 1) ? (bbegin.get().def - 1) : 0; + + } + + /** + * Computes alpha factors for computing new control points + */ + private void factors() { + // DONE + CArrayOfFloats mid = new CArrayOfFloats(outkend.getArray(), (outkend + .getPointer() - 1) + - order + bend.get().multi); + + CArrayOfFloats fptr = null; + if (sbegin != null) + fptr = new CArrayOfFloats(sbegin); + + for (CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend); bpt + .getPointer() >= bbegin.getPointer(); bpt.mm()) { + mid.lessenPointerBy(bpt.get().multi); + int def = bpt.get().def - 1; + if (def < 0) + continue; + float kv = bpt.get().value; + + CArrayOfFloats kf = new CArrayOfFloats(mid.getArray(), (mid + .getPointer() - def) + + (order - 1)); + for (CArrayOfFloats kl = new CArrayOfFloats(kf.getArray(), kf + .getPointer() + + def); kl.getPointer() != kf.getPointer(); kl.mm()) { + CArrayOfFloats kh, kt; + for (kt = new CArrayOfFloats(kl), kh = new CArrayOfFloats(mid); kt + .getPointer() != kf.getPointer(); kh.mm(), kt.mm()) { + fptr.set((kv - kh.get()) / (kt.get() - kh.get())); + fptr.pp(); + } + kl.set(kv); + } + } + + } + + /** + * Makes new knot vector + */ + private void knots() { + // DONE + CArrayOfFloats inkpt = new CArrayOfFloats(kleft.getArray(), kleft + .getPointer() + - order); + CArrayOfFloats inkend = new CArrayOfFloats(kright.getArray(), kright + .getPointer() + + bend.get().def); + + outkbegin = new CArrayOfFloats(new float[inkend.getPointer() + - inkpt.getPointer()], 0); + CArrayOfFloats outkpt; + for (outkpt = new CArrayOfFloats(outkbegin); inkpt.getPointer() != inkend + .getPointer(); inkpt.pp(), outkpt.pp()) { + outkpt.set(inkpt.get()); + } + outkend = new CArrayOfFloats(outkpt); + } + + /** + * Analyzes breakpoints + */ + private void breakpoints() { + // DONE + CArrayOfBreakpts ubpt = new CArrayOfBreakpts(bbegin); + CArrayOfBreakpts ubend = new CArrayOfBreakpts(bend); + int nfactors = 0; + + ubpt.get().value = ubend.get().value; + ubpt.get().multi = ubend.get().multi; + + kleft = new CArrayOfFloats(kright); + + for (; kright.getPointer() != klast.getPointer(); kright.pp()) { + if (Knotvector.identical(kright.get(), ubpt.get().value)) { + ubpt.get().multi++; + } else { + ubpt.get().def = order - ubpt.get().multi; + nfactors += (ubpt.get().def * (ubpt.get().def - 1)) / 2; + ubpt.pp(); + ubpt.get().value = kright.get(); + ubpt.get().multi = 1; + } + } + ubpt.get().def = order - ubpt.get().multi; + nfactors += (ubpt.get().def * (ubpt.get().def - 1)) / 2; + + bend = new CArrayOfBreakpts(ubpt); + + if (nfactors > 0) { + sbegin = new CArrayOfFloats(new float[nfactors], 0); + } else { + sbegin = null; + } + + } + + /** + * Copies control points + * + * @param _inpt + * input control points + * @param _outpt + * output control points + */ + public void copy(CArrayOfFloats _inpt, CArrayOfFloats _outpt) { + CArrayOfFloats inpt = new CArrayOfFloats(_inpt); + CArrayOfFloats outpt = new CArrayOfFloats(_outpt); + + inpt.raisePointerBy(preoffset); + if (next != null) { + for (CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(), + outpt.getPointer() + prewidth); outpt.getPointer() != lpt + .getPointer(); outpt.raisePointerBy(poststride)) { + next.copy(inpt, outpt); + inpt.raisePointerBy(prestride); + } + + } else { + for (CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(), + outpt.getPointer() + prewidth); outpt.getPointer() != lpt + .getPointer(); outpt.raisePointerBy(poststride)) { + pt_io_copy(outpt, inpt); + inpt.raisePointerBy(prestride); + } + } + + } + + /** + * Copies one control point to other + * + * @param topt + * source control point + * @param frompt + * destination control point + */ + private void pt_io_copy(CArrayOfFloats topt, CArrayOfFloats frompt) { + // DONE + switch (ncoords) { + case 4: + topt.setRelative(3, frompt.getRelative(3)); + case 3: + topt.setRelative(2, frompt.getRelative(2)); + case 2: + topt.setRelative(1, frompt.getRelative(1)); + case 1: + topt.set(frompt.get()); + break; + default: + // TODO break with copying in general case + // System.out.println("TODO knotspec.pt_io_copy"); + break; + } + + } + + /** + * Inserts a knot + * + * @param _p + * inserted knot + */ + public void transform(CArrayOfFloats _p) { + CArrayOfFloats p = new CArrayOfFloats(_p); + // DONE + if (next != null) {//surface code + if (this.equals(kspectotrans)) { + next.transform(p); + } else { + if (istransformed) { + p.raisePointerBy(postoffset); + for (CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), + p.getPointer() + postwidth); p.getPointer() != pend + .getPointer(); p.raisePointerBy(poststride)) + next.transform(p); + + } else { + CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p + .getPointer() + + prewidth); + for (; p.getPointer() != pend.getPointer(); p + .raisePointerBy(poststride)) + next.transform(p); + } + } + + } else {//code for curve + if (this.equals(kspectotrans)) { + insert(p); + } else { + if (istransformed) { + p.raisePointerBy(postoffset); + for (CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), + p.getPointer() + postwidth); p.getPointer() != pend + .getPointer(); p.raisePointerBy(poststride)) { + kspectotrans.insert(p); + } + } else { + CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p + .getPointer() + + prewidth); + for (; p.getPointer() != pend.getPointer(); p + .raisePointerBy(poststride)) + kspectotrans.insert(p); + } + } + } + + } + + /** + * Inserts a knot and computes new control points + * + * @param p + * inserted knot + */ + private void insert(CArrayOfFloats p) { + // DONE + CArrayOfFloats fptr = null; + if (sbegin != null) + fptr = new CArrayOfFloats(sbegin); + CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), p.getPointer() + + prewidth - poststride); + // CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), prewidth - + // poststride); + CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), p.getPointer() + + postwidth + postoffset - poststride); + // CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), postwidth + + // postoffset - poststride); + CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend); + + for (CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(), srcpt + .getPointer() + - poststride * bpt.get().def); srcpt.getPointer() != pend + .getPointer(); pend.raisePointerBy(poststride)) { + CArrayOfFloats p1 = new CArrayOfFloats(srcpt); + for (CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(), srcpt + .getPointer() + - poststride); p2.getPointer() != pend.getPointer(); p1 + .setPointer(p2.getPointer()), p2 + .lessenPointerBy(poststride)) { + pt_oo_sum(p1, p1, p2, fptr.get(), 1.0 - fptr.get()); + fptr.pp(); + } + } + bpt.mm(); + for (; bpt.getPointer() >= bbegin.getPointer(); bpt.mm()) { + + for (int multi = bpt.get().multi; multi > 0; multi--) { + pt_oo_copy(dstpt, srcpt); + dstpt.lessenPointerBy(poststride); + srcpt.lessenPointerBy(poststride); + } + for (CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(), + srcpt.getPointer() - poststride * bpt.get().def); srcpt + .getPointer() != pend.getPointer(); pend + .raisePointerBy(poststride), dstpt + .lessenPointerBy(poststride)) { + pt_oo_copy(dstpt, srcpt); + CArrayOfFloats p1 = new CArrayOfFloats(srcpt); + + for (CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(), + srcpt.getPointer() - poststride); p2.getPointer() != pend + .getPointer(); p1.setPointer(p2.getPointer()), p2 + .lessenPointerBy(poststride)) { + pt_oo_sum(p1, p1, p2, fptr.get(), 1.0 - fptr.get()); + fptr.pp(); + } + } + } + } + + /** + * Copies one control point to another + * + * @param topt + * source ctrl point + * @param frompt + * distance ctrl point + */ + private void pt_oo_copy(CArrayOfFloats topt, CArrayOfFloats frompt) { + // DONE + // this is a "trick" with case - "break" is omitted so it comes through all cases + switch (ncoords) { + case 4: + topt.setRelative(3, frompt.getRelative(3)); + case 3: + topt.setRelative(2, frompt.getRelative(2)); + case 2: + topt.setRelative(1, frompt.getRelative(1)); + case 1: + topt.setRelative(0, frompt.getRelative(0)); + break; + default: + // default uses memcpy but it is not needed (we probably won't have more than 4 coords) + // TODO not sure about it + break; + } + + } + + /** + * Computes new control point + * + * @param x + * first point + * @param y + * second point + * @param z + * third pont + * @param a + * alpha + * @param b + * 1 - alpha + */ + private void pt_oo_sum(CArrayOfFloats x, CArrayOfFloats y, + CArrayOfFloats z, float a, double b) { + // DONE + switch (ncoords) { + case 4: + x.setRelative(3, (float) (a * y.getRelative(3) + b + * z.getRelative(3))); + case 3: + x.setRelative(2, (float) (a * y.getRelative(2) + b + * z.getRelative(2))); + case 2: + x.setRelative(1, (float) (a * y.getRelative(1) + b + * z.getRelative(1))); + case 1: + x.setRelative(0, (float) (a * y.getRelative(0) + b + * z.getRelative(0))); + break; + default: + //no need of default - see previous method and its case statement + // System.out.println("TODO pt_oo_sum default"); + break; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotvector.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotvector.java new file mode 100755 index 000000000..658a1cbda --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotvector.java @@ -0,0 +1,179 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Knot vector used in curve specification + * + * @author Tomas Hrasky + * + */ +public class Knotvector { + + /** + * Tolerance used when comparing knots - when difference is smaller, knots + * are considered equal + */ + public static final float TOLERANCE = 1.0e-5f; + + /** + * Maximum curve order + */ + private static final int MAXORDER = 24; + + /** + * Number of knots + */ + int knotcount; + + /** + * Number of control points' coordinates + */ + int stride; + + /** + * Curve order + */ + int order; + + /** + * Knots + */ + float[] knotlist; + + /** + * Makes new knotvector + * + * @param nknots + * number of knots + * @param stride + * number of ctrl points' corrdinates + * @param order + * curve order + * @param knot + * knots + */ + public Knotvector(int nknots, int stride, int order, float[] knot) { + // DONE + init(nknots, stride, order, knot); + } + + /** + * Initializes knotvector + * + * @param nknots + * number of knots + * @param stride + * number of ctrl points' corrdinates + * @param order + * curve order + * @param knot + * knots + */ + public void init(int nknots, int stride, int order, float[] knot) { + // DONE + this.knotcount = nknots; + this.stride = stride; + this.order = order; + this.knotlist = new float[nknots]; + for (int i = 0; i < nknots; i++) { + this.knotlist[i] = knot[i]; + } + + } + + /** + * Validates knot vector parameters + * + * @return knot vector validity + */ + public int validate() { + int kindex = knotcount - 1; + if (order < 1 || order > MAXORDER) { + return 1; + } + if (knotcount < 2 * order) { + return 2; + } + if (identical(knotlist[kindex - (order - 1)], knotlist[order - 1])) { + return 3; + } + for (int i = 0; i < kindex; i++) { + if (knotlist[i] > knotlist[i + 1]) + return 4; + } + int multi = 1; + for (; kindex >= 1; kindex--) { + if (knotlist[kindex] - knotlist[kindex - 1] < TOLERANCE) { + multi++; + continue; + } + if (multi > order) { + return 5; + } + multi = 1; + } + if (multi > order) { + return 5; + } + + return 0; + } + + /** + * Show specified message + * + * @param msg + * message to be shown + */ + public void show(String msg) { + // TODO Auto-generated method stub + // System.out.println("TODO knotvector.show"); + + } + + /** + * Compares two knots for equality + * + * @param a + * first knot + * @param b + * second knot + * @return knots are/are not equal + */ + public static boolean identical(float a, float b) { + return ((a - b) < TOLERANCE) ? true : false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Mapdesc.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Mapdesc.java new file mode 100755 index 000000000..568eddc51 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Mapdesc.java @@ -0,0 +1,442 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding properties of OpenGL map + * @author Tomas Hrasky + * + */ +public class Mapdesc { + + /** + * Maximum control point coords + */ + private static final int MAXCOORDS = 5; + + /** + * Next description in list + */ + public Mapdesc next; + + /** + * Is map rational + */ + public int isrational; + + /** + * Number of control point coords + */ + public int ncoords; + + /** + * Map type + */ + private int type; + + /** + * Number of homogenous coords + */ + private int hcoords; + + /** + * Number of inhomogenous coords + */ + private int inhcoords; + + /** + * Not used + */ + private int mask; + + /** + * Value of N_PIXEL_TOLERANCE property + */ + private float pixel_tolerance; + + /** + * Value of N_ERROR_TOLERANCE property + */ + private float error_tolerance; + + /** + * Value of N_BBOX_SUBDIVIDING property + */ + private float bbox_subdividing; + + /** + * Value of N_CULLING property + */ + private float culling_method; + + /** + * Value of N_SAMPLINGMETHOD property + */ + private float sampling_method; + + /** + * Value of N_CLAMPFACTOR property + */ + float clampfactor; + + /** + * Value of N_MINSAVINGS property + */ + private float minsavings; + + /** + * Steps in u direction + */ + private float s_steps; + + /** + * Steps in v direction + */ + private float t_steps; + + /** + * Maximal step + */ + float maxrate; + + /** + * Maximal u direction step + */ + private float maxsrate; + + /** + * Maximal v direction step + */ + private float maxtrate; + + /** + * Not used + */ + private float[][] bmat; + + /** + * Sampling matrix + */ + private float[][] smat; + + /** + * Not used + */ + private float[][] cmat; + + /** + * Not used + */ + private float[] bboxsize; + + /** + * Makes new mapdesc + * @param type map type + * @param rational is rational + * @param ncoords number of control points coords + * @param backend backend object + */ + public Mapdesc(int type, int rational, int ncoords, Backend backend) { + // DONE + this.type = type; + this.isrational = rational; + this.ncoords = ncoords; + this.hcoords = ncoords + (isrational > 0 ? 0 : 1); + this.inhcoords = ncoords - (isrational > 0 ? 1 : 0); + this.mask = ((1 << (inhcoords * 2)) - 1); + next = null; + + assert (hcoords <= MAXCOORDS); + assert (inhcoords >= 1); + + pixel_tolerance = 1f; + error_tolerance = 1f; + bbox_subdividing = NurbsConsts.N_NOBBOXSUBDIVISION; + culling_method = NurbsConsts.N_NOCULLING; + sampling_method = NurbsConsts.N_NOSAMPLING; + clampfactor = NurbsConsts.N_NOCLAMPING; + minsavings = NurbsConsts.N_NOSAVINGSSUBDIVISION; + s_steps = 0f; + t_steps = 0f; + + maxrate = (s_steps < 0) ? 0 : s_steps; + maxsrate = (s_steps < 0) ? 0 : s_steps; + maxtrate = (t_steps < 0) ? 0 : t_steps; + bmat = new float[MAXCOORDS][MAXCOORDS]; + cmat = new float[MAXCOORDS][MAXCOORDS]; + smat = new float[MAXCOORDS][MAXCOORDS]; + + identify(bmat); + identify(cmat); + identify(smat); + bboxsize = new float[MAXCOORDS]; + for (int i = 0; i < inhcoords; i++) + bboxsize[i] = 1; + } + + /** + * Make matrix identity matrix + * @param arr matrix + */ + private void identify(float[][] arr) { + // DONE + for (int i = 0; i < MAXCOORDS; i++) + for (int j = 0; j < MAXCOORDS; j++) + arr[i][j] = 0; + for (int i = 0; i < MAXCOORDS; i++) + arr[i][i] = 1; + + } + + /** + * Tells whether tag is property tag + * @param tag property tag + * @return is/is not property + */ + public boolean isProperty(int tag) { + boolean ret; + switch (tag) { + case NurbsConsts.N_PIXEL_TOLERANCE: + case NurbsConsts.N_ERROR_TOLERANCE: + case NurbsConsts.N_CULLING: + case NurbsConsts.N_BBOX_SUBDIVIDING: + case NurbsConsts.N_S_STEPS: + case NurbsConsts.N_T_STEPS: + case NurbsConsts.N_SAMPLINGMETHOD: + case NurbsConsts.N_CLAMPFACTOR: + case NurbsConsts.N_MINSAVINGS: + ret = true; + break; + default: + ret = false; + break; + } + return ret; + } + + /** + * Returns number of control points' coords + * @return number of control points' coords + */ + public int getNCoords() { + return ncoords; + } + + /** + * Returns map type + * @return map type + */ + public int getType() { + return type; + } + + /** + * Tells whether map is range sampling + * @return is map range sampling + */ + public boolean isRangeSampling() { + // DONE + return (isParametricDistanceSampling() || isPathLengthSampling() + || isSurfaceAreaSampling() || isObjectSpaceParaSampling() || isObjectSpacePathSampling()); + } + + /** + * Tells whether map is object space sampling + * @return is map object space sampling + */ + private boolean isObjectSpacePathSampling() { + // DONE + return sampling_method == NurbsConsts.N_OBJECTSPACE_PATH; + } + + /** + * Tells whether map is object space parasampling + * @return is map object space parasampling + */ + private boolean isObjectSpaceParaSampling() { + // DONE + return sampling_method == NurbsConsts.N_OBJECTSPACE_PARA; + } + + /** + * Tells whether map is area sampling surface + * @return is map area sampling surface + */ + private boolean isSurfaceAreaSampling() { + // DONE + return sampling_method == NurbsConsts.N_SURFACEAREA; + } + + /** + * Tells whether map is path length sampling + * @return is map path length sampling + */ + boolean isPathLengthSampling() { + // DONE + return sampling_method == NurbsConsts.N_PATHLENGTH; + } + + /** + * Tells whether map is parametric distance sampling + * @return is map parametric distance sampling + */ + boolean isParametricDistanceSampling() { + // DONE + return sampling_method == NurbsConsts.N_PARAMETRICDISTANCE; + } + + /** + * Tells whether map is culling + * @return is map culling + */ + public boolean isCulling() { + // DONE + return culling_method != NurbsConsts.N_NOCULLING ? true : false; + } + + /** + * Tells whether map is constantly sampling + * @return is map constant sampling + */ + public boolean isConstantSampling() { + return (sampling_method == NurbsConsts.N_FIXEDRATE) ? true : false; + } + + /** + * Tells whether map is domain sampling + * @return is map domain sampling + */ + public boolean isDomainSampling() { + return (sampling_method == NurbsConsts.N_DOMAINDISTANCE) ? true : false; + } + + /** + * Returns property of specified tag value + * @param tag property tag + * @return property value + */ + public float getProperty(int tag) { + // TODO Auto-generated method stub + // System.out.println("TODO mapdesc.getproperty"); + return 0; + } + + /** + * Sets property with given tag + * @param tag property tag + * @param value desired value + */ + public void setProperty(int tag, float value) { + // TODO Auto-generated method stub + switch (tag) { + case NurbsConsts.N_PIXEL_TOLERANCE: + pixel_tolerance = value; + break; + case NurbsConsts.N_ERROR_TOLERANCE: + error_tolerance = value; + break; + case NurbsConsts.N_CULLING: + culling_method = value; + break; + case NurbsConsts.N_BBOX_SUBDIVIDING: + if (value <= 0) + value = NurbsConsts.N_NOBBOXSUBDIVISION; + bbox_subdividing = value; + break; + case NurbsConsts.N_S_STEPS: + if (value < 0) + value = 0; + s_steps = value; + maxrate = value; + maxsrate = value; + break; + case NurbsConsts.N_T_STEPS: + if (value < 0) + value = 0; + t_steps = value; + maxtrate = value; + break; + case NurbsConsts.N_SAMPLINGMETHOD: + sampling_method = value; + break; + case NurbsConsts.N_CLAMPFACTOR: + if (value < 0) + value = 0; + clampfactor = value; + break; + case NurbsConsts.N_MINSAVINGS: + if (value <= 0) + value = NurbsConsts.N_NOSAVINGSSUBDIVISION; + minsavings = value; + break; + } + } + + /** + * Samples curve + * @param pts control points + * @param order curve order + * @param stride number of control points' coordinates + * @param sp breakpoints + * @param outstride output number of control points' coordinates + */ + public void xformSampling(CArrayOfFloats pts, int order, int stride, + float[] sp, int outstride) { + // DONE + xFormMat(smat, pts, order, stride, sp, outstride); + } + + /** + * Empty method + * @param mat sampling matrix + * @param pts ontrol points + * @param order curve order + * @param stride number of control points' coordinates + * @param cp breakpoints + * @param outstride output number of control points' coordinates + */ + private void xFormMat(float[][] mat, CArrayOfFloats pts, int order, + int stride, float[] cp, int outstride) { + // TODO Auto-generated method stub + + // System.out.println("TODO mapdsc.xformmat ; change cp from float[] to carrayoffloats"); + + if (isrational > 0) { + + } else { + + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Maplist.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Maplist.java new file mode 100755 index 000000000..b23a1f665 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Maplist.java @@ -0,0 +1,122 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding list of Mapdescs + * @author Tomáš Hráský + * + */ +public class Maplist { + /** + * Head of linked list + */ + private Mapdesc maps; + + /** + * Backend class + */ + private Backend backend; + + /** + * Makes new Maplist + * @param backend Backend class + */ + public Maplist(Backend backend) { + this.backend = backend; + } + + /** + * Sets linked list beginning to null + */ + public void initialize() { + // TODO mapdespool.clear ? + maps = null; + } + + /** + * Defines new Mapdesc if it is not defined and appends it to linked list + * @param type map type + * @param rational is map rational + * @param ncoords number of coords + */ + public void define(int type, int rational, int ncoords) { + // DONE + Mapdesc m = locate(type); + assert (m == null || (m.isrational == rational && m.ncoords == ncoords)); + add(type, rational, ncoords); + + } + + /** + * Adds new Mapdesc to linked list + * @param type map type + * @param rational is map rational + * @param ncoords number of coords + */ + private void add(int type, int rational, int ncoords) { + // DONE + Mapdesc map = new Mapdesc(type, rational, ncoords, backend); + if (maps == null) { + maps = map; + } else { + map.next = maps; + maps = map; + } + } + + /** + * Tries to find Mapdesc in linked list + * @param type map type + * @return Mapdesc of type or null if there is no such map + */ + public Mapdesc locate(int type) { + // DONE + Mapdesc m = null; + for (m = maps; m != null; m = m.next) + if (m.getType() == type) + break; + return m; + } + + /** + * Alias for locate + * @param type maptype + * @return Mapdesc of type or null if there is no such map + */ + public Mapdesc find(int type) { + return locate(type); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/NurbsConsts.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/NurbsConsts.java new file mode 100755 index 000000000..ee7f3b31b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/NurbsConsts.java @@ -0,0 +1,184 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class hodling NURBS constants as seen in OpenGL GLU documentation + * @author JOGL project + * + */ +public class NurbsConsts { + /* + * NURBS Properties - one set per map, each takes a single INREAL arg + */ + public static final int N_SAMPLING_TOLERANCE = 1; + + public static final int N_S_RATE = 6; + + public static final int N_T_RATE = 7; + + public static final int N_CLAMPFACTOR = 13; + + public static final float N_NOCLAMPING = 0.0f; + + public static final int N_MINSAVINGS = 14; + + public static final float N_NOSAVINGSSUBDIVISION = 0.0f; + + /* + * NURBS Properties - one set per map, each takes an enumerated value + */ + public static final int N_CULLING = 2; + + public static final float N_NOCULLING = 0.0f; + + public static final float N_CULLINGON = 1.0f; + + public static final int N_SAMPLINGMETHOD = 10; + + public static final float N_NOSAMPLING = 0.0f; + + public static final float N_FIXEDRATE = 3.0f; + + public static final float N_DOMAINDISTANCE = 2.0f; + + public static final float N_PARAMETRICDISTANCE = 5.0f; + + public static final float N_PATHLENGTH = 6.0f; + + public static final float N_SURFACEAREA = 7.0f; + + public static final float N_OBJECTSPACE_PARA = 8.0f; + + public static final float N_OBJECTSPACE_PATH = 9.0f; + + public static final int N_BBOX_SUBDIVIDING = 17; + + public static final float N_NOBBOXSUBDIVISION = 0.0f; + + public static final float N_BBOXTIGHT = 1.0f; + + public static final float N_BBOXROUND = 2.0f; + + /* + * NURBS Rendering Properties - one set per renderer each takes an + * enumerated value + */ + public static final int N_DISPLAY = 3; + + public static final int N_FILL = 1; + + public static final int N_OUTLINE_POLY = 2; + + public static final int N_OUTLINE_TRI = 3; + + public static final int N_OUTLINE_QUAD = 4; + + public static final int N_OUTLINE_PATCH = 5; + + public static final int N_OUTLINE_PARAM = 6; + + public static final int N_OUTLINE_PARAM_S = 7; + + public static final int N_OUTLINE_PARAM_ST = 8; + + public static final int N_OUTLINE_SUBDIV = 9; + + public static final int N_OUTLINE_SUBDIV_S = 10; + + public static final int N_OUTLINE_SUBDIV_ST = 11; + + public static final int N_ISOLINE_S = 12; + + public static final int N_ERRORCHECKING = 4; + + public static final int N_NOMSG = 0; + + public static final int N_MSG = 1; + + /* GL 4.0 propeties not defined above */ + + public static final int N_PIXEL_TOLERANCE = N_SAMPLING_TOLERANCE; + + public static final int N_ERROR_TOLERANCE = 20; + + public static final int N_SUBDIVISIONS = 5; + + public static final int N_TILES = 8; + + public static final int N_TMP1 = 9; + + public static final int N_TMP2 = N_SAMPLINGMETHOD; + + public static final int N_TMP3 = 11; + + public static final int N_TMP4 = 12; + + public static final int N_TMP5 = N_CLAMPFACTOR; + + public static final int N_TMP6 = N_MINSAVINGS; + + public static final int N_S_STEPS = N_S_RATE; + + public static final int N_T_STEPS = N_T_RATE; + + /* + * NURBS Rendering Properties - one set per map, each takes an INREAL matrix + * argument + */ + public static final int N_CULLINGMATRIX = 1; + + public static final int N_SAMPLINGMATRIX = 2; + + public static final int N_BBOXMATRIX = 3; + + /* + * NURBS Rendering Properties - one set per map, each takes an INREAL vector + * argument + */ + public static final int N_BBOXSIZE = 4; + + /* type argument for trimming curves */ + + public static final int N_P2D = 0x8; + + public static final int N_P2DR = 0xd; + + public static final int N_MESHLINE = 1; + + public static final int N_MESHFILL = 0; + + public static final int N_MESHPOINT = 2; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_curve.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_curve.java new file mode 100755 index 000000000..900f8e56f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_curve.java @@ -0,0 +1,63 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Struct holding curve links + * @author Tomáš Hráský + * + */ +public class O_curve { + + /** + * Curve type + */ + public int curvetype; + + /** + * Next curve in linked list + */ + public O_curve next; + + /** + * Curve of picewiselinear type + */ + public O_pwlcurve o_pwlcurve; + + /** + * NURBS curve + */ + public O_nurbscurve o_nurbscurve; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbscurve.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbscurve.java new file mode 100755 index 000000000..81110813f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbscurve.java @@ -0,0 +1,80 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS curve object + * @author Tomáš Hráský + * + */ +public class O_nurbscurve { + + /** + * List of bezier curves + */ + public Quilt bezier_curves; + + /** + * Curve type + */ + public int type; + + /** + * Was curve used ? + */ + public boolean used; + + /** + * Parent curve + */ + public O_curve owner; + + /** + * Next curve in list + */ + public O_nurbscurve next; + + /** + * Makes new O_nurbscurve + * @param realType type of curve + */ + public O_nurbscurve(int realType) { + // DONE + this.type = realType; + this.owner = null; + this.next = null; + this.used = false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbssurface.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbssurface.java new file mode 100755 index 000000000..b598f525d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbssurface.java @@ -0,0 +1,79 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS surface object + * @author Tomáš Hráský + * + */ +public class O_nurbssurface { + + /** + * List of bezier patches forming NURBS surface + */ + public Quilt bezier_patches; + + /** + * Was surface used + */ + public boolean used; + + /** + * Parent O_surface + */ + public O_surface owner; + + /** + * Next surface in list + */ + public O_nurbssurface next; + + /** + * Surface type + */ + private int type; + + /** + * Makes new O_nurbssurface of type + * @param type surface type + */ + public O_nurbssurface(int type) { + this.type = type; + this.owner = null; + this.next = null; + this.used = false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_pwlcurve.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_pwlcurve.java new file mode 100755 index 000000000..e50f41d81 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_pwlcurve.java @@ -0,0 +1,44 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomáš Hráský + * + */ +public class O_pwlcurve { + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_surface.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_surface.java new file mode 100755 index 000000000..76ac79f0a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_surface.java @@ -0,0 +1,52 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Surface object + * @author Tomáš Hráský + * + */ +public class O_surface { + /** + * NURBS surface + */ + public O_nurbssurface o_nurbssurface; + + /** + * Trims + */ + public O_trim o_trim; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_trim.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_trim.java new file mode 100755 index 000000000..17e5002df --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_trim.java @@ -0,0 +1,44 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomáš Hráský + * + */ +public class O_trim { + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patch.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patch.java new file mode 100755 index 000000000..d3066cc84 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patch.java @@ -0,0 +1,54 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomas Hrasky + * + */ +public class Patch { + + /** + * Empty constructor + * @param q + * @param pta + * @param ptb + * @param patch + */ + public Patch(Quilt q, float[] pta, float[] ptb, Patch patch) { + // System.out.println("TODO patch.constructor"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patchlist.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patchlist.java new file mode 100755 index 000000000..8b439a02f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patchlist.java @@ -0,0 +1,145 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * List of patches + * @author Tomáš Hráský + * + */ +public class Patchlist { + + /** + * Array of ranges + */ + public Pspec[] pspec; + + /** + * head of list of patches + */ + private Patch patch; + + /** + * Makes new list of patches + * @param quilts list of quilts + * @param pta low border + * @param ptb high border + */ + public Patchlist(Quilt quilts, float[] pta, float[] ptb) { + // DONE + patch = null; + + for (Quilt q = quilts; q != null; q = q.next) + patch = new Patch(q, pta, ptb, patch); + pspec[0] = new Pspec(); + pspec[0].range[0] = pta[0]; + pspec[0].range[1] = ptb[0]; + pspec[0].range[2] = ptb[0] - pta[0]; + pspec[1] = new Pspec(); + pspec[1].range[0] = pta[1]; + pspec[1].range[1] = ptb[1]; + pspec[1].range[2] = ptb[1] - pta[1]; + + } + + /** + * Empty constructor + * @param patchlist + * @param param + * @param mid + */ + public Patchlist(Patchlist patchlist, int param, float mid) { + // TODO Auto-generated constructor stub + // System.out.println("TODO patchlist.konstruktor 2"); + } + + /** + * Empty method + * @return 0 + */ + public int cullCheck() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.cullcheck"); + return 0; + } + + /** + * Empty method + */ + public void getstepsize() { + // System.out.println("TODO patchlist.getsptepsize"); + // TODO Auto-generated method stub + + } + + /** + * Empty method + * @return false + */ + public boolean needsSamplingSubdivision() { + // TODO Auto-generated method stub + // System.out.println("patchlist.needsSamplingSubdivision"); + return false; + } + + /** + * Empty method + * @param i + * @return false + */ + public boolean needsSubdivision(int i) { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.needsSubdivision"); + return false; + } + + /** + * Empty method + * @return false + */ + public boolean needsNonSamplingSubdivision() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.needsNonSamplingSubdivision"); + return false; + } + + /** + * Empty method + */ + public void bbox() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.bbox"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Property.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Property.java new file mode 100755 index 000000000..b486a0ead --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Property.java @@ -0,0 +1,75 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class representing property + * + * @author Tomas Hrasky + * + */ +public class Property { + + /** + * Property type + */ + public int type; + + /** + * Property id + */ + public int tag; + + /** + * Property value + */ + public float value; + + /** + * Makes new property with given parameters + * + * @param type + * property type + * @param tag + * property id + * @param value + * property value + */ + public Property(int type, int tag, float value) { + this.type = type; + this.tag = tag; + this.value = value; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Pspec.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Pspec.java new file mode 100755 index 000000000..1e60ed335 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Pspec.java @@ -0,0 +1,47 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding range + * @author Tomáš Hráský + * + */ +public class Pspec { + /** + * Range + */ + public float[] range; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/PwlArc.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/PwlArc.java new file mode 100755 index 000000000..0c9eca91e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/PwlArc.java @@ -0,0 +1,71 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Picewiselinar trimming arc + * @author Tomáš Hráský + * + */ +public class PwlArc { + + /** + * Number of points + */ + private int npts; + + /** + * Vertexes + */ + public TrimVertex[] pts; + + /** + * Arc type + */ + private int type; + + /** + * Makes new trimming arc + * @param i num ber of vertexes + * @param p trimming vertexes array + */ + public PwlArc(int i, TrimVertex[] p) { + // DONE + this.npts = i; + this.pts = p; + type = NurbsConsts.N_P2D; + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quilt.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quilt.java new file mode 100755 index 000000000..03e809d23 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quilt.java @@ -0,0 +1,282 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for converting NURBS curves and surfaces to list of bezier arcs or patches repectively + * @author Tomáš Hráský + * + */ +public class Quilt { + /** + * Maximum quilt dimension + */ + private static final int MAXDIM = 2; + + /** + * List of map descriptions + */ + Mapdesc mapdesc; + + /** + * Array of quiltspecs pointer + */ + public CArrayOfQuiltspecs qspec; + + /** + * End array of quilt specs pointer + */ + public CArrayOfQuiltspecs eqspec; + + /** + * Control points + */ + public CArrayOfFloats cpts; + + /** + * Next quilt in list + */ + public Quilt next; + + /** + * Makes new quilt with mapdesc + * @param mapdesc map description + */ + public Quilt(Mapdesc mapdesc) { + // DONE + this.mapdesc = mapdesc; + Quiltspec[] tmpquilts = new Quiltspec[MAXDIM]; + for (int i = 0; i < tmpquilts.length; i++) + tmpquilts[i] = new Quiltspec(); + this.qspec = new CArrayOfQuiltspecs(tmpquilts); + + } + + /** + * Converts NURBS surface to bezier patches + * @param sknotvector knots in u direction + * @param tknotvector knots in v direction + * @param ctrlarr control points + * @param coords control points coords + */ + public void toBezier(Knotvector sknotvector, Knotvector tknotvector, + CArrayOfFloats ctrlarr, int coords) { + Splinespec spline = new Splinespec(2); + spline.kspecinit(sknotvector, tknotvector); + spline.select(); + spline.layout(coords); + spline.setupquilt(this); + spline.copy(ctrlarr); + spline.transform(); + } + + /** + * Converts NURBS curve to list of bezier curves + * @param knots knot vector + * @param ctlarray control points + * @param ncoords number of coordinates + */ + public void toBezier(Knotvector knots, CArrayOfFloats ctlarray, int ncoords) { + // DONE + Splinespec spline = new Splinespec(1); + spline.kspecinit(knots); + spline.select(); + spline.layout(ncoords); + spline.setupquilt(this); + spline.copy(ctlarray); + spline.transform(); + } + + /** + * Walks thru all arcs/patches + * @param pta low border + * @param ptb high border + * @param backend Backend + */ + public void downloadAll(float[] pta, float[] ptb, Backend backend) { + // DONE + for (Quilt m = this; m != null; m = m.next) { + m.select(pta, ptb); + m.download(backend); + } + + } + + /** + * Renders arcs/patches + * @param backend Backend for rendering + */ + private void download(Backend backend) { + // DONE + if (getDimension() == 2) { + + CArrayOfFloats ps = new CArrayOfFloats(cpts); + ps.raisePointerBy(qspec.get(0).offset); + ps.raisePointerBy(qspec.get(1).offset); + ps.raisePointerBy(qspec.get(0).index * qspec.get(0).order + * qspec.get(0).stride); + ps.raisePointerBy(qspec.get(1).index * qspec.get(1).order + * qspec.get(1).stride); + + backend.surfpts(mapdesc.getType(), ps, qspec.get(0).stride, qspec + .get(1).stride, qspec.get(0).order, qspec.get(1).order, + qspec.get(0).breakpoints[qspec.get(0).index], + qspec.get(0).breakpoints[qspec.get(0).index + 1], qspec + .get(1).breakpoints[qspec.get(1).index], qspec + .get(1).breakpoints[qspec.get(1).index + 1]); + + } else {// code for curves + // CArrayOfFloats ps=new CArrayOfFloats(cpts); + CArrayOfFloats ps = new CArrayOfFloats(cpts.getArray(), 0); + ps.raisePointerBy(qspec.get(0).offset); + ps.raisePointerBy(qspec.get(0).index * qspec.get(0).order + * qspec.get(0).stride); + backend.curvpts(mapdesc.getType(), ps, qspec.get(0).stride, qspec + .get(0).order, + qspec.get(0).breakpoints[qspec.get(0).index], + qspec.get(0).breakpoints[qspec.get(0).index + 1]); + } + + } + + /** + * Returns quilt dimension + * @return quilt dimesion + */ + private int getDimension() { + // DONE + return eqspec.getPointer() - qspec.getPointer(); + } + + /** + * Finds Quiltspec.index + * @param pta range + * @param ptb range + */ + private void select(float[] pta, float[] ptb) { + // DONE + int dim = eqspec.getPointer() - qspec.getPointer(); + int i, j; + for (i = 0; i < dim; i++) { + for (j = qspec.get(i).width - 1; j >= 0; j--) + if (qspec.get(i).breakpoints[j] <= pta[i] + && ptb[i] <= qspec.get(i).breakpoints[j + 1]) + break; + assert (j != -1); + qspec.get(i).index = j; + } + } + + /** + * Find range according to breakpoints + * @param from low param + * @param to high param + * @param bpts breakpoints + */ + public void getRange(float[] from, float[] to, Flist bpts) { + // DONE + getRange(from, to, 0, bpts); + + } + + /** + * Find range according to breakpoints + * @param from low param + * @param to high param + * @param i from/to array index + * @param list breakpoints + */ + private void getRange(float[] from, float[] to, int i, Flist list) { + // DONE + Quilt maps = this; + from[i] = maps.qspec.get(i).breakpoints[0]; + to[i] = maps.qspec.get(i).breakpoints[maps.qspec.get(i).width]; + int maxpts = 0; + Quilt m; + for (m = maps; m != null; m = m.next) { + if (m.qspec.get(i).breakpoints[0] > from[i]) + from[i] = m.qspec.get(i).breakpoints[0]; + if (m.qspec.get(i).breakpoints[m.qspec.get(i).width] < to[i]) + to[i] = m.qspec.get(i).breakpoints[m.qspec.get(i).width]; + maxpts += m.qspec.get(i).width + 1; + } + list.grow(maxpts); + for (m = maps; m != null; m = m.next) { + for (int j = 0; j <= m.qspec.get(i).width; j++) { + list.add(m.qspec.get(i).breakpoints[j]); + } + } + list.filter(); + list.taper(from[i], to[i]); + } + + /** + * Is this quilt culled + * @return 0 or Subdivider.CULL_ACCEPT + */ + public int isCulled() { + if (mapdesc.isCulling()) { + // System.out.println("TODO quilt.isculled mapdesc.isculling"); + return 0; + } else { + return Subdivider.CULL_ACCEPT; + } + } + + /** + * Finds range for surface + * @param from low param + * @param to high param + * @param slist u direction breakpoints + * @param tlist v direction breakpoints + */ + public void getRange(float[] from, float[] to, Flist slist, Flist tlist) { + // DONE + getRange(from, to, 0, slist); + getRange(from, to, 1, tlist); + + } + + /** + * Empty method + * @param sbrkpts + * @param tbrkpts + * @param rate + */ + public void findRates(Flist sbrkpts, Flist tbrkpts, float[] rate) { + // TODO Auto-generated method stub + // System.out.println("TODO quilt.findrates"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quiltspec.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quiltspec.java new file mode 100755 index 000000000..6c8e55e06 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quiltspec.java @@ -0,0 +1,85 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Quilt definition + * @author Tomas Hrasky + * + */ +public class Quiltspec { + + /** + * Stride between control points + */ + public int stride; + + /** + * Quilt width in breakpoints + */ + public int width; + + /** + * Quilt order + */ + public int order; + + /** + * Start offset + */ + public int offset; + + /** + * Breakpoint index + */ + public int index; + + /** + * Boundary + */ + public int[] bdry; + + /** + * Breakpoints + */ + public float[] breakpoints; + + /** + * Makes new quiltspec + */ + public Quiltspec() { + this.bdry = new int[2]; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/README.txt b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/README.txt new file mode 100755 index 000000000..89630c71e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/README.txt @@ -0,0 +1,59 @@ +Unimplemented functionality + - tesselation and callbacks + - trimming + - setting NURBS properties (-> sampling etc.) +Differences from C++ source + - no pooling + - pointers to arrays are replaced by CArrayOf... classes and their methods +Unimplemented or incomplete "calltree top" methods (according to glu.def in Mesa 6.5) + gluBeginTrim + gluDeleteNurbsRenderer - won't be needed + gluEndTrim + gluGetNurbsProperty + gluLoadSamplingMatrices + gluNurbsCallback + gluNurbsCallbackData + gluNurbsCallbackDataEXT + gluNurbsCurve - TODO type switch + gluNurbsProperty + gluPwlCurve + gluQuadricCallback - not a NURBS method +As of files + - Arc[ST]dirSorter.java - unimplemented (part of tesselation) + - Backend.java:194 - wireframe quads - part of tesselation/callback + - Curve.java:141-204 - culling + - DisplayList.java:57 - append to DL - not sure whether it will be needed + - GLUnurbs.java :443,484 - error values + :445 - trimming + :512 - error handling (callback) + :530 - loadGLmatrices + :786 - nuid - nurbs object id - won't be needed I think + :803 - end trim + - GLUwNURBS.java:68,176 - NUBRS properties + - Knotspec.java :371 - copying in general case (more than 4 coords) + :517 - copying with more than 4 coords + :556 - pt_oo_sum default + - Knotvector.java:165 - show method (probably debugging) + - Mapdesc.java :354 - get property + :435 - xFormMat - change param cp to CArrayOfFloats; probably sampling functionality + - Maplist.java:68 - clear ? + - OpenGLCurveEvaluator.java :132 - tess./callback code + :168 - mapgrid1f + :190 - tess./callback code (output triangles) + - OpenGLSurfaceEvaluator.java :77 . tess./callback code + :81 - glGetIntegerValue + :114 - tess./callback code + :117 - Level of detail + :144,161,201 - tess./callback code - output triangles + - Patch.java:55 - constructor stuff ? + - Patchlist.java:55 - constructor stuff ? + :97 - cull check + :105 - step size + :115 - need of sampling subdivision + :126 - need of subdivision + :137 - need of non sampling subd. + :146 - bbox (??) + -Quilt.java :254 - culling + :282 - rates + -Subdivider.java - all TODOs - it's stuff about trimming probably + :545 - jumpbuffer - not sure purpose it exactly served in original source diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Renderhints.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Renderhints.java new file mode 100755 index 000000000..d1a23fbab --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Renderhints.java @@ -0,0 +1,128 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding rendering params + * @author Tomas Hrasky + * + */ +public class Renderhints { + + /** + * Check for errors + */ + public int errorchecking; + + /** + * Maximum subdivisions + */ + public int maxsubdivisions; + + /** + * Number of subdivisions + */ + private int subdivisions; + + /** + * Display method + */ + int display_method; + + /** + * Output triangles + */ + int wiretris; + + /** + * Output quads + */ + int wirequads; + + /** + * Makes new Renderinghints + */ + public Renderhints() { + display_method = NurbsConsts.N_FILL; + errorchecking = NurbsConsts.N_MSG; + subdivisions = 6; + // tmp1=0; + } + + /** + * Set property value + * @param prop property + */ + public void setProperty(Property prop) { + switch (prop.type) { + case NurbsConsts.N_DISPLAY: + display_method = (int) prop.value; + break; + case NurbsConsts.N_ERRORCHECKING: + errorchecking = (int) prop.value; + break; + case NurbsConsts.N_SUBDIVISIONS: + subdivisions = (int) prop.value; + break; + default: + // abort - end program + break; + } + } + + /** + * Initialization + */ + public void init() { + // DONE + maxsubdivisions = subdivisions; + if (maxsubdivisions < 0) + maxsubdivisions = 0; + + if (display_method == NurbsConsts.N_FILL) { + wiretris = 0; + wirequads = 0; + } else if (display_method == NurbsConsts.N_OUTLINE_TRI) { + wiretris = 1; + wirequads = 0; + } else if (display_method == NurbsConsts.N_OUTLINE_QUAD) { + wiretris = 0; + wirequads = 1; + } else { + wiretris = 1; + wirequads = 1; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Splinespec.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Splinespec.java new file mode 100755 index 000000000..487b47f2d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Splinespec.java @@ -0,0 +1,204 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS definition + * @author Tomas Hrasky + * + */ +public class Splinespec { + + /** + * Dimension + */ + private int dim; + + /** + * Knot vector specs + */ + private Knotspec kspec; + + /** + * Control points after conversion + */ + private CArrayOfFloats outcpts; + + /** + * Makes new Splinespec with given dimension + * @param i dimension + */ + public Splinespec(int i) { + // DONE + this.dim = i; + } + + /** + * Initializes knotspec according to knotvector + * @param knotvector basic knotvector + */ + public void kspecinit(Knotvector knotvector) { + // DONE + this.kspec = new Knotspec(); + kspec.inkbegin = new CArrayOfFloats(knotvector.knotlist, 0); + kspec.inkend = new CArrayOfFloats(knotvector.knotlist, + knotvector.knotcount); + kspec.prestride = knotvector.stride; + kspec.order = knotvector.order; + kspec.next = null; + } + + /** + * Initializes knotspec according to knotvector - SURFACE + * @param sknotvector knotvector in u dir + * @param tknotvector knotvector in v dir + */ + public void kspecinit(Knotvector sknotvector, Knotvector tknotvector) { + // DONE + this.kspec = new Knotspec(); + Knotspec tkspec = new Knotspec(); + + kspec.inkbegin = new CArrayOfFloats(sknotvector.knotlist, 0); + kspec.inkend = new CArrayOfFloats(sknotvector.knotlist, + sknotvector.knotcount); + kspec.prestride = sknotvector.stride; + kspec.order = sknotvector.order; + kspec.next = tkspec; + + tkspec.inkbegin = new CArrayOfFloats(tknotvector.knotlist, 0); + tkspec.inkend = new CArrayOfFloats(tknotvector.knotlist, + tknotvector.knotcount); + tkspec.prestride = tknotvector.stride; + tkspec.order = tknotvector.order; + tkspec.next = null; + } + + /** + * Preselect and select knotspecs + */ + public void select() { + // DONE + for (Knotspec knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + knotspec.preselect(); + knotspec.select(); + } + + } + + /** + * Prepares for conversion + * @param ncoords number of coords + */ + public void layout(int ncoords) { + // DONE + int stride = ncoords; + for (Knotspec knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + knotspec.poststride = stride; + stride *= (knotspec.bend.getPointer() - knotspec.bbegin + .getPointer()) + * knotspec.order + knotspec.postoffset; + knotspec.preoffset *= knotspec.prestride; + knotspec.prewidth *= knotspec.poststride; + knotspec.postwidth *= knotspec.poststride; + knotspec.postoffset *= knotspec.poststride; + knotspec.ncoords = ncoords; + } + outcpts = new CArrayOfFloats(new float[stride]); + + } + + /** + * Prepares quilt for conversion + * @param quilt quilt to work with + */ + public void setupquilt(Quilt quilt) { + // DONE + CArrayOfQuiltspecs qspec = new CArrayOfQuiltspecs(quilt.qspec); + quilt.eqspec = new CArrayOfQuiltspecs(qspec.getArray(), dim); + for (Knotspec knotspec = kspec; knotspec != null;) { + qspec.get().stride = knotspec.poststride; + qspec.get().width = knotspec.bend.getPointer() + - knotspec.bbegin.getPointer(); + qspec.get().order = knotspec.order; + qspec.get().offset = knotspec.postoffset; + qspec.get().index = 0; + qspec.get().bdry[0] = (knotspec.kleft.getPointer() == knotspec.kfirst + .getPointer()) ? 1 : 0; + qspec.get().bdry[1] = (knotspec.kright.getPointer() == knotspec.klast + .getPointer()) ? 1 : 0; + qspec.get().breakpoints = new float[qspec.get().width + 1]; + CArrayOfFloats k = new CArrayOfFloats(qspec.get().breakpoints, 0); + for (CArrayOfBreakpts bk = new CArrayOfBreakpts(knotspec.bbegin); bk + .getPointer() <= knotspec.bend.getPointer(); bk.pp()) { + k.set(bk.get().value); + k.pp(); + } + knotspec = knotspec.next; + if (knotspec != null) + qspec.pp(); + } + quilt.cpts = new CArrayOfFloats(outcpts); + quilt.next = null; + } + + /** + * Copies array of control points to output array + * @param ctlarray control points array + */ + public void copy(CArrayOfFloats ctlarray) { + // DONE + kspec.copy(ctlarray, outcpts); + + } + + /** + * Transforms knotspecs - conversion + */ + public void transform() { + // DONE + Knotspec knotspec; + outcpts.setPointer(0); + for (knotspec = kspec; knotspec != null; knotspec = knotspec.next) + knotspec.istransformed = false; + + for (knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + for (Knotspec kspec2 = kspec; kspec2 != null; kspec2 = kspec2.next) + kspec2.kspectotrans = knotspec; + kspec.transform(outcpts); + knotspec.istransformed = true; + } + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Subdivider.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Subdivider.java new file mode 100755 index 000000000..99c1b740b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Subdivider.java @@ -0,0 +1,1167 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class working with curves and surfaces + * @author Tomas Hrasky + * + */ +public class Subdivider { + /** + * Cull type + */ + public static final int CULL_TRIVIAL_REJECT = 0; + + /** + * Cull type + */ + public static final int CULL_ACCEPT = 1; + + /** + * Maximum trimming arcs + */ + private static final int MAXARCS = 10; + + /** + * Linked list of Quilts + */ + Quilt qlist; + + /** + * Object holding rendering honts information + */ + private Renderhints renderhints; + + /** + * Backend object + */ + private Backend backend; + + /** + * Number of subdivisions + */ + private int subdivisions; + + /** + * U step when using domain distance sampling + */ + private float domain_distance_u_rate; + + /** + * Use domain distance sampling + */ + private int is_domain_distance_sampling; + + /** + * Initial class holding trimming arcs + */ + private Bin initialbin; + + /** + * Not used + */ + private boolean showDegenerate; + + /** + * Is triming arc type bezier arc + */ + private boolean isArcTypeBezier; + + /** + * Breakpoints in v direction + */ + private Flist tpbrkpts; + + /** + * Breakpoints in u direction + */ + private Flist spbrkpts; + + /** + * Unused + */ + private int s_index; + + /** + * Head of linked list of trimming arcs + */ + private Arc pjarc; + + /** + * Class tesselating trimming arcs + */ + private ArcTesselator arctesselator; + + /** + * Unused + */ + private int t_index; + + /** + * Breakpoints + */ + private Flist smbrkpts; + + /** + * Not used + */ + private float[] stepsizes; + + /** + * Domain distance in V direction + */ + private float domain_distance_v_rate; + + /** + * Initializes quilt list + */ + public void beginQuilts(Backend backend) { + // DONE + qlist = null; + renderhints = new Renderhints(); + this.backend = backend; + + initialbin = new Bin(); + arctesselator = new ArcTesselator(); + } + + /** + * Adds quilt to linked list + * @param quilt added quilt + */ + public void addQuilt(Quilt quilt) { + // DONE + if (qlist == null) + qlist = quilt; + else { + quilt.next = qlist; + qlist = quilt; + } + + } + + /** + * Empty method + */ + public void endQuilts() { + // DONE + } + + /** + * Draws a surface + */ + public void drawSurfaces() { + renderhints.init(); + + if (qlist == null) { + // System.out.println("qlist is null"); + return; + } + + for (Quilt q = qlist; q != null; q = q.next) { + if (q.isCulled() == CULL_TRIVIAL_REJECT) { + freejarcs(initialbin); + return; + } + } + + float[] from = new float[2]; + float[] to = new float[2]; + + spbrkpts = new Flist(); + tpbrkpts = new Flist(); + qlist.getRange(from, to, spbrkpts, tpbrkpts); + + boolean optimize = (is_domain_distance_sampling > 0 && (renderhints.display_method != NurbsConsts.N_OUTLINE_PATCH)); + + // TODO decide whether to optimize (when there is gluNurbsProperty implemented) + optimize = true; + + if (!initialbin.isnonempty()) { + if (!optimize) { + makeBorderTrim(from, to); + } + } else { + float[] rate = new float[2]; + qlist.findRates(spbrkpts, tpbrkpts, rate); + // System.out.println("subdivider.drawsurfaces decompose"); + } + + backend.bgnsurf(renderhints.wiretris, renderhints.wirequads); + + // TODO partition test + + if (!initialbin.isnonempty() && optimize) { + + int i, j; + int num_u_steps; + int num_v_steps; + for (i = spbrkpts.start; i < spbrkpts.end - 1; i++) { + for (j = tpbrkpts.start; j < tpbrkpts.end - 1; j++) { + float[] pta = new float[2]; + float[] ptb = new float[2]; + + pta[0] = spbrkpts.pts[i]; + ptb[0] = spbrkpts.pts[i + 1]; + pta[1] = tpbrkpts.pts[j]; + ptb[1] = tpbrkpts.pts[j + 1]; + qlist.downloadAll(pta, ptb, backend); + + num_u_steps = (int) (domain_distance_u_rate * (ptb[0] - pta[0])); + num_v_steps = (int) (domain_distance_v_rate * (ptb[1] - pta[1])); + + if (num_u_steps <= 0) + num_u_steps = 1; + if (num_v_steps <= 0) + num_v_steps = 1; + + backend.surfgrid(pta[0], ptb[0], num_u_steps, ptb[1], + pta[1], num_v_steps); + backend.surfmesh(0, 0, num_u_steps, num_v_steps); + + } + } + + } else + + subdivideInS(initialbin); + + backend.endsurf(); + } + + /** + * Empty method + * @param initialbin2 + */ + private void freejarcs(Bin initialbin2) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.freejarcs"); + } + + /** + * Subdivide in U direction + * @param source Trimming arcs source + */ + private void subdivideInS(Bin source) { + // DONE + if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM) { + outline(source); + freejarcs(source); + } else { + setArcTypeBezier(); + setNonDegenerate(); + splitInS(source, spbrkpts.start, spbrkpts.end); + } + + } + + /** + * Split in U direction + * @param source Trimming arcs source + * @param start breakpoints start + * @param end breakpoints end + */ + private void splitInS(Bin source, int start, int end) { + // DONE + if (source.isnonempty()) { + if (start != end) { + int i = start + (end - start) / 2; + Bin left = new Bin(); + Bin right = new Bin(); + + split(source, left, right, 0, spbrkpts.pts[i]); + splitInS(left, start, i); + splitInS(right, i + 1, end); + } else { + if (start == spbrkpts.start || start == spbrkpts.end) { + freejarcs(source); + } else if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM_S) { + outline(source); + freejarcs(source); + } else { + setArcTypeBezier(); + setNonDegenerate(); + s_index = start; + splitInT(source, tpbrkpts.start, tpbrkpts.end); + } + } + } else{ + // System.out.println("Source is empty - subdivider.splitins"); + } + } + + /** + * Split in V direction + * @param source + * @param start + * @param end + */ + private void splitInT(Bin source, int start, int end) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.splitint"); + + if (source.isnonempty()) { + if (start != end) { + int i = start + (end - start) / 2; + Bin left = new Bin(); + Bin right = new Bin(); + split(source, left, right, 1, tpbrkpts.pts[i + 1]); + splitInT(left, start, i); + splitInT(right, i + 1, end); + } else { + if (start == tpbrkpts.start || start == tpbrkpts.end) { + freejarcs(source); + } else if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM_ST) { + outline(source); + freejarcs(source); + } else { + t_index = start; + setArcTypeBezier(); + setDegenerate(); + + float[] pta = new float[2]; + float[] ptb = new float[2]; + + pta[0] = spbrkpts.pts[s_index - 1]; + pta[1] = tpbrkpts.pts[t_index - 1]; + + ptb[0] = spbrkpts.pts[s_index]; + ptb[1] = tpbrkpts.pts[t_index]; + qlist.downloadAll(pta, ptb, backend); + + Patchlist patchlist = new Patchlist(qlist, pta, ptb); + + samplingSplit(source, patchlist, + renderhints.maxsubdivisions, 0); + setNonDegenerate(); + setArcTypeBezier(); + } + } + } + + } + + /** + * Sample + * @param source + * @param patchlist + * @param subdivisions + * @param param + */ + private void samplingSplit(Bin source, Patchlist patchlist, + int subdivisions, int param) { + // DONE + if (!source.isnonempty()) + return; + if (patchlist.cullCheck() == CULL_TRIVIAL_REJECT) { + freejarcs(source); + return; + } + + patchlist.getstepsize(); + if (renderhints.display_method == NurbsConsts.N_OUTLINE_PATCH) { + tesselation(source, patchlist); + outline(source); + freejarcs(source); + return; + } + + tesselation(source, patchlist); + if (patchlist.needsSamplingSubdivision() && subdivisions > 0) { + if (!patchlist.needsSubdivision(0)) { + param = 1; + } else if (patchlist.needsSubdivision(1)) + param = 0; + else + param = 1 - param; + + Bin left = new Bin(); + Bin right = new Bin(); + + float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5); + + split(source, left, right, param, mid); + Patchlist subpatchlist = new Patchlist(patchlist, param, mid); + samplingSplit(left, subpatchlist, subdivisions - 1, param); + samplingSplit(right, subpatchlist, subdivisions - 1, param); + } else { + setArcTypePwl(); + setDegenerate(); + nonSamplingSplit(source, patchlist, subdivisions, param); + setDegenerate(); + setArcTypeBezier(); + } + } + + /** + * Not used + * @param source + * @param patchlist + * @param subdivisions + * @param param + */ + private void nonSamplingSplit(Bin source, Patchlist patchlist, + int subdivisions, int param) { + // DONE + if (patchlist.needsNonSamplingSubdivision() && subdivisions > 0) { + param = 1 - param; + + Bin left = new Bin(); + Bin right = new Bin(); + + float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5); + split(source, left, right, param, mid); + Patchlist subpatchlist = new Patchlist(patchlist, param, mid); + if (left.isnonempty()) { + if (subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT) + freejarcs(left); + else + nonSamplingSplit(left, subpatchlist, subdivisions - 1, + param); + } + if (right.isnonempty()) { + if (patchlist.cullCheck() == CULL_TRIVIAL_REJECT) + freejarcs(right); + else + nonSamplingSplit(right, subpatchlist, subdivisions - 1, + param); + } + } else { + patchlist.bbox(); + backend.patch(patchlist.pspec[0].range[0], + patchlist.pspec[0].range[1], patchlist.pspec[1].range[0], + patchlist.pspec[1].range[1]); + if (renderhints.display_method == NurbsConsts.N_OUTLINE_SUBDIV) { + outline(source); + freejarcs(source); + } else { + setArcTypePwl(); + setDegenerate(); + findIrregularS(source); + monosplitInS(source, smbrkpts.start, smbrkpts.end); + } + } + + } + + /** + * Not used + * @param source + * @param start + * @param end + */ + private void monosplitInS(Bin source, int start, int end) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.monosplitins"); + } + + /** + * Not used + * @param source + */ + private void findIrregularS(Bin source) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.findIrregularS"); + } + + /** + * Not used + */ + private void setArcTypePwl() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.setarctypepwl"); + } + + /** + * Not used + * @param source + * @param patchlist + */ + private void tesselation(Bin source, Patchlist patchlist) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.tesselation"); + } + + /** + * Not used + */ + private void setDegenerate() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.setdegenerate"); + } + + /** + * Not used + * @param bin + * @param left + * @param right + * @param param + * @param value + */ + private void split(Bin bin, Bin left, Bin right, int param, float value) { + // DONE + Bin intersections = new Bin(); + Bin unknown = new Bin(); + + partition(bin, left, intersections, right, unknown, param, value); + + int count = intersections.numarcs(); + // TODO jumpbuffer ?? + + if (count % 2 == 0) { + + Arc[] arclist = new Arc[MAXARCS]; + CArrayOfArcs list; + if (count >= MAXARCS) { + list = new CArrayOfArcs(new Arc[count]); + } else { + list = new CArrayOfArcs(arclist); + } + + CArrayOfArcs last, lptr; + Arc jarc; + + for (last = new CArrayOfArcs(list); (jarc = intersections + .removearc()) != null; last.pp()) + last.set(jarc); + + if (param == 0) {// sort into incrasing t order + ArcSdirSorter sorter = new ArcSdirSorter(this); + sorter.qsort(list, count); + + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + check_s(lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + join_s(left, right, lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() != last + .getPointer(); lptr.pp()) { + if (lptr.get().head()[0] <= value + && lptr.get().tail()[0] <= value) + left.addarc(lptr.get()); + else + right.addarc(lptr.get()); + } + + } else {// sort into decreasing s order + ArcTdirSorter sorter = new ArcTdirSorter(this); + sorter.qsort(list, count); + + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + check_t(lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + join_t(left, right, lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() != last + .getPointer(); lptr.raisePointerBy(2)) { + if (lptr.get().head()[0] <= value + && lptr.get().tail()[0] <= value) + left.addarc(lptr.get()); + else + right.addarc(lptr.get()); + } + + } + + unknown.adopt(); + } + } + + /** + * Not used + * @param left + * @param right + * @param arc + * @param relative + */ + private void join_t(Bin left, Bin right, Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.join_t"); + } + + /** + * Not used + * @param arc + * @param relative + */ + private void check_t(Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.check_t"); + } + + /** + * Not used + * @param left + * @param right + * @param jarc1 + * @param jarc2 + */ + private void join_s(Bin left, Bin right, Arc jarc1, Arc jarc2) { + // DONE + if (!jarc1.getitail()) + jarc1 = jarc1.next; + if (!jarc2.getitail()) + jarc2 = jarc2.next; + + float s = jarc1.tail()[0]; + float t1 = jarc1.tail()[1]; + float t2 = jarc2.tail()[1]; + + if (t1 == t2) { + simplelink(jarc1, jarc2); + } else { + Arc newright = new Arc(Arc.ARC_RIGHT); + Arc newleft = new Arc(Arc.ARC_LEFT); + if (isBezierArcType()) { + arctesselator.bezier(newright, s, s, t1, t2); + arctesselator.bezier(newleft, s, s, t2, t1); + } else { + arctesselator.pwl_right(newright, s, t1, t2, stepsizes[0]); + arctesselator.pwl_left(newright, s, t2, t1, stepsizes[2]); + } + link(jarc1, jarc2, newright, newleft); + left.addarc(newright); + right.addarc(newleft); + } + + } + + /** + * Not used + * @param jarc1 + * @param jarc2 + * @param newright + * @param newleft + */ + private void link(Arc jarc1, Arc jarc2, Arc newright, Arc newleft) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.link"); + } + + /** + * Not used + * @return true + */ + private boolean isBezierArcType() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.isbezierarc"); + return true; + } + + /** + * Not used + * @param jarc1 + * @param jarc2 + */ + private void simplelink(Arc jarc1, Arc jarc2) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.simplelink"); + } + + /** + * Not used + * @param arc + * @param relative + */ + private void check_s(Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.check_s"); + + } + + /** + * Not used + * @param bin + * @param left + * @param intersections + * @param right + * @param unknown + * @param param + * @param value + */ + private void partition(Bin bin, Bin left, Bin intersections, Bin right, + Bin unknown, int param, float value) { + + Bin headonleft = new Bin(); + Bin headonright = new Bin(); + Bin tailonleft = new Bin(); + Bin tailonright = new Bin(); + + for (Arc jarc = bin.removearc(); jarc != null; jarc = bin.removearc()) { + float tdiff = jarc.tail()[param] - value; + float hdiff = jarc.head()[param] - value; + + if (tdiff > 0) { + if (hdiff > 0) { + right.addarc(jarc); + } else if (hdiff == 0) { + tailonright.addarc(jarc); + } else { + Arc jtemp; + switch (arc_split(jarc, param, value, 0)) { + case 2: + tailonright.addarc(jarc); + headonleft.addarc(jarc.next); + break; + // TODO rest cases + default: + System.out + .println("TODO subdivider.partition rest cases"); + break; + } + } + } else if (tdiff == 0) { + if (hdiff > 0) { + headonright.addarc(jarc); + } else if (hdiff == 0) { + unknown.addarc(jarc); + } else { + headonright.addarc(jarc); + } + } else { + if (hdiff > 0) { + // TODO rest + // System.out.println("TODO subdivider.partition rest of else"); + } else if (hdiff == 0) { + tailonleft.addarc(jarc); + } else { + left.addarc(jarc); + } + } + + } + if (param == 0) { + classify_headonleft_s(headonleft, intersections, left, value); + classify_tailonleft_s(tailonleft, intersections, left, value); + classify_headonright_s(headonright, intersections, right, value); + classify_tailonright_s(tailonright, intersections, right, value); + } else { + classify_headonleft_t(headonleft, intersections, left, value); + classify_tailonleft_t(tailonleft, intersections, left, value); + classify_headonright_t(headonright, intersections, right, value); + classify_tailonright_t(tailonright, intersections, right, value); + } + } + + /** + * Not used + * @param tailonright + * @param intersections + * @param right + * @param value + */ + private void classify_tailonright_t(Bin tailonright, Bin intersections, + Bin right, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_tailonright_t"); + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_tailonleft_s(Bin bin, Bin in, Bin out, float val) { + + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.clearitail(); + + float diff = j.next.head()[0] - val; + if (diff > 0) { + in.addarc(j); + } else if (diff < 0) { + if (ccwTurn_sl(j, j.next)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.next.tail()[1] > j.next.head()[1]) + in.addarc(j); + else + out.addarc(j); + } + } + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonright_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[0] - val; + if (diff > 0) { + if (ccwTurn_sr(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else if (diff < 0) { + out.addarc(j); + } else { + if (j.prev.tail()[1] > j.prev.head()[1]) + out.addarc(j); + else + in.addarc(j); + } + } + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_sr(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO ccwTurn_sr"); + return false; + } + + /** + * Not used + * @param headonright + * @param intersections + * @param right + * @param value + */ + private void classify_headonright_t(Bin headonright, Bin intersections, + Bin right, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_headonright_t"); + } + + /** + * Not used + * @param tailonleft + * @param intersections + * @param left + * @param value + */ + private void classify_tailonleft_t(Bin tailonleft, Bin intersections, + Bin left, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_tailonleft_t"); + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonleft_t(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[1] - val; + if (diff > 0) { + out.addarc(j); + } else if (diff < 0) { + if (ccwTurn_tl(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.prev.tail()[0] > j.prev.head()[0]) + out.addarc(j); + else + in.addarc(j); + } + } + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_tl(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.ccwTurn_tl"); + return false; + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_tailonright_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.clearitail(); + + float diff = j.next.head()[0] - val; + if (diff > 0) { + if (ccwTurn_sr(j, j.next)) + out.addarc(j); + else + in.addarc(j); + } else if (diff < 0) { + in.addarc(j); + } else { + if (j.next.tail()[1] > j.next.head()[1]) + out.addarc(j); + else + in.addarc(j); + } + } + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonleft_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[0] - val; + if (diff > 0) { + out.addarc(j); + } else if (diff < 0) { + if (ccwTurn_sl(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.prev.tail()[1] > j.prev.head()[1]) + in.addarc(j); + else + out.addarc(j); + } + } + + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_sl(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.ccwTurn_sl"); + return false; + } + + /** + * Not used + * @param jarc + * @param param + * @param value + * @param i + * @return 0 + */ + private int arc_split(Arc jarc, int param, float value, int i) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.arc_split"); + return 0; + } + + /** + * Not used + */ + private void setNonDegenerate() { + // DONE + this.showDegenerate = false; + + } + + /** + * sets trimming arc default type to bezier + */ + private void setArcTypeBezier() { + // DONE + isArcTypeBezier = true; + } + + /** + * Not used + * @param source + */ + private void outline(Bin source) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.outline"); + } + + /** + * Makes default trim along surface borders + * @param from range beginnings + * @param to range ends + */ + private void makeBorderTrim(float[] from, float[] to) { + // DONE + float smin = from[0]; + float smax = to[0]; + + float tmin = from[1]; + float tmax = to[1]; + + pjarc = null; + Arc jarc = null; + + jarc = new Arc(Arc.ARC_BOTTOM); + arctesselator.bezier(jarc, smin, smax, tmin, tmin); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_RIGHT); + arctesselator.bezier(jarc, smax, smax, tmin, tmax); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_TOP); + arctesselator.bezier(jarc, smax, smin, tmax, tmax); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_LEFT); + arctesselator.bezier(jarc, smin, smin, tmax, tmin); + initialbin.addarc(jarc); + jarc = jarc.append(pjarc); + + // assert (jarc.check() == true); + } + + /** + * Draws NURBS curve + */ + public void drawCurves() { + // DONE + float[] from = new float[1]; + float[] to = new float[1]; + + Flist bpts = new Flist(); + qlist.getRange(from, to, bpts); + + renderhints.init(); + + backend.bgncurv(); + + for (int i = bpts.start; i < bpts.end - 1; i++) { + float[] pta = new float[1]; + float[] ptb = new float[1]; + pta[0] = bpts.pts[i]; + ptb[0] = bpts.pts[i + 1]; + + qlist.downloadAll(pta, ptb, backend); + Curvelist curvelist = new Curvelist(qlist, pta, ptb); + samplingSplit(curvelist, renderhints.maxsubdivisions); + } + backend.endcurv(); + } + + /** + * Samples a curve in case of need, or sends curve to backend + * @param curvelist list of curves + * @param maxsubdivisions maximum number of subdivisions + */ + private void samplingSplit(Curvelist curvelist, int maxsubdivisions) { + if (curvelist.cullCheck() == CULL_TRIVIAL_REJECT) + return; + + curvelist.getstepsize(); + + if (curvelist.needsSamplingSubdivision() && (subdivisions > 0)) { + // TODO kód + // System.out.println("TODO subdivider-needsSamplingSubdivision"); + } else { + int nu = (int) (1 + curvelist.range[2] / curvelist.stepsize); + backend.curvgrid(curvelist.range[0], curvelist.range[1], nu); + backend.curvmesh(0, nu); + } + + } + + /** + * Sets new domain_distance_u_rate value + * @param d new domain_distance_u_rate value + + */ + public void set_domain_distance_u_rate(double d) { + // DONE + domain_distance_u_rate = (float) d; + } + + /** + * Sets new domain_distance_v_rate value + * @param d new domain_distance_v_rate value + */ + public void set_domain_distance_v_rate(double d) { + // DONE + domain_distance_v_rate = (float) d; + } + + /** + * Sets new is_domain_distance_sampling value + * @param i new is_domain_distance_sampling value + */ + public void set_is_domain_distance_sampling(int i) { + // DONE + this.is_domain_distance_sampling = i; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/SurfaceEvaluator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/SurfaceEvaluator.java new file mode 100755 index 000000000..fe23f9c08 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/SurfaceEvaluator.java @@ -0,0 +1,111 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class rendering surfaces with OpenGL + * @author Tomas Hrasky + * + */ +public interface SurfaceEvaluator { + + /** + * Pushes eval bit + */ + public void bgnmap2f() ; + + /** + * Sets glPolygonMode + * @param style polygon mode (N_MESHFILL/N_MESHLINE/N_MESHPOINT) + */ + public void polymode(int style) ; + + /** + * Pops all attributes + */ + public void endmap2f() ; + + /** + * Empty method + * @param ulo + * @param uhi + * @param vlo + * @param vhi + */ + public void domain2f(float ulo, float uhi, float vlo, float vhi) ; + + /** + * Defines 2D mesh + * @param nu number of steps in u direction + * @param u0 lowest u + * @param u1 highest u + * @param nv number of steps in v direction + * @param v0 lowest v + * @param v1 highest v + */ + public void mapgrid2f(int nu, float u0, float u1, int nv, float v0, float v1) ; + + /** + * Evaluates surface + * @param style surface style + * @param umin minimum U + * @param umax maximum U + * @param vmin minimum V + * @param vmax maximum V + */ + public void mapmesh2f(int style, int umin, int umax, int vmin, int vmax) ; + + /** + * Initializes evaluator + * @param type surface type + * @param ulo lowest u + * @param uhi highest u + * @param ustride number of objects between control points in u direction + * @param uorder surface order in u direction + * @param vlo lowest v + * @param vhi highest v + * @param vstride number of control points' coords + * @param vorder surface order in v direction + * @param pts control points + */ + public void map2f(int type, float ulo, float uhi, int ustride, int uorder, + float vlo, float vhi, int vstride, int vorder, CArrayOfFloats pts) ; + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) ; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/TrimVertex.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/TrimVertex.java new file mode 100755 index 000000000..6608f8f40 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/TrimVertex.java @@ -0,0 +1,56 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Holds vertex used in trim + * + * @author Tomas Hrasky + * + */ +public class TrimVertex { + + /** + * Trim vertex coords + */ + public float[] param; + + /** + * Makes new empty trim vertex + */ + public TrimVertex() { + param = new float[2]; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/registry/Registry.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/registry/Registry.java new file mode 100644 index 000000000..21b15f4d4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/registry/Registry.java @@ -0,0 +1,79 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.registry; + +import javax.media.opengl.glu.GLU; + +/** + * + * @author Administrator + */ +public class Registry { + + /** Creates a new instance of Registry */ + public Registry() { + } + + public static String gluGetString(int name) { + if( name == GLU.GLU_VERSION ) { + return( "1.3" ); + } else if( name == GLU.GLU_EXTENSIONS ) { + return( "GLU_EXT_nurbs_tessellator GLU_EXT_object_space_tess " ); + } + return( null ); + } + + public static boolean gluCheckExtension( String extName, String extString ) { + if( extName == null || extString == null ) { + return( false ); + } + if ((extString.indexOf(extName + " ") >= 0) || + extString.endsWith(extName) || + extString.equals(extName)) { + return true; + } + return false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/ActiveRegion.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/ActiveRegion.java new file mode 100644 index 000000000..85397dd6a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/ActiveRegion.java @@ -0,0 +1,69 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + + +class ActiveRegion { + GLUhalfEdge eUp; /* upper edge, directed right to left */ + DictNode nodeUp; /* dictionary node corresponding to eUp */ + int windingNumber; /* used to determine which regions are + * inside the polygon */ + boolean inside; /* is this region inside the polygon? */ + boolean sentinel; /* marks fake edges at t = +/-infinity */ + boolean dirty; /* marks regions where the upper or lower + * edge has changed, but we haven't checked + * whether they intersect yet */ + boolean fixUpperEdge; /* marks temporary edges introduced when + * we process a "right vertex" (one without + * any edges leaving to the right) */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/CachedVertex.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/CachedVertex.java new file mode 100644 index 000000000..8948acfec --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/CachedVertex.java @@ -0,0 +1,58 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class CachedVertex { + public double[] coords = new double[3]; + public Object data; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Dict.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Dict.java new file mode 100644 index 000000000..d26948e7f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Dict.java @@ -0,0 +1,140 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class Dict { + DictNode head; + Object frame; + DictLeq leq; + + private Dict() { + } + + static Dict dictNewDict(Object frame, DictLeq leq) { + Dict dict = new Dict(); + dict.head = new DictNode(); + + dict.head.key = null; + dict.head.next = dict.head; + dict.head.prev = dict.head; + + dict.frame = frame; + dict.leq = leq; + + return dict; + } + + static void dictDeleteDict(Dict dict) { + dict.head = null; + dict.frame = null; + dict.leq = null; + } + + static DictNode dictInsert(Dict dict, Object key) { + return dictInsertBefore(dict, dict.head, key); + } + + static DictNode dictInsertBefore(Dict dict, DictNode node, Object key) { + do { + node = node.prev; + } while (node.key != null && !dict.leq.leq(dict.frame, node.key, key)); + + DictNode newNode = new DictNode(); + newNode.key = key; + newNode.next = node.next; + node.next.prev = newNode; + newNode.prev = node; + node.next = newNode; + + return newNode; + } + + static Object dictKey(DictNode aNode) { + return aNode.key; + } + + static DictNode dictSucc(DictNode aNode) { + return aNode.next; + } + + static DictNode dictPred(DictNode aNode) { + return aNode.prev; + } + + static DictNode dictMin(Dict aDict) { + return aDict.head.next; + } + + static DictNode dictMax(Dict aDict) { + return aDict.head.prev; + } + + static void dictDelete(Dict dict, DictNode node) { + node.next.prev = node.prev; + node.prev.next = node.next; + } + + static DictNode dictSearch(Dict dict, Object key) { + DictNode node = dict.head; + + do { + node = node.next; + } while (node.key != null && !(dict.leq.leq(dict.frame, key, node.key))); + + return node; + } + + public interface DictLeq { + boolean leq(Object frame, Object key1, Object key2); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/DictNode.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/DictNode.java new file mode 100644 index 000000000..8864de127 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/DictNode.java @@ -0,0 +1,59 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class DictNode { + Object key; + DictNode next; + DictNode prev; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUface.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUface.java new file mode 100644 index 000000000..2ff4aae59 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUface.java @@ -0,0 +1,65 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class GLUface { + public GLUface next; /* next face (never NULL) */ + public GLUface prev; /* previous face (never NULL) */ + public GLUhalfEdge anEdge; /* a half edge with this left face */ + public Object data; /* room for client's data */ + + /* Internal data (keep hidden) */ + public GLUface trail; /* "stack" for conversion to strips */ + public boolean marked; /* flag for conversion to strips */ + public boolean inside; /* this face is in the polygon interior */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUhalfEdge.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUhalfEdge.java new file mode 100644 index 000000000..c2128b616 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUhalfEdge.java @@ -0,0 +1,71 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class GLUhalfEdge { + public GLUhalfEdge next; /* doubly-linked list (prev==Sym->next) */ + public GLUhalfEdge Sym; /* same edge, opposite direction */ + public GLUhalfEdge Onext; /* next edge CCW around origin */ + public GLUhalfEdge Lnext; /* next edge CCW around left face */ + public GLUvertex Org; /* origin vertex (Overtex too long) */ + public com.jogamp.opengl.impl.glu.tessellator.GLUface Lface; /* left face */ + + /* Internal data (keep hidden) */ + public com.jogamp.opengl.impl.glu.tessellator.ActiveRegion activeRegion; /* a region with this upper edge (sweep.c) */ + public int winding; /* change in winding number when crossing */ + public boolean first; + + public GLUhalfEdge(boolean first) { + this.first = first; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUmesh.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUmesh.java new file mode 100644 index 000000000..493eb20f4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUmesh.java @@ -0,0 +1,60 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class GLUmesh { + GLUvertex vHead = new GLUvertex(); /* dummy header for vertex list */ + com.jogamp.opengl.impl.glu.tessellator.GLUface fHead = new GLUface(); /* dummy header for face list */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eHead = new GLUhalfEdge(true); /* dummy header for edge list */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eHeadSym = new GLUhalfEdge(false); /* and its symmetric counterpart */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUtessellatorImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUtessellatorImpl.java new file mode 100644 index 000000000..b21998355 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUtessellatorImpl.java @@ -0,0 +1,646 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +import com.jogamp.opengl.impl.glu.tessellator.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +public class GLUtessellatorImpl implements GLUtessellator { + public static final int TESS_MAX_CACHE = 100; + + private int state; /* what begin/end calls have we seen? */ + + private GLUhalfEdge lastEdge; /* lastEdge->Org is the most recent vertex */ + GLUmesh mesh; /* stores the input contours, and eventually + the tessellation itself */ + + /*** state needed for projecting onto the sweep plane ***/ + + double[] normal = new double[3]; /* user-specified normal (if provided) */ + double[] sUnit = new double[3]; /* unit vector in s-direction (debugging) */ + double[] tUnit = new double[3]; /* unit vector in t-direction (debugging) */ + + /*** state needed for the line sweep ***/ + + private double relTolerance; /* tolerance for merging features */ + int windingRule; /* rule for determining polygon interior */ + boolean fatalError; /* fatal error: needed combine callback */ + + Dict dict; /* edge dictionary for sweep line */ + PriorityQ pq; /* priority queue of vertex events */ + GLUvertex event; /* current sweep event being processed */ + + /*** state needed for rendering callbacks (see render.c) ***/ + + boolean flagBoundary; /* mark boundary edges (use EdgeFlag) */ + boolean boundaryOnly; /* Extract contours, not triangles */ + boolean avoidDegenerateTris; /* JOGL-specific hint to try to improve triangulation + by avoiding producing degenerate (zero-area) triangles; + has not been tested exhaustively and is therefore an option */ + + GLUface lonelyTriList; + /* list of triangles which could not be rendered as strips or fans */ + + + + /*** state needed to cache single-contour polygons for renderCache() */ + + private boolean flushCacheOnNextVertex; /* empty cache on next vertex() call */ + int cacheCount; /* number of cached vertices */ + CachedVertex[] cache = new CachedVertex[TESS_MAX_CACHE]; /* the vertex data */ + + /*** rendering callbacks that also pass polygon data ***/ + private Object polygonData; /* client data for current polygon */ + + private GLUtessellatorCallback callBegin; + private GLUtessellatorCallback callEdgeFlag; + private GLUtessellatorCallback callVertex; + private GLUtessellatorCallback callEnd; +// private GLUtessellatorCallback callMesh; + private GLUtessellatorCallback callError; + private GLUtessellatorCallback callCombine; + + private GLUtessellatorCallback callBeginData; + private GLUtessellatorCallback callEdgeFlagData; + private GLUtessellatorCallback callVertexData; + private GLUtessellatorCallback callEndData; +// private GLUtessellatorCallback callMeshData; + private GLUtessellatorCallback callErrorData; + private GLUtessellatorCallback callCombineData; + + private static final double GLU_TESS_DEFAULT_TOLERANCE = 0.0; +// private static final int GLU_TESS_MESH = 100112; /* void (*)(GLUmesh *mesh) */ + private static GLUtessellatorCallback NULL_CB = new GLUtessellatorCallbackAdapter(); + +// #define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \ +// MAX(sizeof(GLUvertex),sizeof(GLUface)))) + + private GLUtessellatorImpl() { + state = TessState.T_DORMANT; + + normal[0] = 0; + normal[1] = 0; + normal[2] = 0; + + relTolerance = GLU_TESS_DEFAULT_TOLERANCE; + windingRule = GLU.GLU_TESS_WINDING_ODD; + flagBoundary = false; + boundaryOnly = false; + + callBegin = NULL_CB; + callEdgeFlag = NULL_CB; + callVertex = NULL_CB; + callEnd = NULL_CB; + callError = NULL_CB; + callCombine = NULL_CB; +// callMesh = NULL_CB; + + callBeginData = NULL_CB; + callEdgeFlagData = NULL_CB; + callVertexData = NULL_CB; + callEndData = NULL_CB; + callErrorData = NULL_CB; + callCombineData = NULL_CB; + + polygonData = null; + + for (int i = 0; i < cache.length; i++) { + cache[i] = new CachedVertex(); + } + } + + static public GLUtessellator gluNewTess() + { + return new GLUtessellatorImpl(); + } + + + private void makeDormant() { + /* Return the tessellator to its original dormant state. */ + + if (mesh != null) { + Mesh.__gl_meshDeleteMesh(mesh); + } + state = TessState.T_DORMANT; + lastEdge = null; + mesh = null; + } + + private void requireState(int newState) { + if (state != newState) gotoState(newState); + } + + private void gotoState(int newState) { + while (state != newState) { + /* We change the current state one level at a time, to get to + * the desired state. + */ + if (state < newState) { + if (state == TessState.T_DORMANT) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_BEGIN_POLYGON); + gluTessBeginPolygon(null); + } else if (state == TessState.T_IN_POLYGON) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_BEGIN_CONTOUR); + gluTessBeginContour(); + } + } else { + if (state == TessState.T_IN_CONTOUR) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_END_CONTOUR); + gluTessEndContour(); + } else if (state == TessState.T_IN_POLYGON) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_END_POLYGON); + /* gluTessEndPolygon( tess ) is too much work! */ + makeDormant(); + } + } + } + } + + public void gluDeleteTess() { + requireState(TessState.T_DORMANT); + } + + public void gluTessProperty(int which, double value) { + switch (which) { + case GLU.GLU_TESS_TOLERANCE: + if (value < 0.0 || value > 1.0) break; + relTolerance = value; + return; + + case GLU.GLU_TESS_WINDING_RULE: + int windingRule = (int) value; + if (windingRule != value) break; /* not an integer */ + + switch (windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + case GLU.GLU_TESS_WINDING_NONZERO: + case GLU.GLU_TESS_WINDING_POSITIVE: + case GLU.GLU_TESS_WINDING_NEGATIVE: + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + this.windingRule = windingRule; + return; + default: + break; + } + + case GLU.GLU_TESS_BOUNDARY_ONLY: + boundaryOnly = (value != 0); + return; + + case GLU.GLU_TESS_AVOID_DEGENERATE_TRIANGLES: + avoidDegenerateTris = (value != 0); + return; + + default: + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + return; + } + callErrorOrErrorData(GLU.GLU_INVALID_VALUE); + } + +/* Returns tessellator property */ + public void gluGetTessProperty(int which, double[] value, int value_offset) { + switch (which) { + case GLU.GLU_TESS_TOLERANCE: +/* tolerance should be in range [0..1] */ + assert (0.0 <= relTolerance && relTolerance <= 1.0); + value[value_offset] = relTolerance; + break; + case GLU.GLU_TESS_WINDING_RULE: + assert (windingRule == GLU.GLU_TESS_WINDING_ODD || + windingRule == GLU.GLU_TESS_WINDING_NONZERO || + windingRule == GLU.GLU_TESS_WINDING_POSITIVE || + windingRule == GLU.GLU_TESS_WINDING_NEGATIVE || + windingRule == GLU.GLU_TESS_WINDING_ABS_GEQ_TWO); + value[value_offset] = windingRule; + break; + case GLU.GLU_TESS_BOUNDARY_ONLY: + assert (boundaryOnly == true || boundaryOnly == false); + value[value_offset] = boundaryOnly ? 1 : 0; + break; + case GLU.GLU_TESS_AVOID_DEGENERATE_TRIANGLES: + value[value_offset] = avoidDegenerateTris ? 1 : 0; + break; + default: + value[value_offset] = 0.0; + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + break; + } + } /* gluGetTessProperty() */ + + public void gluTessNormal(double x, double y, double z) { + normal[0] = x; + normal[1] = y; + normal[2] = z; + } + + public void gluTessCallback(int which, GLUtessellatorCallback aCallback) { + switch (which) { + case GLU.GLU_TESS_BEGIN: + callBegin = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_BEGIN_DATA: + callBeginData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_EDGE_FLAG: + callEdgeFlag = aCallback == null ? NULL_CB : aCallback; +/* If the client wants boundary edges to be flagged, + * we render everything as separate triangles (no strips or fans). + */ + flagBoundary = aCallback != null; + return; + case GLU.GLU_TESS_EDGE_FLAG_DATA: + callEdgeFlagData = callBegin = aCallback == null ? NULL_CB : aCallback; +/* If the client wants boundary edges to be flagged, + * we render everything as separate triangles (no strips or fans). + */ + flagBoundary = (aCallback != null); + return; + case GLU.GLU_TESS_VERTEX: + callVertex = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_VERTEX_DATA: + callVertexData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_END: + callEnd = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_END_DATA: + callEndData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_ERROR: + callError = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_ERROR_DATA: + callErrorData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_COMBINE: + callCombine = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_COMBINE_DATA: + callCombineData = aCallback == null ? NULL_CB : aCallback; + return; +// case GLU_TESS_MESH: +// callMesh = aCallback == null ? NULL_CB : aCallback; +// return; + default: + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + return; + } + } + + private boolean addVertex(double[] coords, Object vertexData) { + GLUhalfEdge e; + + e = lastEdge; + if (e == null) { +/* Make a self-loop (one vertex, one edge). */ + + e = Mesh.__gl_meshMakeEdge(mesh); + if (e == null) return false; + if (!Mesh.__gl_meshSplice(e, e.Sym)) return false; + } else { +/* Create a new vertex and edge which immediately follow e + * in the ordering around the left face. + */ + if (Mesh.__gl_meshSplitEdge(e) == null) return false; + e = e.Lnext; + } + +/* The new vertex is now e.Org. */ + e.Org.data = vertexData; + e.Org.coords[0] = coords[0]; + e.Org.coords[1] = coords[1]; + e.Org.coords[2] = coords[2]; + +/* The winding of an edge says how the winding number changes as we + * cross from the edge''s right face to its left face. We add the + * vertices in such an order that a CCW contour will add +1 to + * the winding number of the region inside the contour. + */ + e.winding = 1; + e.Sym.winding = -1; + + lastEdge = e; + + return true; + } + + private void cacheVertex(double[] coords, Object vertexData) { + if (cache[cacheCount] == null) { + cache[cacheCount] = new CachedVertex(); + } + + CachedVertex v = cache[cacheCount]; + + v.data = vertexData; + v.coords[0] = coords[0]; + v.coords[1] = coords[1]; + v.coords[2] = coords[2]; + ++cacheCount; + } + + + private boolean flushCache() { + CachedVertex[] v = cache; + + mesh = Mesh.__gl_meshNewMesh(); + if (mesh == null) return false; + + for (int i = 0; i < cacheCount; i++) { + CachedVertex vertex = v[i]; + if (!addVertex(vertex.coords, vertex.data)) return false; + } + cacheCount = 0; + flushCacheOnNextVertex = false; + + return true; + } + + public void gluTessVertex(double[] coords, int coords_offset, Object vertexData) { + int i; + boolean tooLarge = false; + double x; + double[] clamped = new double[3]; + + requireState(TessState.T_IN_CONTOUR); + + if (flushCacheOnNextVertex) { + if (!flushCache()) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + return; + } + lastEdge = null; + } + for (i = 0; i < 3; ++i) { + x = coords[i+coords_offset]; + if (x < -GLU.GLU_TESS_MAX_COORD) { + x = -GLU.GLU_TESS_MAX_COORD; + tooLarge = true; + } + if (x > GLU.GLU_TESS_MAX_COORD) { + x = GLU.GLU_TESS_MAX_COORD; + tooLarge = true; + } + clamped[i] = x; + } + if (tooLarge) { + callErrorOrErrorData(GLU.GLU_TESS_COORD_TOO_LARGE); + } + + if (mesh == null) { + if (cacheCount < TESS_MAX_CACHE) { + cacheVertex(clamped, vertexData); + return; + } + if (!flushCache()) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + return; + } + } + + if (!addVertex(clamped, vertexData)) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + } + } + + + public void gluTessBeginPolygon(Object data) { + requireState(TessState.T_DORMANT); + + state = TessState.T_IN_POLYGON; + cacheCount = 0; + flushCacheOnNextVertex = false; + mesh = null; + + polygonData = data; + } + + + public void gluTessBeginContour() { + requireState(TessState.T_IN_POLYGON); + + state = TessState.T_IN_CONTOUR; + lastEdge = null; + if (cacheCount > 0) { +/* Just set a flag so we don't get confused by empty contours + * -- these can be generated accidentally with the obsolete + * NextContour() interface. + */ + flushCacheOnNextVertex = true; + } + } + + + public void gluTessEndContour() { + requireState(TessState.T_IN_CONTOUR); + state = TessState.T_IN_POLYGON; + } + + public void gluTessEndPolygon() { + GLUmesh mesh; + + try { + requireState(TessState.T_IN_POLYGON); + state = TessState.T_DORMANT; + + if (this.mesh == null) { + if (!flagBoundary /*&& callMesh == NULL_CB*/) { + +/* Try some special code to make the easy cases go quickly + * (eg. convex polygons). This code does NOT handle multiple contours, + * intersections, edge flags, and of course it does not generate + * an explicit mesh either. + */ + if (Render.__gl_renderCache(this)) { + polygonData = null; + return; + } + } + if (!flushCache()) throw new RuntimeException(); /* could've used a label*/ + } + +/* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + Normal.__gl_projectPolygon(this); + +/* __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by windingRule. + * Each interior region is guaranteed be monotone. + */ + if (!Sweep.__gl_computeInterior(this)) { + throw new RuntimeException(); /* could've used a label */ + } + + mesh = this.mesh; + if (!fatalError) { + boolean rc = true; + +/* If the user wants only the boundary contours, we throw away all edges + * except those which separate the interior from the exterior. + * Otherwise we tessellate all the regions marked "inside". + */ + if (boundaryOnly) { + rc = TessMono.__gl_meshSetWindingNumber(mesh, 1, true); + } else { + rc = TessMono.__gl_meshTessellateInterior(mesh, avoidDegenerateTris); + } + if (!rc) throw new RuntimeException(); /* could've used a label */ + + Mesh.__gl_meshCheckMesh(mesh); + + if (callBegin != NULL_CB || callEnd != NULL_CB + || callVertex != NULL_CB || callEdgeFlag != NULL_CB + || callBeginData != NULL_CB + || callEndData != NULL_CB + || callVertexData != NULL_CB + || callEdgeFlagData != NULL_CB) { + if (boundaryOnly) { + Render.__gl_renderBoundary(this, mesh); /* output boundary contours */ + } else { + Render.__gl_renderMesh(this, mesh); /* output strips and fans */ + } + } +// if (callMesh != NULL_CB) { +// +///* Throw away the exterior faces, so that all faces are interior. +// * This way the user doesn't have to check the "inside" flag, +// * and we don't need to even reveal its existence. It also leaves +// * the freedom for an implementation to not generate the exterior +// * faces in the first place. +// */ +// TessMono.__gl_meshDiscardExterior(mesh); +// callMesh.mesh(mesh); /* user wants the mesh itself */ +// mesh = null; +// polygonData = null; +// return; +// } + } + Mesh.__gl_meshDeleteMesh(mesh); + polygonData = null; + mesh = null; + } catch (Exception e) { + e.printStackTrace(); + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + } + } + + /*******************************************************/ + +/* Obsolete calls -- for backward compatibility */ + + public void gluBeginPolygon() { + gluTessBeginPolygon(null); + gluTessBeginContour(); + } + + +/*ARGSUSED*/ + public void gluNextContour(int type) { + gluTessEndContour(); + gluTessBeginContour(); + } + + + public void gluEndPolygon() { + gluTessEndContour(); + gluTessEndPolygon(); + } + + void callBeginOrBeginData(int a) { + if (callBeginData != NULL_CB) + callBeginData.beginData(a, polygonData); + else + callBegin.begin(a); + } + + void callVertexOrVertexData(Object a) { + if (callVertexData != NULL_CB) + callVertexData.vertexData(a, polygonData); + else + callVertex.vertex(a); + } + + void callEdgeFlagOrEdgeFlagData(boolean a) { + if (callEdgeFlagData != NULL_CB) + callEdgeFlagData.edgeFlagData(a, polygonData); + else + callEdgeFlag.edgeFlag(a); + } + + void callEndOrEndData() { + if (callEndData != NULL_CB) + callEndData.endData(polygonData); + else + callEnd.end(); + } + + void callCombineOrCombineData(double[] coords, Object[] vertexData, float[] weights, Object[] outData) { + if (callCombineData != NULL_CB) + callCombineData.combineData(coords, vertexData, weights, outData, polygonData); + else + callCombine.combine(coords, vertexData, weights, outData); + } + + void callErrorOrErrorData(int a) { + if (callErrorData != NULL_CB) + callErrorData.errorData(a, polygonData); + else + callError.error(a); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUvertex.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUvertex.java new file mode 100644 index 000000000..af294caad --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUvertex.java @@ -0,0 +1,65 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class GLUvertex { + public GLUvertex next; /* next vertex (never NULL) */ + public GLUvertex prev; /* previous vertex (never NULL) */ + public com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge anEdge; /* a half-edge with this origin */ + public Object data; /* client's data */ + + /* Internal data (keep hidden) */ + public double[] coords = new double[3]; /* vertex location in 3D */ + public double s, t; /* projection onto the sweep plane */ + public int pqHandle; /* to allow deletion from priority queue */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Geom.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Geom.java new file mode 100644 index 000000000..2710346d1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Geom.java @@ -0,0 +1,338 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class Geom { + private Geom() { + } + + /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->t = 0 and + * let r be the negated result (this evaluates (uw)(v->s)), then + * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). + */ + static double EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w) { + double gapL, gapR; + + assert (VertLeq(u, v) && VertLeq(v, w)); + + gapL = v.s - u.s; + gapR = w.s - v.s; + + if (gapL + gapR > 0) { + if (gapL < gapR) { + return (v.t - u.t) + (u.t - w.t) * (gapL / (gapL + gapR)); + } else { + return (v.t - w.t) + (w.t - u.t) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; + } + + static double EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w) { + double gapL, gapR; + + assert (VertLeq(u, v) && VertLeq(v, w)); + + gapL = v.s - u.s; + gapR = w.s - v.s; + + if (gapL + gapR > 0) { + return (v.t - w.t) * gapL + (v.t - u.t) * gapR; + } + /* vertical line */ + return 0; + } + + + /*********************************************************************** + * Define versions of EdgeSign, EdgeEval with s and t transposed. + */ + + static double TransEval(GLUvertex u, GLUvertex v, GLUvertex w) { + /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->s = 0 and + * let r be the negated result (this evaluates (uw)(v->t)), then + * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). + */ + double gapL, gapR; + + assert (TransLeq(u, v) && TransLeq(v, w)); + + gapL = v.t - u.t; + gapR = w.t - v.t; + + if (gapL + gapR > 0) { + if (gapL < gapR) { + return (v.s - u.s) + (u.s - w.s) * (gapL / (gapL + gapR)); + } else { + return (v.s - w.s) + (w.s - u.s) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; + } + + static double TransSign(GLUvertex u, GLUvertex v, GLUvertex w) { + /* Returns a number whose sign matches TransEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + double gapL, gapR; + + assert (TransLeq(u, v) && TransLeq(v, w)); + + gapL = v.t - u.t; + gapR = w.t - v.t; + + if (gapL + gapR > 0) { + return (v.s - w.s) * gapL + (v.s - u.s) * gapR; + } + /* vertical line */ + return 0; + } + + + static boolean VertCCW(GLUvertex u, GLUvertex v, GLUvertex w) { + /* For almost-degenerate situations, the results are not reliable. + * Unless the floating-point arithmetic can be performed without + * rounding errors, *any* implementation will give incorrect results + * on some degenerate inputs, so the client must have some way to + * handle this situation. + */ + return (u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0; + } + +/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), + * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces + * this in the rare case that one argument is slightly negative. + * The implementation is extremely stable numerically. + * In particular it guarantees that the result r satisfies + * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate + * even when a and b differ greatly in magnitude. + */ + static double Interpolate(double a, double x, double b, double y) { + a = (a < 0) ? 0 : a; + b = (b < 0) ? 0 : b; + if (a <= b) { + if (b == 0) { + return (x + y) / 2.0; + } else { + return (x + (y - x) * (a / (a + b))); + } + } else { + return (y + (x - y) * (b / (a + b))); + } + } + + static void EdgeIntersect(GLUvertex o1, GLUvertex d1, + GLUvertex o2, GLUvertex d2, + GLUvertex v) +/* Given edges (o1,d1) and (o2,d2), compute their point of intersection. + * The computed point is guaranteed to lie in the intersection of the + * bounding rectangles defined by each edge. + */ { + double z1, z2; + + /* This is certainly not the most efficient way to find the intersection + * of two line segments, but it is very numerically stable. + * + * Strategy: find the two middle vertices in the VertLeq ordering, + * and interpolate the intersection s-value from these. Then repeat + * using the TransLeq ordering to find the intersection t-value. + */ + + if (!VertLeq(o1, d1)) { + GLUvertex temp = o1; + o1 = d1; + d1 = temp; + } + if (!VertLeq(o2, d2)) { + GLUvertex temp = o2; + o2 = d2; + d2 = temp; + } + if (!VertLeq(o1, o2)) { + GLUvertex temp = o1; + o1 = o2; + o2 = temp; + temp = d1; + d1 = d2; + d2 = temp; + } + + if (!VertLeq(o2, d1)) { + /* Technically, no intersection -- do our best */ + v.s = (o2.s + d1.s) / 2.0; + } else if (VertLeq(d1, d2)) { + /* Interpolate between o2 and d1 */ + z1 = EdgeEval(o1, o2, d1); + z2 = EdgeEval(o2, d1, d2); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.s = Interpolate(z1, o2.s, z2, d1.s); + } else { + /* Interpolate between o2 and d2 */ + z1 = EdgeSign(o1, o2, d1); + z2 = -EdgeSign(o1, d2, d1); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.s = Interpolate(z1, o2.s, z2, d2.s); + } + + /* Now repeat the process for t */ + + if (!TransLeq(o1, d1)) { + GLUvertex temp = o1; + o1 = d1; + d1 = temp; + } + if (!TransLeq(o2, d2)) { + GLUvertex temp = o2; + o2 = d2; + d2 = temp; + } + if (!TransLeq(o1, o2)) { + GLUvertex temp = o2; + o2 = o1; + o1 = temp; + temp = d2; + d2 = d1; + d1 = temp; + } + + if (!TransLeq(o2, d1)) { + /* Technically, no intersection -- do our best */ + v.t = (o2.t + d1.t) / 2.0; + } else if (TransLeq(d1, d2)) { + /* Interpolate between o2 and d1 */ + z1 = TransEval(o1, o2, d1); + z2 = TransEval(o2, d1, d2); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.t = Interpolate(z1, o2.t, z2, d1.t); + } else { + /* Interpolate between o2 and d2 */ + z1 = TransSign(o1, o2, d1); + z2 = -TransSign(o1, d2, d1); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.t = Interpolate(z1, o2.t, z2, d2.t); + } + } + + static boolean VertEq(GLUvertex u, GLUvertex v) { + return u.s == v.s && u.t == v.t; + } + + static boolean VertLeq(GLUvertex u, GLUvertex v) { + return u.s < v.s || (u.s == v.s && u.t <= v.t); + } + +/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ + + static boolean TransLeq(GLUvertex u, GLUvertex v) { + return u.t < v.t || (u.t == v.t && u.s <= v.s); + } + + static boolean EdgeGoesLeft(GLUhalfEdge e) { + return VertLeq(e.Sym.Org, e.Org); + } + + static boolean EdgeGoesRight(GLUhalfEdge e) { + return VertLeq(e.Org, e.Sym.Org); + } + + static double VertL1dist(GLUvertex u, GLUvertex v) { + return Math.abs(u.s - v.s) + Math.abs(u.t - v.t); + } + + /***********************************************************************/ + + // Compute the cosine of the angle between the edges between o and + // v1 and between o and v2 + static double EdgeCos(GLUvertex o, GLUvertex v1, GLUvertex v2) { + double ov1s = v1.s - o.s; + double ov1t = v1.t - o.t; + double ov2s = v2.s - o.s; + double ov2t = v2.t - o.t; + double dotp = ov1s * ov2s + ov1t * ov2t; + double len = Math.sqrt(ov1s * ov1s + ov1t * ov1t) * Math.sqrt(ov2s * ov2s + ov2t * ov2t); + if (len > 0.0) { + dotp /= len; + } + return dotp; + } + + static final double EPSILON = 1.0e-5; + static final double ONE_MINUS_EPSILON = 1.0 - EPSILON; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Mesh.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Mesh.java new file mode 100644 index 000000000..b8be9f80f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Mesh.java @@ -0,0 +1,734 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class Mesh { + private Mesh() { + } + + /************************ Utility Routines ************************/ +/* MakeEdge creates a new pair of half-edges which form their own loop. + * No vertex or face structures are allocated, but these must be assigned + * before the current edge operation is completed. + */ + static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge MakeEdge(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNext) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eSym; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge ePrev; + +// EdgePair * pair = (EdgePair *) +// memAlloc(sizeof(EdgePair)); +// if (pair == NULL) return NULL; +// +// e = &pair - > e; + e = new com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge(true); +// eSym = &pair - > eSym; + eSym = new com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge(false); + + + /* Make sure eNext points to the first edge of the edge pair */ + if (!eNext.first) { + eNext = eNext.Sym; + } + + /* Insert in circular doubly-linked list before eNext. + * Note that the prev pointer is stored in Sym->next. + */ + ePrev = eNext.Sym.next; + eSym.next = ePrev; + ePrev.Sym.next = e; + e.next = eNext; + eNext.Sym.next = eSym; + + e.Sym = eSym; + e.Onext = e; + e.Lnext = eSym; + e.Org = null; + e.Lface = null; + e.winding = 0; + e.activeRegion = null; + + eSym.Sym = e; + eSym.Onext = eSym; + eSym.Lnext = e; + eSym.Org = null; + eSym.Lface = null; + eSym.winding = 0; + eSym.activeRegion = null; + + return e; + } + +/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the + * CS348a notes (see mesh.h). Basically it modifies the mesh so that + * a->Onext and b->Onext are exchanged. This can have various effects + * depending on whether a and b belong to different face or vertex rings. + * For more explanation see __gl_meshSplice() below. + */ + static void Splice(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge a, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge b) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge aOnext = a.Onext; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge bOnext = b.Onext; + + aOnext.Sym.Lnext = b; + bOnext.Sym.Lnext = a; + a.Onext = bOnext; + b.Onext = aOnext; + } + +/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the + * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives + * a place to insert the new vertex in the global vertex list. We insert + * the new vertex *before* vNext so that algorithms which walk the vertex + * list will not see the newly created vertices. + */ + static void MakeVertex(com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex, + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrig, com.jogamp.opengl.impl.glu.tessellator.GLUvertex vNext) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vPrev; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vNew = newVertex; + + assert (vNew != null); + + /* insert in circular doubly-linked list before vNext */ + vPrev = vNext.prev; + vNew.prev = vPrev; + vPrev.next = vNew; + vNew.next = vNext; + vNext.prev = vNew; + + vNew.anEdge = eOrig; + vNew.data = null; + /* leave coords, s, t undefined */ + + /* fix other edges on this vertex loop */ + e = eOrig; + do { + e.Org = vNew; + e = e.Onext; + } while (e != eOrig); + } + +/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left + * face of all edges in the face loop to which eOrig belongs. "fNext" gives + * a place to insert the new face in the global face list. We insert + * the new face *before* fNext so that algorithms which walk the face + * list will not see the newly created faces. + */ + static void MakeFace(com.jogamp.opengl.impl.glu.tessellator.GLUface newFace, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrig, com.jogamp.opengl.impl.glu.tessellator.GLUface fNext) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.jogamp.opengl.impl.glu.tessellator.GLUface fPrev; + com.jogamp.opengl.impl.glu.tessellator.GLUface fNew = newFace; + + assert (fNew != null); + + /* insert in circular doubly-linked list before fNext */ + fPrev = fNext.prev; + fNew.prev = fPrev; + fPrev.next = fNew; + fNew.next = fNext; + fNext.prev = fNew; + + fNew.anEdge = eOrig; + fNew.data = null; + fNew.trail = null; + fNew.marked = false; + + /* The new face is marked "inside" if the old one was. This is a + * convenience for the common case where a face has been split in two. + */ + fNew.inside = fNext.inside; + + /* fix other edges on this face loop */ + e = eOrig; + do { + e.Lface = fNew; + e = e.Lnext; + } while (e != eOrig); + } + +/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym), + * and removes from the global edge list. + */ + static void KillEdge(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDel) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge ePrev, eNext; + + /* Half-edges are allocated in pairs, see EdgePair above */ + if (!eDel.first) { + eDel = eDel.Sym; + } + + /* delete from circular doubly-linked list */ + eNext = eDel.next; + ePrev = eDel.Sym.next; + eNext.Sym.next = ePrev; + ePrev.Sym.next = eNext; + } + + +/* KillVertex( vDel ) destroys a vertex and removes it from the global + * vertex list. It updates the vertex loop to point to a given new vertex. + */ + static void KillVertex(com.jogamp.opengl.impl.glu.tessellator.GLUvertex vDel, com.jogamp.opengl.impl.glu.tessellator.GLUvertex newOrg) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eStart = vDel.anEdge; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vPrev, vNext; + + /* change the origin of all affected edges */ + e = eStart; + do { + e.Org = newOrg; + e = e.Onext; + } while (e != eStart); + + /* delete from circular doubly-linked list */ + vPrev = vDel.prev; + vNext = vDel.next; + vNext.prev = vPrev; + vPrev.next = vNext; + } + +/* KillFace( fDel ) destroys a face and removes it from the global face + * list. It updates the face loop to point to a given new face. + */ + static void KillFace(com.jogamp.opengl.impl.glu.tessellator.GLUface fDel, com.jogamp.opengl.impl.glu.tessellator.GLUface newLface) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eStart = fDel.anEdge; + com.jogamp.opengl.impl.glu.tessellator.GLUface fPrev, fNext; + + /* change the left face of all affected edges */ + e = eStart; + do { + e.Lface = newLface; + e = e.Lnext; + } while (e != eStart); + + /* delete from circular doubly-linked list */ + fPrev = fDel.prev; + fNext = fDel.next; + fNext.prev = fPrev; + fPrev.next = fNext; + } + + + /****************** Basic Edge Operations **********************/ + +/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face). + * The loop consists of the two new half-edges. + */ + public static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshMakeEdge(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex1 = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex(); + com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex2 = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex(); + com.jogamp.opengl.impl.glu.tessellator.GLUface newFace = new com.jogamp.opengl.impl.glu.tessellator.GLUface(); + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + + e = MakeEdge(mesh.eHead); + if (e == null) return null; + + MakeVertex(newVertex1, e, mesh.vHead); + MakeVertex(newVertex2, e.Sym, mesh.vHead); + MakeFace(newFace, e, mesh.fHead); + return e; + } + + +/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the + * mesh connectivity and topology. It changes the mesh so that + * eOrg->Onext <- OLD( eDst->Onext ) + * eDst->Onext <- OLD( eOrg->Onext ) + * where OLD(...) means the value before the meshSplice operation. + * + * This can have two effects on the vertex structure: + * - if eOrg->Org != eDst->Org, the two vertices are merged together + * - if eOrg->Org == eDst->Org, the origin is split into two vertices + * In both cases, eDst->Org is changed and eOrg->Org is untouched. + * + * Similarly (and independently) for the face structure, + * - if eOrg->Lface == eDst->Lface, one loop is split into two + * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one + * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. + * + * Some special cases: + * If eDst == eOrg, the operation has no effect. + * If eDst == eOrg->Lnext, the new face will have a single edge. + * If eDst == eOrg->Lprev, the old face will have a single edge. + * If eDst == eOrg->Onext, the new vertex will have a single edge. + * If eDst == eOrg->Oprev, the old vertex will have a single edge. + */ + public static boolean __gl_meshSplice(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrg, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDst) { + boolean joiningLoops = false; + boolean joiningVertices = false; + + if (eOrg == eDst) return true; + + if (eDst.Org != eOrg.Org) { + /* We are merging two disjoint vertices -- destroy eDst->Org */ + joiningVertices = true; + KillVertex(eDst.Org, eOrg.Org); + } + if (eDst.Lface != eOrg.Lface) { + /* We are connecting two disjoint loops -- destroy eDst.Lface */ + joiningLoops = true; + KillFace(eDst.Lface, eOrg.Lface); + } + + /* Change the edge structure */ + Splice(eDst, eOrg); + + if (!joiningVertices) { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex(); + + /* We split one vertex into two -- the new vertex is eDst.Org. + * Make sure the old vertex points to a valid half-edge. + */ + MakeVertex(newVertex, eDst, eOrg.Org); + eOrg.Org.anEdge = eOrg; + } + if (!joiningLoops) { + com.jogamp.opengl.impl.glu.tessellator.GLUface newFace = new com.jogamp.opengl.impl.glu.tessellator.GLUface(); + + /* We split one loop into two -- the new loop is eDst.Lface. + * Make sure the old face points to a valid half-edge. + */ + MakeFace(newFace, eDst, eOrg.Lface); + eOrg.Lface.anEdge = eOrg; + } + + return true; + } + + +/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases: + * if (eDel.Lface != eDel.Rface), we join two loops into one; the loop + * eDel.Lface is deleted. Otherwise, we are splitting one loop into two; + * the newly created loop will contain eDel.Dst. If the deletion of eDel + * would create isolated vertices, those are deleted as well. + * + * This function could be implemented as two calls to __gl_meshSplice + * plus a few calls to memFree, but this would allocate and delete + * unnecessary vertices and faces. + */ + static boolean __gl_meshDelete(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDel) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDelSym = eDel.Sym; + boolean joiningLoops = false; + + /* First step: disconnect the origin vertex eDel.Org. We make all + * changes to get a consistent mesh in this "intermediate" state. + */ + if (eDel.Lface != eDel.Sym.Lface) { + /* We are joining two loops into one -- remove the left face */ + joiningLoops = true; + KillFace(eDel.Lface, eDel.Sym.Lface); + } + + if (eDel.Onext == eDel) { + KillVertex(eDel.Org, null); + } else { + /* Make sure that eDel.Org and eDel.Sym.Lface point to valid half-edges */ + eDel.Sym.Lface.anEdge = eDel.Sym.Lnext; + eDel.Org.anEdge = eDel.Onext; + + Splice(eDel, eDel.Sym.Lnext); + if (!joiningLoops) { + com.jogamp.opengl.impl.glu.tessellator.GLUface newFace = new com.jogamp.opengl.impl.glu.tessellator.GLUface(); + + /* We are splitting one loop into two -- create a new loop for eDel. */ + MakeFace(newFace, eDel, eDel.Lface); + } + } + + /* Claim: the mesh is now in a consistent state, except that eDel.Org + * may have been deleted. Now we disconnect eDel.Dst. + */ + if (eDelSym.Onext == eDelSym) { + KillVertex(eDelSym.Org, null); + KillFace(eDelSym.Lface, null); + } else { + /* Make sure that eDel.Dst and eDel.Lface point to valid half-edges */ + eDel.Lface.anEdge = eDelSym.Sym.Lnext; + eDelSym.Org.anEdge = eDelSym.Onext; + Splice(eDelSym, eDelSym.Sym.Lnext); + } + + /* Any isolated vertices or faces have already been freed. */ + KillEdge(eDel); + + return true; + } + + + /******************** Other Edge Operations **********************/ + +/* All these routines can be implemented with the basic edge + * operations above. They are provided for convenience and efficiency. + */ + + +/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that + * eNew == eOrg.Lnext, and eNew.Dst is a newly created vertex. + * eOrg and eNew will have the same left face. + */ + static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshAddEdgeVertex(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrg) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNewSym; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg); + + eNewSym = eNew.Sym; + + /* Connect the new edge appropriately */ + Splice(eNew, eOrg.Lnext); + + /* Set the vertex and face information */ + eNew.Org = eOrg.Sym.Org; + { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex(); + + MakeVertex(newVertex, eNewSym, eNew.Org); + } + eNew.Lface = eNewSym.Lface = eOrg.Lface; + + return eNew; + } + + +/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, + * such that eNew == eOrg.Lnext. The new vertex is eOrg.Sym.Org == eNew.Org. + * eOrg and eNew will have the same left face. + */ + public static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshSplitEdge(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrg) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNew; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge tempHalfEdge = __gl_meshAddEdgeVertex(eOrg); + + eNew = tempHalfEdge.Sym; + + /* Disconnect eOrg from eOrg.Sym.Org and connect it to eNew.Org */ + Splice(eOrg.Sym, eOrg.Sym.Sym.Lnext); + Splice(eOrg.Sym, eNew); + + /* Set the vertex and face information */ + eOrg.Sym.Org = eNew.Org; + eNew.Sym.Org.anEdge = eNew.Sym; /* may have pointed to eOrg.Sym */ + eNew.Sym.Lface = eOrg.Sym.Lface; + eNew.winding = eOrg.winding; /* copy old winding information */ + eNew.Sym.winding = eOrg.Sym.winding; + + return eNew; + } + + +/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg.Sym.Org + * to eDst.Org, and returns the corresponding half-edge eNew. + * If eOrg.Lface == eDst.Lface, this splits one loop into two, + * and the newly created loop is eNew.Lface. Otherwise, two disjoint + * loops are merged into one, and the loop eDst.Lface is destroyed. + * + * If (eOrg == eDst), the new face will have only two edges. + * If (eOrg.Lnext == eDst), the old face is reduced to a single edge. + * If (eOrg.Lnext.Lnext == eDst), the old face is reduced to two edges. + */ + static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshConnect(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrg, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDst) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNewSym; + boolean joiningLoops = false; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg); + + eNewSym = eNew.Sym; + + if (eDst.Lface != eOrg.Lface) { + /* We are connecting two disjoint loops -- destroy eDst.Lface */ + joiningLoops = true; + KillFace(eDst.Lface, eOrg.Lface); + } + + /* Connect the new edge appropriately */ + Splice(eNew, eOrg.Lnext); + Splice(eNewSym, eDst); + + /* Set the vertex and face information */ + eNew.Org = eOrg.Sym.Org; + eNewSym.Org = eDst.Org; + eNew.Lface = eNewSym.Lface = eOrg.Lface; + + /* Make sure the old face points to a valid half-edge */ + eOrg.Lface.anEdge = eNewSym; + + if (!joiningLoops) { + com.jogamp.opengl.impl.glu.tessellator.GLUface newFace = new com.jogamp.opengl.impl.glu.tessellator.GLUface(); + + /* We split one loop into two -- the new loop is eNew.Lface */ + MakeFace(newFace, eNew, eOrg.Lface); + } + return eNew; + } + + + /******************** Other Operations **********************/ + +/* __gl_meshZapFace( fZap ) destroys a face and removes it from the + * global face list. All edges of fZap will have a null pointer as their + * left face. Any edges which also have a null pointer as their right face + * are deleted entirely (along with any isolated vertices this produces). + * An entire mesh can be deleted by zapping its faces, one at a time, + * in any order. Zapped faces cannot be used in further mesh operations! + */ + static void __gl_meshZapFace(com.jogamp.opengl.impl.glu.tessellator.GLUface fZap) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eStart = fZap.anEdge; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eNext, eSym; + com.jogamp.opengl.impl.glu.tessellator.GLUface fPrev, fNext; + + /* walk around face, deleting edges whose right face is also null */ + eNext = eStart.Lnext; + do { + e = eNext; + eNext = e.Lnext; + + e.Lface = null; + if (e.Sym.Lface == null) { + /* delete the edge -- see __gl_MeshDelete above */ + + if (e.Onext == e) { + KillVertex(e.Org, null); + } else { + /* Make sure that e.Org points to a valid half-edge */ + e.Org.anEdge = e.Onext; + Splice(e, e.Sym.Lnext); + } + eSym = e.Sym; + if (eSym.Onext == eSym) { + KillVertex(eSym.Org, null); + } else { + /* Make sure that eSym.Org points to a valid half-edge */ + eSym.Org.anEdge = eSym.Onext; + Splice(eSym, eSym.Sym.Lnext); + } + KillEdge(e); + } + } while (e != eStart); + + /* delete from circular doubly-linked list */ + fPrev = fZap.prev; + fNext = fZap.next; + fNext.prev = fPrev; + fPrev.next = fNext; + } + + +/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, + * and no loops (what we usually call a "face"). + */ + public static com.jogamp.opengl.impl.glu.tessellator.GLUmesh __gl_meshNewMesh() { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v; + com.jogamp.opengl.impl.glu.tessellator.GLUface f; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eSym; + com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh = new com.jogamp.opengl.impl.glu.tessellator.GLUmesh(); + + v = mesh.vHead; + f = mesh.fHead; + e = mesh.eHead; + eSym = mesh.eHeadSym; + + v.next = v.prev = v; + v.anEdge = null; + v.data = null; + + f.next = f.prev = f; + f.anEdge = null; + f.data = null; + f.trail = null; + f.marked = false; + f.inside = false; + + e.next = e; + e.Sym = eSym; + e.Onext = null; + e.Lnext = null; + e.Org = null; + e.Lface = null; + e.winding = 0; + e.activeRegion = null; + + eSym.next = eSym; + eSym.Sym = e; + eSym.Onext = null; + eSym.Lnext = null; + eSym.Org = null; + eSym.Lface = null; + eSym.winding = 0; + eSym.activeRegion = null; + + return mesh; + } + + +/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in + * both meshes, and returns the new mesh (the old meshes are destroyed). + */ + static com.jogamp.opengl.impl.glu.tessellator.GLUmesh __gl_meshUnion(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh1, com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh2) { + com.jogamp.opengl.impl.glu.tessellator.GLUface f1 = mesh1.fHead; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v1 = mesh1.vHead; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e1 = mesh1.eHead; + com.jogamp.opengl.impl.glu.tessellator.GLUface f2 = mesh2.fHead; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v2 = mesh2.vHead; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e2 = mesh2.eHead; + + /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */ + if (f2.next != f2) { + f1.prev.next = f2.next; + f2.next.prev = f1.prev; + f2.prev.next = f1; + f1.prev = f2.prev; + } + + if (v2.next != v2) { + v1.prev.next = v2.next; + v2.next.prev = v1.prev; + v2.prev.next = v1; + v1.prev = v2.prev; + } + + if (e2.next != e2) { + e1.Sym.next.Sym.next = e2.next; + e2.next.Sym.next = e1.Sym.next; + e2.Sym.next.Sym.next = e1; + e1.Sym.next = e2.Sym.next; + } + + return mesh1; + } + + +/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + */ + static void __gl_meshDeleteMeshZap(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface fHead = mesh.fHead; + + while (fHead.next != fHead) { + __gl_meshZapFace(fHead.next); + } + assert (mesh.vHead.next == mesh.vHead); + } + +/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + */ + public static void __gl_meshDeleteMesh(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface f, fNext; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, vNext; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eNext; + + for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { + fNext = f.next; + } + + for (v = mesh.vHead.next; v != mesh.vHead; v = vNext) { + vNext = v.next; + } + + for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { + /* One call frees both e and e.Sym (see EdgePair above) */ + eNext = e.next; + } + } + +/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. + */ + public static void __gl_meshCheckMesh(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface fHead = mesh.fHead; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vHead = mesh.vHead; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eHead = mesh.eHead; + com.jogamp.opengl.impl.glu.tessellator.GLUface f, fPrev; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, vPrev; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, ePrev; + + fPrev = fHead; + for (fPrev = fHead; (f = fPrev.next) != fHead; fPrev = f) { + assert (f.prev == fPrev); + e = f.anEdge; + do { + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + assert (e.Lface == f); + e = e.Lnext; + } while (e != f.anEdge); + } + assert (f.prev == fPrev && f.anEdge == null && f.data == null); + + vPrev = vHead; + for (vPrev = vHead; (v = vPrev.next) != vHead; vPrev = v) { + assert (v.prev == vPrev); + e = v.anEdge; + do { + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + assert (e.Org == v); + e = e.Onext; + } while (e != v.anEdge); + } + assert (v.prev == vPrev && v.anEdge == null && v.data == null); + + ePrev = eHead; + for (ePrev = eHead; (e = ePrev.next) != eHead; ePrev = e) { + assert (e.Sym.next == ePrev.Sym); + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Org != null); + assert (e.Sym.Org != null); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + } + assert (e.Sym.next == ePrev.Sym + && e.Sym == mesh.eHeadSym + && e.Sym.Sym == e + && e.Org == null && e.Sym.Org == null + && e.Lface == null && e.Sym.Lface == null); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Normal.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Normal.java new file mode 100644 index 000000000..fe1a20c49 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Normal.java @@ -0,0 +1,288 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Normal { + private Normal() { + } + + static boolean SLANTED_SWEEP = false; + static double S_UNIT_X; /* Pre-normalized */ + static double S_UNIT_Y; + private static final boolean TRUE_PROJECT = false; + + static { + if (SLANTED_SWEEP) { +/* The "feature merging" is not intended to be complete. There are + * special cases where edges are nearly parallel to the sweep line + * which are not implemented. The algorithm should still behave + * robustly (ie. produce a reasonable tesselation) in the presence + * of such edges, however it may miss features which could have been + * merged. We could minimize this effect by choosing the sweep line + * direction to be something unusual (ie. not parallel to one of the + * coordinate axes). + */ + S_UNIT_X = 0.50941539564955385; /* Pre-normalized */ + S_UNIT_Y = 0.86052074622010633; + } else { + S_UNIT_X = 1.0; + S_UNIT_Y = 0.0; + } + } + + private static double Dot(double[] u, double[] v) { + return (u[0] * v[0] + u[1] * v[1] + u[2] * v[2]); + } + + static void Normalize(double[] v) { + double len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + + assert (len > 0); + len = Math.sqrt(len); + v[0] /= len; + v[1] /= len; + v[2] /= len; + } + + static int LongAxis(double[] v) { + int i = 0; + + if (Math.abs(v[1]) > Math.abs(v[0])) { + i = 1; + } + if (Math.abs(v[2]) > Math.abs(v[i])) { + i = 2; + } + return i; + } + + static void ComputeNormal(GLUtessellatorImpl tess, double[] norm) { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, v1, v2; + double c, tLen2, maxLen2; + double[] maxVal, minVal, d1, d2, tNorm; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex[] maxVert, minVert; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vHead = tess.mesh.vHead; + int i; + + maxVal = new double[3]; + minVal = new double[3]; + minVert = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex[3]; + maxVert = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex[3]; + d1 = new double[3]; + d2 = new double[3]; + tNorm = new double[3]; + + maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU.GLU_TESS_MAX_COORD; + minVal[0] = minVal[1] = minVal[2] = 2 * GLU.GLU_TESS_MAX_COORD; + + for (v = vHead.next; v != vHead; v = v.next) { + for (i = 0; i < 3; ++i) { + c = v.coords[i]; + if (c < minVal[i]) { + minVal[i] = c; + minVert[i] = v; + } + if (c > maxVal[i]) { + maxVal[i] = c; + maxVert[i] = v; + } + } + } + +/* Find two vertices separated by at least 1/sqrt(3) of the maximum + * distance between any two vertices + */ + i = 0; + if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0]) { + i = 1; + } + if (maxVal[2] - minVal[2] > maxVal[i] - minVal[i]) { + i = 2; + } + if (minVal[i] >= maxVal[i]) { +/* All vertices are the same -- normal doesn't matter */ + norm[0] = 0; + norm[1] = 0; + norm[2] = 1; + return; + } + +/* Look for a third vertex which forms the triangle with maximum area + * (Length of normal == twice the triangle area) + */ + maxLen2 = 0; + v1 = minVert[i]; + v2 = maxVert[i]; + d1[0] = v1.coords[0] - v2.coords[0]; + d1[1] = v1.coords[1] - v2.coords[1]; + d1[2] = v1.coords[2] - v2.coords[2]; + for (v = vHead.next; v != vHead; v = v.next) { + d2[0] = v.coords[0] - v2.coords[0]; + d2[1] = v.coords[1] - v2.coords[1]; + d2[2] = v.coords[2] - v2.coords[2]; + tNorm[0] = d1[1] * d2[2] - d1[2] * d2[1]; + tNorm[1] = d1[2] * d2[0] - d1[0] * d2[2]; + tNorm[2] = d1[0] * d2[1] - d1[1] * d2[0]; + tLen2 = tNorm[0] * tNorm[0] + tNorm[1] * tNorm[1] + tNorm[2] * tNorm[2]; + if (tLen2 > maxLen2) { + maxLen2 = tLen2; + norm[0] = tNorm[0]; + norm[1] = tNorm[1]; + norm[2] = tNorm[2]; + } + } + + if (maxLen2 <= 0) { +/* All points lie on a single line -- any decent normal will do */ + norm[0] = norm[1] = norm[2] = 0; + norm[LongAxis(d1)] = 1; + } + } + + static void CheckOrientation(GLUtessellatorImpl tess) { + double area; + com.jogamp.opengl.impl.glu.tessellator.GLUface f, fHead = tess.mesh.fHead; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, vHead = tess.mesh.vHead; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + +/* When we compute the normal automatically, we choose the orientation + * so that the the sum of the signed areas of all contours is non-negative. + */ + area = 0; + for (f = fHead.next; f != fHead; f = f.next) { + e = f.anEdge; + if (e.winding <= 0) continue; + do { + area += (e.Org.s - e.Sym.Org.s) * (e.Org.t + e.Sym.Org.t); + e = e.Lnext; + } while (e != f.anEdge); + } + if (area < 0) { +/* Reverse the orientation by flipping all the t-coordinates */ + for (v = vHead.next; v != vHead; v = v.next) { + v.t = -v.t; + } + tess.tUnit[0] = -tess.tUnit[0]; + tess.tUnit[1] = -tess.tUnit[1]; + tess.tUnit[2] = -tess.tUnit[2]; + } + } + +/* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + public static void __gl_projectPolygon(GLUtessellatorImpl tess) { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, vHead = tess.mesh.vHead; + double w; + double[] norm = new double[3]; + double[] sUnit, tUnit; + int i; + boolean computedNormal = false; + + norm[0] = tess.normal[0]; + norm[1] = tess.normal[1]; + norm[2] = tess.normal[2]; + if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) { + ComputeNormal(tess, norm); + computedNormal = true; + } + sUnit = tess.sUnit; + tUnit = tess.tUnit; + i = LongAxis(norm); + + if (TRUE_PROJECT) { +/* Choose the initial sUnit vector to be approximately perpendicular + * to the normal. + */ + Normalize(norm); + + sUnit[i] = 0; + sUnit[(i + 1) % 3] = S_UNIT_X; + sUnit[(i + 2) % 3] = S_UNIT_Y; + +/* Now make it exactly perpendicular */ + w = Dot(sUnit, norm); + sUnit[0] -= w * norm[0]; + sUnit[1] -= w * norm[1]; + sUnit[2] -= w * norm[2]; + Normalize(sUnit); + +/* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */ + tUnit[0] = norm[1] * sUnit[2] - norm[2] * sUnit[1]; + tUnit[1] = norm[2] * sUnit[0] - norm[0] * sUnit[2]; + tUnit[2] = norm[0] * sUnit[1] - norm[1] * sUnit[0]; + Normalize(tUnit); + } else { +/* Project perpendicular to a coordinate axis -- better numerically */ + sUnit[i] = 0; + sUnit[(i + 1) % 3] = S_UNIT_X; + sUnit[(i + 2) % 3] = S_UNIT_Y; + + tUnit[i] = 0; + tUnit[(i + 1) % 3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y; + tUnit[(i + 2) % 3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X; + } + +/* Project the vertices onto the sweep plane */ + for (v = vHead.next; v != vHead; v = v.next) { + v.s = Dot(v.coords, sUnit); + v.t = Dot(v.coords, tUnit); + } + if (computedNormal) { + CheckOrientation(tess); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQ.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQ.java new file mode 100644 index 000000000..b77305ae2 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQ.java @@ -0,0 +1,100 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +abstract class PriorityQ { + public static final int INIT_SIZE = 32; + + public static class PQnode { + int handle; + } + + public static class PQhandleElem { + Object key; + int node; + } + + public static interface Leq { + boolean leq(Object key1, Object key2); + } + + // #ifdef FOR_TRITE_TEST_PROGRAM +// private static boolean LEQ(PriorityQCommon.Leq leq, Object x,Object y) { +// return pq.leq.leq(x,y); +// } +// #else +/* Violates modularity, but a little faster */ +// #include "geom.h" + public static boolean LEQ(Leq leq, Object x, Object y) { + return com.jogamp.opengl.impl.glu.tessellator.Geom.VertLeq((com.jogamp.opengl.impl.glu.tessellator.GLUvertex) x, (com.jogamp.opengl.impl.glu.tessellator.GLUvertex) y); + } + + static PriorityQ pqNewPriorityQ(Leq leq) { + return new PriorityQSort(leq); + } + + abstract void pqDeletePriorityQ(); + + abstract boolean pqInit(); + + abstract int pqInsert(Object keyNew); + + abstract Object pqExtractMin(); + + abstract void pqDelete(int hCurr); + + abstract Object pqMinimum(); + + abstract boolean pqIsEmpty(); +// #endif +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQHeap.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQHeap.java new file mode 100644 index 000000000..61aa9574f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQHeap.java @@ -0,0 +1,262 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class PriorityQHeap extends com.jogamp.opengl.impl.glu.tessellator.PriorityQ { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] handles; + int size, max; + int freeList; + boolean initialized; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq; + +/* really __gl_pqHeapNewPriorityQ */ + public PriorityQHeap(com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq) { + size = 0; + max = com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE; + nodes = new com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE + 1]; + for (int i = 0; i < nodes.length; i++) { + nodes[i] = new PQnode(); + } + handles = new com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE + 1]; + for (int i = 0; i < handles.length; i++) { + handles[i] = new PQhandleElem(); + } + initialized = false; + freeList = 0; + this.leq = leq; + + nodes[1].handle = 1; /* so that Minimum() returns NULL */ + handles[1].key = null; + } + +/* really __gl_pqHeapDeletePriorityQ */ + void pqDeletePriorityQ() { + handles = null; + nodes = null; + } + + void FloatDown(int curr) { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hCurr, hChild; + int child; + + hCurr = n[curr].handle; + for (; ;) { + child = curr << 1; + if (child < size && LEQ(leq, h[n[child + 1].handle].key, + h[n[child].handle].key)) { + ++child; + } + + assert (child <= max); + + hChild = n[child].handle; + if (child > size || LEQ(leq, h[hCurr].key, h[hChild].key)) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hChild; + h[hChild].node = curr; + curr = child; + } + } + + + void FloatUp(int curr) { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hCurr, hParent; + int parent; + + hCurr = n[curr].handle; + for (; ;) { + parent = curr >> 1; + hParent = n[parent].handle; + if (parent == 0 || LEQ(leq, h[hParent].key, h[hCurr].key)) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hParent; + h[hParent].node = curr; + curr = parent; + } + } + +/* really __gl_pqHeapInit */ + boolean pqInit() { + int i; + + /* This method of building a heap is O(n), rather than O(n lg n). */ + + for (i = size; i >= 1; --i) { + FloatDown(i); + } + initialized = true; + + return true; + } + +/* really __gl_pqHeapInsert */ +/* returns LONG_MAX iff out of memory */ + int pqInsert(Object keyNew) { + int curr; + int free; + + curr = ++size; + if ((curr * 2) > max) { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] saveNodes = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] saveHandles = handles; + + /* If the heap overflows, double its size. */ + max <<= 1; +// pq->nodes = (PQnode *)memRealloc( pq->nodes, (size_t) ((pq->max + 1) * sizeof( pq->nodes[0] ))); + PriorityQ.PQnode[] pqNodes = new PriorityQ.PQnode[max + 1]; + System.arraycopy( nodes, 0, pqNodes, 0, nodes.length ); + for (int i = nodes.length; i < pqNodes.length; i++) { + pqNodes[i] = new PQnode(); + } + nodes = pqNodes; + if (nodes == null) { + nodes = saveNodes; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + +// pq->handles = (PQhandleElem *)memRealloc( pq->handles,(size_t)((pq->max + 1) * sizeof( pq->handles[0] ))); + PriorityQ.PQhandleElem[] pqHandles = new PriorityQ.PQhandleElem[max + 1]; + System.arraycopy( handles, 0, pqHandles, 0, handles.length ); + for (int i = handles.length; i < pqHandles.length; i++) { + pqHandles[i] = new PQhandleElem(); + } + handles = pqHandles; + if (handles == null) { + handles = saveHandles; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + } + + if (freeList == 0) { + free = curr; + } else { + free = freeList; + freeList = handles[free].node; + } + + nodes[curr].handle = free; + handles[free].node = curr; + handles[free].key = keyNew; + + if (initialized) { + FloatUp(curr); + } + assert (free != Integer.MAX_VALUE); + return free; + } + +/* really __gl_pqHeapExtractMin */ + Object pqExtractMin() { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hMin = n[1].handle; + Object min = h[hMin].key; + + if (size > 0) { + n[1].handle = n[size].handle; + h[n[1].handle].node = 1; + + h[hMin].key = null; + h[hMin].node = freeList; + freeList = hMin; + + if (--size > 0) { + FloatDown(1); + } + } + return min; + } + +/* really __gl_pqHeapDelete */ + void pqDelete(int hCurr) { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int curr; + + assert (hCurr >= 1 && hCurr <= max && h[hCurr].key != null); + + curr = h[hCurr].node; + n[curr].handle = n[size].handle; + h[n[curr].handle].node = curr; + + if (curr <= --size) { + if (curr <= 1 || LEQ(leq, h[n[curr >> 1].handle].key, h[n[curr].handle].key)) { + FloatDown(curr); + } else { + FloatUp(curr); + } + } + h[hCurr].key = null; + h[hCurr].node = freeList; + freeList = hCurr; + } + + Object pqMinimum() { + return handles[nodes[1].handle].key; + } + + boolean pqIsEmpty() { + return size == 0; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQSort.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQSort.java new file mode 100644 index 000000000..f115b8f49 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQSort.java @@ -0,0 +1,278 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class PriorityQSort extends com.jogamp.opengl.impl.glu.tessellator.PriorityQ { + com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap heap; + Object[] keys; + + // JAVA: 'order' contains indices into the keys array. + // This simulates the indirect pointers used in the original C code + // (from Frank Suykens, Luciad.com). + int[] order; + int size, max; + boolean initialized; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq; + + public PriorityQSort(com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq) { + heap = new com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap(leq); + + keys = new Object[com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE]; + + size = 0; + max = com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE; + initialized = false; + this.leq = leq; + } + +/* really __gl_pqSortDeletePriorityQ */ + void pqDeletePriorityQ() { + if (heap != null) heap.pqDeletePriorityQ(); + order = null; + keys = null; + } + + private static boolean LT(com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq, Object x, Object y) { + return (!com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, y, x)); + } + + private static boolean GT(com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq, Object x, Object y) { + return (!com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, x, y)); + } + + private static void Swap(int[] array, int a, int b) { + if (true) { + int tmp = array[a]; + array[a] = array[b]; + array[b] = tmp; + } else { + + } + } + + private static class Stack { + int p, r; + } + +/* really __gl_pqSortInit */ + boolean pqInit() { + int p, r, i, j; + int piv; + Stack[] stack = new Stack[50]; + for (int k = 0; k < stack.length; k++) { + stack[k] = new Stack(); + } + int top = 0; + + int seed = 2016473283; + + /* Create an array of indirect pointers to the keys, so that we + * the handles we have returned are still valid. + */ + order = new int[size + 1]; +/* the previous line is a patch to compensate for the fact that IBM */ +/* machines return a null on a malloc of zero bytes (unlike SGI), */ +/* so we have to put in this defense to guard against a memory */ +/* fault four lines down. from [email protected]. */ + p = 0; + r = size - 1; + for (piv = 0, i = p; i <= r; ++piv, ++i) { + // indirect pointers: keep an index into the keys array, not a direct pointer to its contents + order[i] = piv; + } + + /* Sort the indirect pointers in descending order, + * using randomized Quicksort + */ + stack[top].p = p; + stack[top].r = r; + ++top; + while (--top >= 0) { + p = stack[top].p; + r = stack[top].r; + while (r > p + 10) { + seed = Math.abs( seed * 1539415821 + 1 ); + i = p + seed % (r - p + 1); + piv = order[i]; + order[i] = order[p]; + order[p] = piv; + i = p - 1; + j = r + 1; + do { + do { + ++i; + } while (GT(leq, keys[order[i]], keys[piv])); + do { + --j; + } while (LT(leq, keys[order[j]], keys[piv])); + Swap(order, i, j); + } while (i < j); + Swap(order, i, j); /* Undo last swap */ + if (i - p < r - j) { + stack[top].p = j + 1; + stack[top].r = r; + ++top; + r = i - 1; + } else { + stack[top].p = p; + stack[top].r = i - 1; + ++top; + p = j + 1; + } + } + /* Insertion sort small lists */ + for (i = p + 1; i <= r; ++i) { + piv = order[i]; + for (j = i; j > p && LT(leq, keys[order[j - 1]], keys[piv]); --j) { + order[j] = order[j - 1]; + } + order[j] = piv; + } + } + max = size; + initialized = true; + heap.pqInit(); /* always succeeds */ + +/* #ifndef NDEBUG + p = order; + r = p + size - 1; + for (i = p; i < r; ++i) { + Assertion.doAssert(LEQ( * * (i + 1), **i )); + } + #endif*/ + + return true; + } + +/* really __gl_pqSortInsert */ +/* returns LONG_MAX iff out of memory */ + int pqInsert(Object keyNew) { + int curr; + + if (initialized) { + return heap.pqInsert(keyNew); + } + curr = size; + if (++size >= max) { + Object[] saveKey = keys; + + /* If the heap overflows, double its size. */ + max <<= 1; +// pq->keys = (PQHeapKey *)memRealloc( pq->keys,(size_t)(pq->max * sizeof( pq->keys[0] ))); + Object[] pqKeys = new Object[max]; + System.arraycopy( keys, 0, pqKeys, 0, keys.length ); + keys = pqKeys; + if (keys == null) { + keys = saveKey; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + } + assert curr != Integer.MAX_VALUE; + keys[curr] = keyNew; + + /* Negative handles index the sorted array. */ + return -(curr + 1); + } + +/* really __gl_pqSortExtractMin */ + Object pqExtractMin() { + Object sortMin, heapMin; + + if (size == 0) { + return heap.pqExtractMin(); + } + sortMin = keys[order[size - 1]]; + if (!heap.pqIsEmpty()) { + heapMin = heap.pqMinimum(); + if (LEQ(leq, heapMin, sortMin)) { + return heap.pqExtractMin(); + } + } + do { + --size; + } while (size > 0 && keys[order[size - 1]] == null); + return sortMin; + } + +/* really __gl_pqSortMinimum */ + Object pqMinimum() { + Object sortMin, heapMin; + + if (size == 0) { + return heap.pqMinimum(); + } + sortMin = keys[order[size - 1]]; + if (!heap.pqIsEmpty()) { + heapMin = heap.pqMinimum(); + if (com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, heapMin, sortMin)) { + return heapMin; + } + } + return sortMin; + } + +/* really __gl_pqSortIsEmpty */ + boolean pqIsEmpty() { + return (size == 0) && heap.pqIsEmpty(); + } + +/* really __gl_pqSortDelete */ + void pqDelete(int curr) { + if (curr >= 0) { + heap.pqDelete(curr); + return; + } + curr = -(curr + 1); + assert curr < max && keys[curr] != null; + + keys[curr] = null; + while (size > 0 && keys[order[size - 1]] == null) { + --size; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Render.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Render.java new file mode 100644 index 000000000..9761200e0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Render.java @@ -0,0 +1,557 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Render { + private static final boolean USE_OPTIMIZED_CODE_PATH = false; + + private Render() { + } + + private static final RenderFan renderFan = new RenderFan(); + private static final RenderStrip renderStrip = new RenderStrip(); + private static final RenderTriangle renderTriangle = new RenderTriangle(); + +/* This structure remembers the information we need about a primitive + * to be able to render it later, once we have determined which + * primitive is able to use the most triangles. + */ + private static class FaceCount { + public FaceCount() { + } + + public FaceCount(long size, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eStart, renderCallBack render) { + this.size = size; + this.eStart = eStart; + this.render = render; + } + + long size; /* number of triangles used */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eStart; /* edge where this primitive starts */ + renderCallBack render; + }; + + private static interface renderCallBack { + void render(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, long size); + } + + /************************ Strips and Fans decomposition ******************/ + +/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle + * fans, strips, and separate triangles. A substantial effort is made + * to use as few rendering primitives as possible (ie. to make the fans + * and strips as large as possible). + * + * The rendering output is provided as callbacks (see the api). + */ + public static void __gl_renderMesh(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface f; + + /* Make a list of separate triangles so we can render them all at once */ + tess.lonelyTriList = null; + + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + f.marked = false; + } + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + + /* We examine all faces in an arbitrary order. Whenever we find + * an unprocessed face F, we output a group of faces including F + * whose size is maximum. + */ + if (f.inside && !f.marked) { + RenderMaximumFaceGroup(tess, f); + assert (f.marked); + } + } + if (tess.lonelyTriList != null) { + RenderLonelyTriangles(tess, tess.lonelyTriList); + tess.lonelyTriList = null; + } + } + + + static void RenderMaximumFaceGroup(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUface fOrig) { + /* We want to find the largest triangle fan or strip of unmarked faces + * which includes the given face fOrig. There are 3 possible fans + * passing through fOrig (one centered at each vertex), and 3 possible + * strips (one for each CCW permutation of the vertices). Our strategy + * is to try all of these, and take the primitive which uses the most + * triangles (a greedy approach). + */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e = fOrig.anEdge; + FaceCount max = new FaceCount(); + FaceCount newFace = new FaceCount(); + + max.size = 1; + max.eStart = e; + max.render = renderTriangle; + + if (!tess.flagBoundary) { + newFace = MaximumFan(e); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumFan(e.Lnext); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumFan(e.Onext.Sym); + if (newFace.size > max.size) { + max = newFace; + } + + newFace = MaximumStrip(e); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumStrip(e.Lnext); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumStrip(e.Onext.Sym); + if (newFace.size > max.size) { + max = newFace; + } + } + max.render.render(tess, max.eStart, max.size); + } + + +/* Macros which keep track of faces we have marked temporarily, and allow + * us to backtrack when necessary. With triangle fans, this is not + * really necessary, since the only awkward case is a loop of triangles + * around a single origin vertex. However with strips the situation is + * more complicated, and we need a general tracking method like the + * one here. + */ + private static boolean Marked(com.jogamp.opengl.impl.glu.tessellator.GLUface f) { + return !f.inside || f.marked; + } + + private static GLUface AddToTrail(com.jogamp.opengl.impl.glu.tessellator.GLUface f, com.jogamp.opengl.impl.glu.tessellator.GLUface t) { + f.trail = t; + f.marked = true; + return f; + } + + private static void FreeTrail(com.jogamp.opengl.impl.glu.tessellator.GLUface t) { + if (true) { + while (t != null) { + t.marked = false; + t = t.trail; + } + } else { + /* absorb trailing semicolon */ + } + } + + static FaceCount MaximumFan(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrig) { + /* eOrig.Lface is the face we want to render. We want to find the size + * of a maximal fan around eOrig.Org. To do this we just walk around + * the origin vertex as far as possible in both directions. + */ + FaceCount newFace = new FaceCount(0, null, renderFan); + com.jogamp.opengl.impl.glu.tessellator.GLUface trail = null; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + + for (e = eOrig; !Marked(e.Lface); e = e.Onext) { + trail = AddToTrail(e.Lface, trail); + ++newFace.size; + } + for (e = eOrig; !Marked(e.Sym.Lface); e = e.Sym.Lnext) { + trail = AddToTrail(e.Sym.Lface, trail); + ++newFace.size; + } + newFace.eStart = e; + /*LINTED*/ + FreeTrail(trail); + return newFace; + } + + + private static boolean IsEven(long n) { + return (n & 0x1L) == 0; + } + + static FaceCount MaximumStrip(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrig) { + /* Here we are looking for a maximal strip that contains the vertices + * eOrig.Org, eOrig.Dst, eOrig.Lnext.Dst (in that order or the + * reverse, such that all triangles are oriented CCW). + * + * Again we walk forward and backward as far as possible. However for + * strips there is a twist: to get CCW orientations, there must be + * an *even* number of triangles in the strip on one side of eOrig. + * We walk the strip starting on a side with an even number of triangles; + * if both side have an odd number, we are forced to shorten one side. + */ + FaceCount newFace = new FaceCount(0, null, renderStrip); + long headSize = 0, tailSize = 0; + com.jogamp.opengl.impl.glu.tessellator.GLUface trail = null; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eTail, eHead; + + for (e = eOrig; !Marked(e.Lface); ++tailSize, e = e.Onext) { + trail = AddToTrail(e.Lface, trail); + ++tailSize; + e = e.Lnext.Sym; + if (Marked(e.Lface)) break; + trail = AddToTrail(e.Lface, trail); + } + eTail = e; + + for (e = eOrig; !Marked(e.Sym.Lface); ++headSize, e = e.Sym.Onext.Sym) { + trail = AddToTrail(e.Sym.Lface, trail); + ++headSize; + e = e.Sym.Lnext; + if (Marked(e.Sym.Lface)) break; + trail = AddToTrail(e.Sym.Lface, trail); + } + eHead = e; + + newFace.size = tailSize + headSize; + if (IsEven(tailSize)) { + newFace.eStart = eTail.Sym; + } else if (IsEven(headSize)) { + newFace.eStart = eHead; + } else { + /* Both sides have odd length, we must shorten one of them. In fact, + * we must start from eHead to guarantee inclusion of eOrig.Lface. + */ + --newFace.size; + newFace.eStart = eHead.Onext; + } + /*LINTED*/ + FreeTrail(trail); + return newFace; + } + + private static class RenderTriangle implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Just add the triangle to a triangle list, so we can render all + * the separate triangles at once. + */ + assert (size == 1); + tess.lonelyTriList = AddToTrail(e.Lface, tess.lonelyTriList); + } + } + + + static void RenderLonelyTriangles(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUface f) { + /* Now we render all the separate triangles which could not be + * grouped into a triangle fan or strip. + */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + int newState; + int edgeState = -1; /* force edge state output for first vertex */ + + tess.callBeginOrBeginData(GL.GL_TRIANGLES); + + for (; f != null; f = f.trail) { + /* Loop once for each edge (there will always be 3 edges) */ + + e = f.anEdge; + do { + if (tess.flagBoundary) { + /* Set the "edge state" to true just before we output the + * first vertex of each edge on the polygon boundary. + */ + newState = (!e.Sym.Lface.inside) ? 1 : 0; + if (edgeState != newState) { + edgeState = newState; + tess.callEdgeFlagOrEdgeFlagData( edgeState != 0); + } + } + tess.callVertexOrVertexData( e.Org.data); + + e = e.Lnext; + } while (e != f.anEdge); + } + tess.callEndOrEndData(); + } + + private static class RenderFan implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Render as many CCW triangles as possible in a fan starting from + * edge "e". The fan *should* contain exactly "size" triangles + * (otherwise we've goofed up somewhere). + */ + tess.callBeginOrBeginData( GL.GL_TRIANGLE_FAN); + tess.callVertexOrVertexData( e.Org.data); + tess.callVertexOrVertexData( e.Sym.Org.data); + + while (!Marked(e.Lface)) { + e.Lface.marked = true; + --size; + e = e.Onext; + tess.callVertexOrVertexData( e.Sym.Org.data); + } + + assert (size == 0); + tess.callEndOrEndData(); + } + } + + private static class RenderStrip implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Render as many CCW triangles as possible in a strip starting from + * edge "e". The strip *should* contain exactly "size" triangles + * (otherwise we've goofed up somewhere). + */ + tess.callBeginOrBeginData( GL.GL_TRIANGLE_STRIP); + tess.callVertexOrVertexData( e.Org.data); + tess.callVertexOrVertexData( e.Sym.Org.data); + + while (!Marked(e.Lface)) { + e.Lface.marked = true; + --size; + e = e.Lnext.Sym; + tess.callVertexOrVertexData( e.Org.data); + if (Marked(e.Lface)) break; + + e.Lface.marked = true; + --size; + e = e.Onext; + tess.callVertexOrVertexData( e.Sym.Org.data); + } + + assert (size == 0); + tess.callEndOrEndData(); + } + } + + /************************ Boundary contour decomposition ******************/ + +/* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one + * contour for each face marked "inside". The rendering output is + * provided as callbacks (see the api). + */ + public static void __gl_renderBoundary(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface f; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + if (f.inside) { + tess.callBeginOrBeginData( GL.GL_LINE_LOOP); + e = f.anEdge; + do { + tess.callVertexOrVertexData( e.Org.data); + e = e.Lnext; + } while (e != f.anEdge); + tess.callEndOrEndData(); + } + } + } + + + /************************ Quick-and-dirty decomposition ******************/ + + private static final int SIGN_INCONSISTENT = 2; + + static int ComputeNormal(GLUtessellatorImpl tess, double[] norm, boolean check) +/* + * If check==false, we compute the polygon normal and place it in norm[]. + * If check==true, we check that each triangle in the fan from v0 has a + * consistent orientation with respect to norm[]. If triangles are + * consistently oriented CCW, return 1; if CW, return -1; if all triangles + * are degenerate return 0; otherwise (no consistent orientation) return + * SIGN_INCONSISTENT. + */ { + com.jogamp.opengl.impl.glu.tessellator.CachedVertex[] v = tess.cache; +// CachedVertex vn = v0 + tess.cacheCount; + int vn = tess.cacheCount; +// CachedVertex vc; + int vc; + double dot, xc, yc, zc, xp, yp, zp; + double[] n = new double[3]; + int sign = 0; + + /* Find the polygon normal. It is important to get a reasonable + * normal even when the polygon is self-intersecting (eg. a bowtie). + * Otherwise, the computed normal could be very tiny, but perpendicular + * to the true plane of the polygon due to numerical noise. Then all + * the triangles would appear to be degenerate and we would incorrectly + * decompose the polygon as a fan (or simply not render it at all). + * + * We use a sum-of-triangles normal algorithm rather than the more + * efficient sum-of-trapezoids method (used in CheckOrientation() + * in normal.c). This lets us explicitly reverse the signed area + * of some triangles to get a reasonable normal in the self-intersecting + * case. + */ + if (!check) { + norm[0] = norm[1] = norm[2] = 0.0; + } + + vc = 1; + xc = v[vc].coords[0] - v[0].coords[0]; + yc = v[vc].coords[1] - v[0].coords[1]; + zc = v[vc].coords[2] - v[0].coords[2]; + while (++vc < vn) { + xp = xc; + yp = yc; + zp = zc; + xc = v[vc].coords[0] - v[0].coords[0]; + yc = v[vc].coords[1] - v[0].coords[1]; + zc = v[vc].coords[2] - v[0].coords[2]; + + /* Compute (vp - v0) cross (vc - v0) */ + n[0] = yp * zc - zp * yc; + n[1] = zp * xc - xp * zc; + n[2] = xp * yc - yp * xc; + + dot = n[0] * norm[0] + n[1] * norm[1] + n[2] * norm[2]; + if (!check) { + /* Reverse the contribution of back-facing triangles to get + * a reasonable normal for self-intersecting polygons (see above) + */ + if (dot >= 0) { + norm[0] += n[0]; + norm[1] += n[1]; + norm[2] += n[2]; + } else { + norm[0] -= n[0]; + norm[1] -= n[1]; + norm[2] -= n[2]; + } + } else if (dot != 0) { + /* Check the new orientation for consistency with previous triangles */ + if (dot > 0) { + if (sign < 0) return SIGN_INCONSISTENT; + sign = 1; + } else { + if (sign > 0) return SIGN_INCONSISTENT; + sign = -1; + } + } + } + return sign; + } + +/* __gl_renderCache( tess ) takes a single contour and tries to render it + * as a triangle fan. This handles convex polygons, as well as some + * non-convex polygons if we get lucky. + * + * Returns true if the polygon was successfully rendered. The rendering + * output is provided as callbacks (see the api). + */ + public static boolean __gl_renderCache(GLUtessellatorImpl tess) { + com.jogamp.opengl.impl.glu.tessellator.CachedVertex[] v = tess.cache; +// CachedVertex vn = v0 + tess.cacheCount; + int vn = tess.cacheCount; +// CachedVertex vc; + int vc; + double[] norm = new double[3]; + int sign; + + if (tess.cacheCount < 3) { + /* Degenerate contour -- no output */ + return true; + } + + norm[0] = tess.normal[0]; + norm[1] = tess.normal[1]; + norm[2] = tess.normal[2]; + if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) { + ComputeNormal( tess, norm, false); + } + + sign = ComputeNormal( tess, norm, true); + if (sign == SIGN_INCONSISTENT) { + /* Fan triangles did not have a consistent orientation */ + return false; + } + if (sign == 0) { + /* All triangles were degenerate */ + return true; + } + + if ( !USE_OPTIMIZED_CODE_PATH ) { + return false; + } else { + /* Make sure we do the right thing for each winding rule */ + switch (tess.windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + case GLU.GLU_TESS_WINDING_NONZERO: + break; + case GLU.GLU_TESS_WINDING_POSITIVE: + if (sign < 0) return true; + break; + case GLU.GLU_TESS_WINDING_NEGATIVE: + if (sign > 0) return true; + break; + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + return true; + } + + tess.callBeginOrBeginData( tess.boundaryOnly ? GL.GL_LINE_LOOP + : (tess.cacheCount > 3) ? GL.GL_TRIANGLE_FAN + : GL.GL_TRIANGLES); + + tess.callVertexOrVertexData( v[0].data); + if (sign > 0) { + for (vc = 1; vc < vn; ++vc) { + tess.callVertexOrVertexData( v[vc].data); + } + } else { + for (vc = vn - 1; vc > 0; --vc) { + tess.callVertexOrVertexData( v[vc].data); + } + } + tess.callEndOrEndData(); + return true; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Sweep.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Sweep.java new file mode 100644 index 000000000..8ffeadb67 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Sweep.java @@ -0,0 +1,1353 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Sweep { + private Sweep() { + } + +// #ifdef FOR_TRITE_TEST_PROGRAM +// extern void DebugEvent( GLUtessellator *tess ); +// #else + private static void DebugEvent(GLUtessellatorImpl tess) { + + } +// #endif + +/* + * Invariants for the Edge Dictionary. + * - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2) + * at any valid location of the sweep event + * - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2 + * share a common endpoint + * - for each e, e.Dst has been processed, but not e.Org + * - each edge e satisfies VertLeq(e.Dst,event) && VertLeq(event,e.Org) + * where "event" is the current sweep line event. + * - no edge e has zero length + * + * Invariants for the Mesh (the processed portion). + * - the portion of the mesh left of the sweep line is a planar graph, + * ie. there is *some* way to embed it in the plane + * - no processed edge has zero length + * - no two processed vertices have identical coordinates + * - each "inside" region is monotone, ie. can be broken into two chains + * of monotonically increasing vertices according to VertLeq(v1,v2) + * - a non-invariant: these chains may intersect (very slightly) + * + * Invariants for the Sweep. + * - if none of the edges incident to the event vertex have an activeRegion + * (ie. none of these edges are in the edge dictionary), then the vertex + * has only right-going edges. + * - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced + * by ConnectRightVertex), then it is the only right-going edge from + * its associated vertex. (This says that these edges exist only + * when it is necessary.) + */ + +/* When we merge two edges into one, we need to compute the combined + * winding of the new edge. + */ + private static void AddWinding(GLUhalfEdge eDst, GLUhalfEdge eSrc) { + eDst.winding += eSrc.winding; + eDst.Sym.winding += eSrc.Sym.winding; + } + + + private static ActiveRegion RegionBelow(ActiveRegion r) { + return ((ActiveRegion) Dict.dictKey(Dict.dictPred(r.nodeUp))); + } + + private static ActiveRegion RegionAbove(ActiveRegion r) { + return ((ActiveRegion) Dict.dictKey(Dict.dictSucc(r.nodeUp))); + } + + static boolean EdgeLeq(GLUtessellatorImpl tess, ActiveRegion reg1, ActiveRegion reg2) +/* + * Both edges must be directed from right to left (this is the canonical + * direction for the upper edge of each region). + * + * The strategy is to evaluate a "t" value for each edge at the + * current sweep line position, given by tess.event. The calculations + * are designed to be very stable, but of course they are not perfect. + * + * Special case: if both edge destinations are at the sweep event, + * we sort the edges by slope (they would otherwise compare equally). + */ { + GLUvertex event = tess.event; + GLUhalfEdge e1, e2; + double t1, t2; + + e1 = reg1.eUp; + e2 = reg2.eUp; + + if (e1.Sym.Org == event) { + if (e2.Sym.Org == event) { + /* Two edges right of the sweep line which meet at the sweep event. + * Sort them by slope. + */ + if (Geom.VertLeq(e1.Org, e2.Org)) { + return Geom.EdgeSign(e2.Sym.Org, e1.Org, e2.Org) <= 0; + } + return Geom.EdgeSign(e1.Sym.Org, e2.Org, e1.Org) >= 0; + } + return Geom.EdgeSign(e2.Sym.Org, event, e2.Org) <= 0; + } + if (e2.Sym.Org == event) { + return Geom.EdgeSign(e1.Sym.Org, event, e1.Org) >= 0; + } + + /* General case - compute signed distance *from* e1, e2 to event */ + t1 = Geom.EdgeEval(e1.Sym.Org, event, e1.Org); + t2 = Geom.EdgeEval(e2.Sym.Org, event, e2.Org); + return (t1 >= t2); + } + + + static void DeleteRegion(GLUtessellatorImpl tess, ActiveRegion reg) { + if (reg.fixUpperEdge) { + /* It was created with zero winding number, so it better be + * deleted with zero winding number (ie. it better not get merged + * with a real edge). + */ + assert (reg.eUp.winding == 0); + } + reg.eUp.activeRegion = null; + Dict.dictDelete(tess.dict, reg.nodeUp); /* __gl_dictListDelete */ + } + + + static boolean FixUpperEdge(ActiveRegion reg, GLUhalfEdge newEdge) +/* + * Replace an upper edge which needs fixing (see ConnectRightVertex). + */ { + assert (reg.fixUpperEdge); + if (!Mesh.__gl_meshDelete(reg.eUp)) return false; + reg.fixUpperEdge = false; + reg.eUp = newEdge; + newEdge.activeRegion = reg; + + return true; + } + + static ActiveRegion TopLeftRegion(ActiveRegion reg) { + GLUvertex org = reg.eUp.Org; + GLUhalfEdge e; + + /* Find the region above the uppermost edge with the same origin */ + do { + reg = RegionAbove(reg); + } while (reg.eUp.Org == org); + + /* If the edge above was a temporary edge introduced by ConnectRightVertex, + * now is the time to fix it. + */ + if (reg.fixUpperEdge) { + e = Mesh.__gl_meshConnect(RegionBelow(reg).eUp.Sym, reg.eUp.Lnext); + if (e == null) return null; + if (!FixUpperEdge(reg, e)) return null; + reg = RegionAbove(reg); + } + return reg; + } + + static ActiveRegion TopRightRegion(ActiveRegion reg) { + GLUvertex dst = reg.eUp.Sym.Org; + + /* Find the region above the uppermost edge with the same destination */ + do { + reg = RegionAbove(reg); + } while (reg.eUp.Sym.Org == dst); + return reg; + } + + static ActiveRegion AddRegionBelow(GLUtessellatorImpl tess, + ActiveRegion regAbove, + GLUhalfEdge eNewUp) +/* + * Add a new active region to the sweep line, *somewhere* below "regAbove" + * (according to where the new edge belongs in the sweep-line dictionary). + * The upper edge of the new region will be "eNewUp". + * Winding number and "inside" flag are not updated. + */ { + ActiveRegion regNew = new ActiveRegion(); + if (regNew == null) throw new RuntimeException(); + + regNew.eUp = eNewUp; + /* __gl_dictListInsertBefore */ + regNew.nodeUp = Dict.dictInsertBefore(tess.dict, regAbove.nodeUp, regNew); + if (regNew.nodeUp == null) throw new RuntimeException(); + regNew.fixUpperEdge = false; + regNew.sentinel = false; + regNew.dirty = false; + + eNewUp.activeRegion = regNew; + return regNew; + } + + static boolean IsWindingInside(GLUtessellatorImpl tess, int n) { + switch (tess.windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + return (n & 1) != 0; + case GLU.GLU_TESS_WINDING_NONZERO: + return (n != 0); + case GLU.GLU_TESS_WINDING_POSITIVE: + return (n > 0); + case GLU.GLU_TESS_WINDING_NEGATIVE: + return (n < 0); + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + return (n >= 2) || (n <= -2); + } + /*LINTED*/ +// assert (false); + throw new InternalError(); + /*NOTREACHED*/ + } + + + static void ComputeWinding(GLUtessellatorImpl tess, ActiveRegion reg) { + reg.windingNumber = RegionAbove(reg).windingNumber + reg.eUp.winding; + reg.inside = IsWindingInside(tess, reg.windingNumber); + } + + + static void FinishRegion(GLUtessellatorImpl tess, ActiveRegion reg) +/* + * Delete a region from the sweep line. This happens when the upper + * and lower chains of a region meet (at a vertex on the sweep line). + * The "inside" flag is copied to the appropriate mesh face (we could + * not do this before -- since the structure of the mesh is always + * changing, this face may not have even existed until now). + */ { + GLUhalfEdge e = reg.eUp; + GLUface f = e.Lface; + + f.inside = reg.inside; + f.anEdge = e; /* optimization for __gl_meshTessellateMonoRegion() */ + DeleteRegion(tess, reg); + } + + + static GLUhalfEdge FinishLeftRegions(GLUtessellatorImpl tess, + ActiveRegion regFirst, ActiveRegion regLast) +/* + * We are given a vertex with one or more left-going edges. All affected + * edges should be in the edge dictionary. Starting at regFirst.eUp, + * we walk down deleting all regions where both edges have the same + * origin vOrg. At the same time we copy the "inside" flag from the + * active region to the face, since at this point each face will belong + * to at most one region (this was not necessarily true until this point + * in the sweep). The walk stops at the region above regLast; if regLast + * is null we walk as far as possible. At the same time we relink the + * mesh if necessary, so that the ordering of edges around vOrg is the + * same as in the dictionary. + */ { + ActiveRegion reg, regPrev; + GLUhalfEdge e, ePrev; + + regPrev = regFirst; + ePrev = regFirst.eUp; + while (regPrev != regLast) { + regPrev.fixUpperEdge = false; /* placement was OK */ + reg = RegionBelow(regPrev); + e = reg.eUp; + if (e.Org != ePrev.Org) { + if (!reg.fixUpperEdge) { + /* Remove the last left-going edge. Even though there are no further + * edges in the dictionary with this origin, there may be further + * such edges in the mesh (if we are adding left edges to a vertex + * that has already been processed). Thus it is important to call + * FinishRegion rather than just DeleteRegion. + */ + FinishRegion(tess, regPrev); + break; + } + /* If the edge below was a temporary edge introduced by + * ConnectRightVertex, now is the time to fix it. + */ + e = Mesh.__gl_meshConnect(ePrev.Onext.Sym, e.Sym); + if (e == null) throw new RuntimeException(); + if (!FixUpperEdge(reg, e)) throw new RuntimeException(); + } + + /* Relink edges so that ePrev.Onext == e */ + if (ePrev.Onext != e) { + if (!Mesh.__gl_meshSplice(e.Sym.Lnext, e)) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(ePrev, e)) throw new RuntimeException(); + } + FinishRegion(tess, regPrev); /* may change reg.eUp */ + ePrev = reg.eUp; + regPrev = reg; + } + return ePrev; + } + + + static void AddRightEdges(GLUtessellatorImpl tess, ActiveRegion regUp, + GLUhalfEdge eFirst, GLUhalfEdge eLast, GLUhalfEdge eTopLeft, + boolean cleanUp) +/* + * Purpose: insert right-going edges into the edge dictionary, and update + * winding numbers and mesh connectivity appropriately. All right-going + * edges share a common origin vOrg. Edges are inserted CCW starting at + * eFirst; the last edge inserted is eLast.Sym.Lnext. If vOrg has any + * left-going edges already processed, then eTopLeft must be the edge + * such that an imaginary upward vertical segment from vOrg would be + * contained between eTopLeft.Sym.Lnext and eTopLeft; otherwise eTopLeft + * should be null. + */ { + ActiveRegion reg, regPrev; + GLUhalfEdge e, ePrev; + boolean firstTime = true; + + /* Insert the new right-going edges in the dictionary */ + e = eFirst; + do { + assert (Geom.VertLeq(e.Org, e.Sym.Org)); + AddRegionBelow(tess, regUp, e.Sym); + e = e.Onext; + } while (e != eLast); + + /* Walk *all* right-going edges from e.Org, in the dictionary order, + * updating the winding numbers of each region, and re-linking the mesh + * edges to match the dictionary ordering (if necessary). + */ + if (eTopLeft == null) { + eTopLeft = RegionBelow(regUp).eUp.Sym.Onext; + } + regPrev = regUp; + ePrev = eTopLeft; + for (; ;) { + reg = RegionBelow(regPrev); + e = reg.eUp.Sym; + if (e.Org != ePrev.Org) break; + + if (e.Onext != ePrev) { + /* Unlink e from its current position, and relink below ePrev */ + if (!Mesh.__gl_meshSplice(e.Sym.Lnext, e)) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(ePrev.Sym.Lnext, e)) throw new RuntimeException(); + } + /* Compute the winding number and "inside" flag for the new regions */ + reg.windingNumber = regPrev.windingNumber - e.winding; + reg.inside = IsWindingInside(tess, reg.windingNumber); + + /* Check for two outgoing edges with same slope -- process these + * before any intersection tests (see example in __gl_computeInterior). + */ + regPrev.dirty = true; + if (!firstTime && CheckForRightSplice(tess, regPrev)) { + AddWinding(e, ePrev); + DeleteRegion(tess, regPrev); + if (!Mesh.__gl_meshDelete(ePrev)) throw new RuntimeException(); + } + firstTime = false; + regPrev = reg; + ePrev = e; + } + regPrev.dirty = true; + assert (regPrev.windingNumber - e.winding == reg.windingNumber); + + if (cleanUp) { + /* Check for intersections between newly adjacent edges. */ + WalkDirtyRegions(tess, regPrev); + } + } + + + static void CallCombine(GLUtessellatorImpl tess, GLUvertex isect, + Object[] data, float[] weights, boolean needed) { + double[] coords = new double[3]; + + /* Copy coord data in case the callback changes it. */ + coords[0] = isect.coords[0]; + coords[1] = isect.coords[1]; + coords[2] = isect.coords[2]; + + Object[] outData = new Object[1]; + tess.callCombineOrCombineData(coords, data, weights, outData); + isect.data = outData[0]; + if (isect.data == null) { + if (!needed) { + isect.data = data[0]; + } else if (!tess.fatalError) { + /* The only way fatal error is when two edges are found to intersect, + * but the user has not provided the callback necessary to handle + * generated intersection points. + */ + tess.callErrorOrErrorData(GLU.GLU_TESS_NEED_COMBINE_CALLBACK); + tess.fatalError = true; + } + } + } + + static void SpliceMergeVertices(GLUtessellatorImpl tess, GLUhalfEdge e1, + GLUhalfEdge e2) +/* + * Two vertices with idential coordinates are combined into one. + * e1.Org is kept, while e2.Org is discarded. + */ { + Object[] data = new Object[4]; + float[] weights = new float[]{0.5f, 0.5f, 0.0f, 0.0f}; + + data[0] = e1.Org.data; + data[1] = e2.Org.data; + CallCombine(tess, e1.Org, data, weights, false); + if (!Mesh.__gl_meshSplice(e1, e2)) throw new RuntimeException(); + } + + static void VertexWeights(GLUvertex isect, GLUvertex org, GLUvertex dst, + float[] weights) +/* + * Find some weights which describe how the intersection vertex is + * a linear combination of "org" and "dest". Each of the two edges + * which generated "isect" is allocated 50% of the weight; each edge + * splits the weight between its org and dst according to the + * relative distance to "isect". + */ { + double t1 = Geom.VertL1dist(org, isect); + double t2 = Geom.VertL1dist(dst, isect); + + weights[0] = (float) (0.5 * t2 / (t1 + t2)); + weights[1] = (float) (0.5 * t1 / (t1 + t2)); + isect.coords[0] += weights[0] * org.coords[0] + weights[1] * dst.coords[0]; + isect.coords[1] += weights[0] * org.coords[1] + weights[1] * dst.coords[1]; + isect.coords[2] += weights[0] * org.coords[2] + weights[1] * dst.coords[2]; + } + + + static void GetIntersectData(GLUtessellatorImpl tess, GLUvertex isect, + GLUvertex orgUp, GLUvertex dstUp, + GLUvertex orgLo, GLUvertex dstLo) +/* + * We've computed a new intersection point, now we need a "data" pointer + * from the user so that we can refer to this new vertex in the + * rendering callbacks. + */ { + Object[] data = new Object[4]; + float[] weights = new float[4]; + float[] weights1 = new float[2]; + float[] weights2 = new float[2]; + + data[0] = orgUp.data; + data[1] = dstUp.data; + data[2] = orgLo.data; + data[3] = dstLo.data; + + isect.coords[0] = isect.coords[1] = isect.coords[2] = 0; + VertexWeights(isect, orgUp, dstUp, weights1); + VertexWeights(isect, orgLo, dstLo, weights2); + System.arraycopy(weights1, 0, weights, 0, 2); + System.arraycopy(weights2, 0, weights, 2, 2); + + CallCombine(tess, isect, data, weights, true); + } + + static boolean CheckForRightSplice(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edge of "regUp", to make sure that the + * eUp.Org is above eLo, or eLo.Org is below eUp (depending on which + * origin is leftmost). + * + * The main purpose is to splice right-going edges with the same + * dest vertex and nearly identical slopes (ie. we can't distinguish + * the slopes numerically). However the splicing can also help us + * to recover from numerical errors. For example, suppose at one + * point we checked eUp and eLo, and decided that eUp.Org is barely + * above eLo. Then later, we split eLo into two edges (eg. from + * a splice operation like this one). This can change the result of + * our test so that now eUp.Org is incident to eLo, or barely below it. + * We must correct this condition to maintain the dictionary invariants. + * + * One possibility is to check these edges for intersection again + * (ie. CheckForIntersect). This is what we do if possible. However + * CheckForIntersect requires that tess.event lies between eUp and eLo, + * so that it has something to fall back on when the intersection + * calculation gives us an unusable answer. So, for those cases where + * we can't check for intersection, this routine fixes the problem + * by just splicing the offending vertex into the other edge. + * This is a guaranteed solution, no matter how degenerate things get. + * Basically this is a combinatorial solution to a numerical problem. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + + if (Geom.VertLeq(eUp.Org, eLo.Org)) { + if (Geom.EdgeSign(eLo.Sym.Org, eUp.Org, eLo.Org) > 0) return false; + + /* eUp.Org appears to be below eLo */ + if (!Geom.VertEq(eUp.Org, eLo.Org)) { + /* Splice eUp.Org into eLo */ + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp, eLo.Sym.Lnext)) throw new RuntimeException(); + regUp.dirty = regLo.dirty = true; + + } else if (eUp.Org != eLo.Org) { + /* merge the two vertices, discarding eUp.Org */ + tess.pq.pqDelete(eUp.Org.pqHandle); /* __gl_pqSortDelete */ + SpliceMergeVertices(tess, eLo.Sym.Lnext, eUp); + } + } else { + if (Geom.EdgeSign(eUp.Sym.Org, eLo.Org, eUp.Org) < 0) return false; + + /* eLo.Org appears to be above eUp, so splice eLo.Org into eUp */ + RegionAbove(regUp).dirty = regUp.dirty = true; + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym.Lnext, eUp)) throw new RuntimeException(); + } + return true; + } + + static boolean CheckForLeftSplice(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edge of "regUp", to make sure that the + * eUp.Sym.Org is above eLo, or eLo.Sym.Org is below eUp (depending on which + * destination is rightmost). + * + * Theoretically, this should always be true. However, splitting an edge + * into two pieces can change the results of previous tests. For example, + * suppose at one point we checked eUp and eLo, and decided that eUp.Sym.Org + * is barely above eLo. Then later, we split eLo into two edges (eg. from + * a splice operation like this one). This can change the result of + * the test so that now eUp.Sym.Org is incident to eLo, or barely below it. + * We must correct this condition to maintain the dictionary invariants + * (otherwise new edges might get inserted in the wrong place in the + * dictionary, and bad stuff will happen). + * + * We fix the problem by just splicing the offending vertex into the + * other edge. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + GLUhalfEdge e; + + assert (!Geom.VertEq(eUp.Sym.Org, eLo.Sym.Org)); + + if (Geom.VertLeq(eUp.Sym.Org, eLo.Sym.Org)) { + if (Geom.EdgeSign(eUp.Sym.Org, eLo.Sym.Org, eUp.Org) < 0) return false; + + /* eLo.Sym.Org is above eUp, so splice eLo.Sym.Org into eUp */ + RegionAbove(regUp).dirty = regUp.dirty = true; + e = Mesh.__gl_meshSplitEdge(eUp); + if (e == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym, e)) throw new RuntimeException(); + e.Lface.inside = regUp.inside; + } else { + if (Geom.EdgeSign(eLo.Sym.Org, eUp.Sym.Org, eLo.Org) > 0) return false; + + /* eUp.Sym.Org is below eLo, so splice eUp.Sym.Org into eLo */ + regUp.dirty = regLo.dirty = true; + e = Mesh.__gl_meshSplitEdge(eLo); + if (e == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp.Lnext, eLo.Sym)) throw new RuntimeException(); + e.Sym.Lface.inside = regUp.inside; + } + return true; + } + + + static boolean CheckForIntersect(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edges of the given region to see if + * they intersect. If so, create the intersection and add it + * to the data structures. + * + * Returns true if adding the new intersection resulted in a recursive + * call to AddRightEdges(); in this case all "dirty" regions have been + * checked for intersections, and possibly regUp has been deleted. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + GLUvertex orgUp = eUp.Org; + GLUvertex orgLo = eLo.Org; + GLUvertex dstUp = eUp.Sym.Org; + GLUvertex dstLo = eLo.Sym.Org; + double tMinUp, tMaxLo; + GLUvertex isect = new GLUvertex(); + GLUvertex orgMin; + GLUhalfEdge e; + + assert (!Geom.VertEq(dstLo, dstUp)); + assert (Geom.EdgeSign(dstUp, tess.event, orgUp) <= 0); + assert (Geom.EdgeSign(dstLo, tess.event, orgLo) >= 0); + assert (orgUp != tess.event && orgLo != tess.event); + assert (!regUp.fixUpperEdge && !regLo.fixUpperEdge); + + if (orgUp == orgLo) return false; /* right endpoints are the same */ + + tMinUp = Math.min(orgUp.t, dstUp.t); + tMaxLo = Math.max(orgLo.t, dstLo.t); + if (tMinUp > tMaxLo) return false; /* t ranges do not overlap */ + + if (Geom.VertLeq(orgUp, orgLo)) { + if (Geom.EdgeSign(dstLo, orgUp, orgLo) > 0) return false; + } else { + if (Geom.EdgeSign(dstUp, orgLo, orgUp) < 0) return false; + } + + /* At this point the edges intersect, at least marginally */ + DebugEvent(tess); + + Geom.EdgeIntersect(dstUp, orgUp, dstLo, orgLo, isect); + /* The following properties are guaranteed: */ + assert (Math.min(orgUp.t, dstUp.t) <= isect.t); + assert (isect.t <= Math.max(orgLo.t, dstLo.t)); + assert (Math.min(dstLo.s, dstUp.s) <= isect.s); + assert (isect.s <= Math.max(orgLo.s, orgUp.s)); + + if (Geom.VertLeq(isect, tess.event)) { + /* The intersection point lies slightly to the left of the sweep line, + * so move it until it''s slightly to the right of the sweep line. + * (If we had perfect numerical precision, this would never happen + * in the first place). The easiest and safest thing to do is + * replace the intersection by tess.event. + */ + isect.s = tess.event.s; + isect.t = tess.event.t; + } + /* Similarly, if the computed intersection lies to the right of the + * rightmost origin (which should rarely happen), it can cause + * unbelievable inefficiency on sufficiently degenerate inputs. + * (If you have the test program, try running test54.d with the + * "X zoom" option turned on). + */ + orgMin = Geom.VertLeq(orgUp, orgLo) ? orgUp : orgLo; + if (Geom.VertLeq(orgMin, isect)) { + isect.s = orgMin.s; + isect.t = orgMin.t; + } + + if (Geom.VertEq(isect, orgUp) || Geom.VertEq(isect, orgLo)) { + /* Easy case -- intersection at one of the right endpoints */ + CheckForRightSplice(tess, regUp); + return false; + } + + if ((!Geom.VertEq(dstUp, tess.event) + && Geom.EdgeSign(dstUp, tess.event, isect) >= 0) + || (!Geom.VertEq(dstLo, tess.event) + && Geom.EdgeSign(dstLo, tess.event, isect) <= 0)) { + /* Very unusual -- the new upper or lower edge would pass on the + * wrong side of the sweep event, or through it. This can happen + * due to very small numerical errors in the intersection calculation. + */ + if (dstLo == tess.event) { + /* Splice dstLo into eUp, and process the new region(s) */ + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym, eUp)) throw new RuntimeException(); + regUp = TopLeftRegion(regUp); + if (regUp == null) throw new RuntimeException(); + eUp = RegionBelow(regUp).eUp; + FinishLeftRegions(tess, RegionBelow(regUp), regLo); + AddRightEdges(tess, regUp, eUp.Sym.Lnext, eUp, eUp, true); + return true; + } + if (dstUp == tess.event) { + /* Splice dstUp into eLo, and process the new region(s) */ + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp.Lnext, eLo.Sym.Lnext)) throw new RuntimeException(); + regLo = regUp; + regUp = TopRightRegion(regUp); + e = RegionBelow(regUp).eUp.Sym.Onext; + regLo.eUp = eLo.Sym.Lnext; + eLo = FinishLeftRegions(tess, regLo, null); + AddRightEdges(tess, regUp, eLo.Onext, eUp.Sym.Onext, e, true); + return true; + } + /* Special case: called from ConnectRightVertex. If either + * edge passes on the wrong side of tess.event, split it + * (and wait for ConnectRightVertex to splice it appropriately). + */ + if (Geom.EdgeSign(dstUp, tess.event, isect) >= 0) { + RegionAbove(regUp).dirty = regUp.dirty = true; + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + eUp.Org.s = tess.event.s; + eUp.Org.t = tess.event.t; + } + if (Geom.EdgeSign(dstLo, tess.event, isect) <= 0) { + regUp.dirty = regLo.dirty = true; + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + eLo.Org.s = tess.event.s; + eLo.Org.t = tess.event.t; + } + /* leave the rest for ConnectRightVertex */ + return false; + } + + /* General case -- split both edges, splice into new vertex. + * When we do the splice operation, the order of the arguments is + * arbitrary as far as correctness goes. However, when the operation + * creates a new face, the work done is proportional to the size of + * the new face. We expect the faces in the processed part of + * the mesh (ie. eUp.Lface) to be smaller than the faces in the + * unprocessed original contours (which will be eLo.Sym.Lnext.Lface). + */ + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym.Lnext, eUp)) throw new RuntimeException(); + eUp.Org.s = isect.s; + eUp.Org.t = isect.t; + eUp.Org.pqHandle = tess.pq.pqInsert(eUp.Org); /* __gl_pqSortInsert */ + if (eUp.Org.pqHandle == Long.MAX_VALUE) { + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + tess.pq = null; + throw new RuntimeException(); + } + GetIntersectData(tess, eUp.Org, orgUp, dstUp, orgLo, dstLo); + RegionAbove(regUp).dirty = regUp.dirty = regLo.dirty = true; + return false; + } + + static void WalkDirtyRegions(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * When the upper or lower edge of any region changes, the region is + * marked "dirty". This routine walks through all the dirty regions + * and makes sure that the dictionary invariants are satisfied + * (see the comments at the beginning of this file). Of course + * new dirty regions can be created as we make changes to restore + * the invariants. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp, eLo; + + for (; ;) { + /* Find the lowest dirty region (we walk from the bottom up). */ + while (regLo.dirty) { + regUp = regLo; + regLo = RegionBelow(regLo); + } + if (!regUp.dirty) { + regLo = regUp; + regUp = RegionAbove(regUp); + if (regUp == null || !regUp.dirty) { + /* We've walked all the dirty regions */ + return; + } + } + regUp.dirty = false; + eUp = regUp.eUp; + eLo = regLo.eUp; + + if (eUp.Sym.Org != eLo.Sym.Org) { + /* Check that the edge ordering is obeyed at the Dst vertices. */ + if (CheckForLeftSplice(tess, regUp)) { + + /* If the upper or lower edge was marked fixUpperEdge, then + * we no longer need it (since these edges are needed only for + * vertices which otherwise have no right-going edges). + */ + if (regLo.fixUpperEdge) { + DeleteRegion(tess, regLo); + if (!Mesh.__gl_meshDelete(eLo)) throw new RuntimeException(); + regLo = RegionBelow(regUp); + eLo = regLo.eUp; + } else if (regUp.fixUpperEdge) { + DeleteRegion(tess, regUp); + if (!Mesh.__gl_meshDelete(eUp)) throw new RuntimeException(); + regUp = RegionAbove(regLo); + eUp = regUp.eUp; + } + } + } + if (eUp.Org != eLo.Org) { + if (eUp.Sym.Org != eLo.Sym.Org + && !regUp.fixUpperEdge && !regLo.fixUpperEdge + && (eUp.Sym.Org == tess.event || eLo.Sym.Org == tess.event)) { + /* When all else fails in CheckForIntersect(), it uses tess.event + * as the intersection location. To make this possible, it requires + * that tess.event lie between the upper and lower edges, and also + * that neither of these is marked fixUpperEdge (since in the worst + * case it might splice one of these edges into tess.event, and + * violate the invariant that fixable edges are the only right-going + * edge from their associated vertex). + */ + if (CheckForIntersect(tess, regUp)) { + /* WalkDirtyRegions() was called recursively; we're done */ + return; + } + } else { + /* Even though we can't use CheckForIntersect(), the Org vertices + * may violate the dictionary edge ordering. Check and correct this. + */ + CheckForRightSplice(tess, regUp); + } + } + if (eUp.Org == eLo.Org && eUp.Sym.Org == eLo.Sym.Org) { + /* A degenerate loop consisting of only two edges -- delete it. */ + AddWinding(eLo, eUp); + DeleteRegion(tess, regUp); + if (!Mesh.__gl_meshDelete(eUp)) throw new RuntimeException(); + regUp = RegionAbove(regLo); + } + } + } + + + static void ConnectRightVertex(GLUtessellatorImpl tess, ActiveRegion regUp, + GLUhalfEdge eBottomLeft) +/* + * Purpose: connect a "right" vertex vEvent (one where all edges go left) + * to the unprocessed portion of the mesh. Since there are no right-going + * edges, two regions (one above vEvent and one below) are being merged + * into one. "regUp" is the upper of these two regions. + * + * There are two reasons for doing this (adding a right-going edge): + * - if the two regions being merged are "inside", we must add an edge + * to keep them separated (the combined region would not be monotone). + * - in any case, we must leave some record of vEvent in the dictionary, + * so that we can merge vEvent with features that we have not seen yet. + * For example, maybe there is a vertical edge which passes just to + * the right of vEvent; we would like to splice vEvent into this edge. + * + * However, we don't want to connect vEvent to just any vertex. We don''t + * want the new edge to cross any other edges; otherwise we will create + * intersection vertices even when the input data had no self-intersections. + * (This is a bad thing; if the user's input data has no intersections, + * we don't want to generate any false intersections ourselves.) + * + * Our eventual goal is to connect vEvent to the leftmost unprocessed + * vertex of the combined region (the union of regUp and regLo). + * But because of unseen vertices with all right-going edges, and also + * new vertices which may be created by edge intersections, we don''t + * know where that leftmost unprocessed vertex is. In the meantime, we + * connect vEvent to the closest vertex of either chain, and mark the region + * as "fixUpperEdge". This flag says to delete and reconnect this edge + * to the next processed vertex on the boundary of the combined region. + * Quite possibly the vertex we connected to will turn out to be the + * closest one, in which case we won''t need to make any changes. + */ { + GLUhalfEdge eNew; + GLUhalfEdge eTopLeft = eBottomLeft.Onext; + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + boolean degenerate = false; + + if (eUp.Sym.Org != eLo.Sym.Org) { + CheckForIntersect(tess, regUp); + } + + /* Possible new degeneracies: upper or lower edge of regUp may pass + * through vEvent, or may coincide with new intersection vertex + */ + if (Geom.VertEq(eUp.Org, tess.event)) { + if (!Mesh.__gl_meshSplice(eTopLeft.Sym.Lnext, eUp)) throw new RuntimeException(); + regUp = TopLeftRegion(regUp); + if (regUp == null) throw new RuntimeException(); + eTopLeft = RegionBelow(regUp).eUp; + FinishLeftRegions(tess, RegionBelow(regUp), regLo); + degenerate = true; + } + if (Geom.VertEq(eLo.Org, tess.event)) { + if (!Mesh.__gl_meshSplice(eBottomLeft, eLo.Sym.Lnext)) throw new RuntimeException(); + eBottomLeft = FinishLeftRegions(tess, regLo, null); + degenerate = true; + } + if (degenerate) { + AddRightEdges(tess, regUp, eBottomLeft.Onext, eTopLeft, eTopLeft, true); + return; + } + + /* Non-degenerate situation -- need to add a temporary, fixable edge. + * Connect to the closer of eLo.Org, eUp.Org. + */ + if (Geom.VertLeq(eLo.Org, eUp.Org)) { + eNew = eLo.Sym.Lnext; + } else { + eNew = eUp; + } + eNew = Mesh.__gl_meshConnect(eBottomLeft.Onext.Sym, eNew); + if (eNew == null) throw new RuntimeException(); + + /* Prevent cleanup, otherwise eNew might disappear before we've even + * had a chance to mark it as a temporary edge. + */ + AddRightEdges(tess, regUp, eNew, eNew.Onext, eNew.Onext, false); + eNew.Sym.activeRegion.fixUpperEdge = true; + WalkDirtyRegions(tess, regUp); + } + +/* Because vertices at exactly the same location are merged together + * before we process the sweep event, some degenerate cases can't occur. + * However if someone eventually makes the modifications required to + * merge features which are close together, the cases below marked + * TOLERANCE_NONZERO will be useful. They were debugged before the + * code to merge identical vertices in the main loop was added. + */ + private static final boolean TOLERANCE_NONZERO = false; + + static void ConnectLeftDegenerate(GLUtessellatorImpl tess, + ActiveRegion regUp, GLUvertex vEvent) +/* + * The event vertex lies exacty on an already-processed edge or vertex. + * Adding the new vertex involves splicing it into the already-processed + * part of the mesh. + */ { + GLUhalfEdge e, eTopLeft, eTopRight, eLast; + ActiveRegion reg; + + e = regUp.eUp; + if (Geom.VertEq(e.Org, vEvent)) { + /* e.Org is an unprocessed vertex - just combine them, and wait + * for e.Org to be pulled from the queue + */ + assert (TOLERANCE_NONZERO); + SpliceMergeVertices(tess, e, vEvent.anEdge); + return; + } + + if (!Geom.VertEq(e.Sym.Org, vEvent)) { + /* General case -- splice vEvent into edge e which passes through it */ + if (Mesh.__gl_meshSplitEdge(e.Sym) == null) throw new RuntimeException(); + if (regUp.fixUpperEdge) { + /* This edge was fixable -- delete unused portion of original edge */ + if (!Mesh.__gl_meshDelete(e.Onext)) throw new RuntimeException(); + regUp.fixUpperEdge = false; + } + if (!Mesh.__gl_meshSplice(vEvent.anEdge, e)) throw new RuntimeException(); + SweepEvent(tess, vEvent); /* recurse */ + return; + } + + /* vEvent coincides with e.Sym.Org, which has already been processed. + * Splice in the additional right-going edges. + */ + assert (TOLERANCE_NONZERO); + regUp = TopRightRegion(regUp); + reg = RegionBelow(regUp); + eTopRight = reg.eUp.Sym; + eTopLeft = eLast = eTopRight.Onext; + if (reg.fixUpperEdge) { + /* Here e.Sym.Org has only a single fixable edge going right. + * We can delete it since now we have some real right-going edges. + */ + assert (eTopLeft != eTopRight); /* there are some left edges too */ + DeleteRegion(tess, reg); + if (!Mesh.__gl_meshDelete(eTopRight)) throw new RuntimeException(); + eTopRight = eTopLeft.Sym.Lnext; + } + if (!Mesh.__gl_meshSplice(vEvent.anEdge, eTopRight)) throw new RuntimeException(); + if (!Geom.EdgeGoesLeft(eTopLeft)) { + /* e.Sym.Org had no left-going edges -- indicate this to AddRightEdges() */ + eTopLeft = null; + } + AddRightEdges(tess, regUp, eTopRight.Onext, eLast, eTopLeft, true); + } + + + static void ConnectLeftVertex(GLUtessellatorImpl tess, GLUvertex vEvent) +/* + * Purpose: connect a "left" vertex (one where both edges go right) + * to the processed portion of the mesh. Let R be the active region + * containing vEvent, and let U and L be the upper and lower edge + * chains of R. There are two possibilities: + * + * - the normal case: split R into two regions, by connecting vEvent to + * the rightmost vertex of U or L lying to the left of the sweep line + * + * - the degenerate case: if vEvent is close enough to U or L, we + * merge vEvent into that edge chain. The subcases are: + * - merging with the rightmost vertex of U or L + * - merging with the active edge of U or L + * - merging with an already-processed portion of U or L + */ { + ActiveRegion regUp, regLo, reg; + GLUhalfEdge eUp, eLo, eNew; + ActiveRegion tmp = new ActiveRegion(); + + /* assert ( vEvent.anEdge.Onext.Onext == vEvent.anEdge ); */ + + /* Get a pointer to the active region containing vEvent */ + tmp.eUp = vEvent.anEdge.Sym; + /* __GL_DICTLISTKEY */ /* __gl_dictListSearch */ + regUp = (ActiveRegion) Dict.dictKey(Dict.dictSearch(tess.dict, tmp)); + regLo = RegionBelow(regUp); + eUp = regUp.eUp; + eLo = regLo.eUp; + + /* Try merging with U or L first */ + if (Geom.EdgeSign(eUp.Sym.Org, vEvent, eUp.Org) == 0) { + ConnectLeftDegenerate(tess, regUp, vEvent); + return; + } + + /* Connect vEvent to rightmost processed vertex of either chain. + * e.Sym.Org is the vertex that we will connect to vEvent. + */ + reg = Geom.VertLeq(eLo.Sym.Org, eUp.Sym.Org) ? regUp : regLo; + + if (regUp.inside || reg.fixUpperEdge) { + if (reg == regUp) { + eNew = Mesh.__gl_meshConnect(vEvent.anEdge.Sym, eUp.Lnext); + if (eNew == null) throw new RuntimeException(); + } else { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(eLo.Sym.Onext.Sym, vEvent.anEdge); + if (tempHalfEdge == null) throw new RuntimeException(); + + eNew = tempHalfEdge.Sym; + } + if (reg.fixUpperEdge) { + if (!FixUpperEdge(reg, eNew)) throw new RuntimeException(); + } else { + ComputeWinding(tess, AddRegionBelow(tess, regUp, eNew)); + } + SweepEvent(tess, vEvent); + } else { + /* The new vertex is in a region which does not belong to the polygon. + * We don''t need to connect this vertex to the rest of the mesh. + */ + AddRightEdges(tess, regUp, vEvent.anEdge, vEvent.anEdge, null, true); + } + } + + + static void SweepEvent(GLUtessellatorImpl tess, GLUvertex vEvent) +/* + * Does everything necessary when the sweep line crosses a vertex. + * Updates the mesh and the edge dictionary. + */ { + ActiveRegion regUp, reg; + GLUhalfEdge e, eTopLeft, eBottomLeft; + + tess.event = vEvent; /* for access in EdgeLeq() */ + DebugEvent(tess); + + /* Check if this vertex is the right endpoint of an edge that is + * already in the dictionary. In this case we don't need to waste + * time searching for the location to insert new edges. + */ + e = vEvent.anEdge; + while (e.activeRegion == null) { + e = e.Onext; + if (e == vEvent.anEdge) { + /* All edges go right -- not incident to any processed edges */ + ConnectLeftVertex(tess, vEvent); + return; + } + } + + /* Processing consists of two phases: first we "finish" all the + * active regions where both the upper and lower edges terminate + * at vEvent (ie. vEvent is closing off these regions). + * We mark these faces "inside" or "outside" the polygon according + * to their winding number, and delete the edges from the dictionary. + * This takes care of all the left-going edges from vEvent. + */ + regUp = TopLeftRegion(e.activeRegion); + if (regUp == null) throw new RuntimeException(); + reg = RegionBelow(regUp); + eTopLeft = reg.eUp; + eBottomLeft = FinishLeftRegions(tess, reg, null); + + /* Next we process all the right-going edges from vEvent. This + * involves adding the edges to the dictionary, and creating the + * associated "active regions" which record information about the + * regions between adjacent dictionary edges. + */ + if (eBottomLeft.Onext == eTopLeft) { + /* No right-going edges -- add a temporary "fixable" edge */ + ConnectRightVertex(tess, regUp, eBottomLeft); + } else { + AddRightEdges(tess, regUp, eBottomLeft.Onext, eTopLeft, eTopLeft, true); + } + } + + +/* Make the sentinel coordinates big enough that they will never be + * merged with real input features. (Even with the largest possible + * input contour and the maximum tolerance of 1.0, no merging will be + * done with coordinates larger than 3 * GLU_TESS_MAX_COORD). + */ + private static final double SENTINEL_COORD = (4.0 * GLU.GLU_TESS_MAX_COORD); + + static void AddSentinel(GLUtessellatorImpl tess, double t) +/* + * We add two sentinel edges above and below all other edges, + * to avoid special cases at the top and bottom. + */ { + GLUhalfEdge e; + ActiveRegion reg = new ActiveRegion(); + if (reg == null) throw new RuntimeException(); + + e = Mesh.__gl_meshMakeEdge(tess.mesh); + if (e == null) throw new RuntimeException(); + + e.Org.s = SENTINEL_COORD; + e.Org.t = t; + e.Sym.Org.s = -SENTINEL_COORD; + e.Sym.Org.t = t; + tess.event = e.Sym.Org; /* initialize it */ + + reg.eUp = e; + reg.windingNumber = 0; + reg.inside = false; + reg.fixUpperEdge = false; + reg.sentinel = true; + reg.dirty = false; + reg.nodeUp = Dict.dictInsert(tess.dict, reg); /* __gl_dictListInsertBefore */ + if (reg.nodeUp == null) throw new RuntimeException(); + } + + + static void InitEdgeDict(final GLUtessellatorImpl tess) +/* + * We maintain an ordering of edge intersections with the sweep line. + * This order is maintained in a dynamic dictionary. + */ { + /* __gl_dictListNewDict */ + tess.dict = Dict.dictNewDict(tess, new Dict.DictLeq() { + public boolean leq(Object frame, Object key1, Object key2) { + return EdgeLeq(tess, (ActiveRegion) key1, (ActiveRegion) key2); + } + }); + if (tess.dict == null) throw new RuntimeException(); + + AddSentinel(tess, -SENTINEL_COORD); + AddSentinel(tess, SENTINEL_COORD); + } + + + static void DoneEdgeDict(GLUtessellatorImpl tess) { + ActiveRegion reg; + int fixedEdges = 0; + + /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ + while ((reg = (ActiveRegion) Dict.dictKey(Dict.dictMin(tess.dict))) != null) { + /* + * At the end of all processing, the dictionary should contain + * only the two sentinel edges, plus at most one "fixable" edge + * created by ConnectRightVertex(). + */ + if (!reg.sentinel) { + assert (reg.fixUpperEdge); + assert (++fixedEdges == 1); + } + assert (reg.windingNumber == 0); + DeleteRegion(tess, reg); +/* __gl_meshDelete( reg.eUp );*/ + } + Dict.dictDeleteDict(tess.dict); /* __gl_dictListDeleteDict */ + } + + + static void RemoveDegenerateEdges(GLUtessellatorImpl tess) +/* + * Remove zero-length edges, and contours with fewer than 3 vertices. + */ { + GLUhalfEdge e, eNext, eLnext; + GLUhalfEdge eHead = tess.mesh.eHead; + + /*LINTED*/ + for (e = eHead.next; e != eHead; e = eNext) { + eNext = e.next; + eLnext = e.Lnext; + + if (Geom.VertEq(e.Org, e.Sym.Org) && e.Lnext.Lnext != e) { + /* Zero-length edge, contour has at least 3 edges */ + + SpliceMergeVertices(tess, eLnext, e); /* deletes e.Org */ + if (!Mesh.__gl_meshDelete(e)) throw new RuntimeException(); /* e is a self-loop */ + e = eLnext; + eLnext = e.Lnext; + } + if (eLnext.Lnext == e) { + /* Degenerate contour (one or two edges) */ + + if (eLnext != e) { + if (eLnext == eNext || eLnext == eNext.Sym) { + eNext = eNext.next; + } + if (!Mesh.__gl_meshDelete(eLnext)) throw new RuntimeException(); + } + if (e == eNext || e == eNext.Sym) { + eNext = eNext.next; + } + if (!Mesh.__gl_meshDelete(e)) throw new RuntimeException(); + } + } + } + + static boolean InitPriorityQ(GLUtessellatorImpl tess) +/* + * Insert all vertices into the priority queue which determines the + * order in which vertices cross the sweep line. + */ { + PriorityQ pq; + GLUvertex v, vHead; + + /* __gl_pqSortNewPriorityQ */ + pq = tess.pq = PriorityQ.pqNewPriorityQ(new PriorityQ.Leq() { + public boolean leq(Object key1, Object key2) { + return Geom.VertLeq(((GLUvertex) key1), (GLUvertex) key2); + } + }); + if (pq == null) return false; + + vHead = tess.mesh.vHead; + for (v = vHead.next; v != vHead; v = v.next) { + v.pqHandle = pq.pqInsert(v); /* __gl_pqSortInsert */ + if (v.pqHandle == Long.MAX_VALUE) break; + } + if (v != vHead || !pq.pqInit()) { /* __gl_pqSortInit */ + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + tess.pq = null; + return false; + } + + return true; + } + + + static void DonePriorityQ(GLUtessellatorImpl tess) { + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + } + + + static boolean RemoveDegenerateFaces(GLUmesh mesh) +/* + * Delete any degenerate faces with only two edges. WalkDirtyRegions() + * will catch almost all of these, but it won't catch degenerate faces + * produced by splice operations on already-processed edges. + * The two places this can happen are in FinishLeftRegions(), when + * we splice in a "temporary" edge produced by ConnectRightVertex(), + * and in CheckForLeftSplice(), where we splice already-processed + * edges to ensure that our dictionary invariants are not violated + * by numerical errors. + * + * In both these cases it is *very* dangerous to delete the offending + * edge at the time, since one of the routines further up the stack + * will sometimes be keeping a pointer to that edge. + */ { + GLUface f, fNext; + GLUhalfEdge e; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { + fNext = f.next; + e = f.anEdge; + assert (e.Lnext != e); + + if (e.Lnext.Lnext == e) { + /* A face with only two edges */ + AddWinding(e.Onext, e); + if (!Mesh.__gl_meshDelete(e)) return false; + } + } + return true; + } + + public static boolean __gl_computeInterior(GLUtessellatorImpl tess) +/* + * __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by tess.windingRule. + * Each interior region is guaranteed be monotone. + */ { + GLUvertex v, vNext; + + tess.fatalError = false; + + /* Each vertex defines an event for our sweep line. Start by inserting + * all the vertices in a priority queue. Events are processed in + * lexicographic order, ie. + * + * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y) + */ + RemoveDegenerateEdges(tess); + if (!InitPriorityQ(tess)) return false; /* if error */ + InitEdgeDict(tess); + + /* __gl_pqSortExtractMin */ + while ((v = (GLUvertex) tess.pq.pqExtractMin()) != null) { + for (; ;) { + vNext = (GLUvertex) tess.pq.pqMinimum(); /* __gl_pqSortMinimum */ + if (vNext == null || !Geom.VertEq(vNext, v)) break; + + /* Merge together all vertices at exactly the same location. + * This is more efficient than processing them one at a time, + * simplifies the code (see ConnectLeftDegenerate), and is also + * important for correct handling of certain degenerate cases. + * For example, suppose there are two identical edges A and B + * that belong to different contours (so without this code they would + * be processed by separate sweep events). Suppose another edge C + * crosses A and B from above. When A is processed, we split it + * at its intersection point with C. However this also splits C, + * so when we insert B we may compute a slightly different + * intersection point. This might leave two edges with a small + * gap between them. This kind of error is especially obvious + * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY). + */ + vNext = (GLUvertex) tess.pq.pqExtractMin(); /* __gl_pqSortExtractMin*/ + SpliceMergeVertices(tess, v.anEdge, vNext.anEdge); + } + SweepEvent(tess, v); + } + + /* Set tess.event for debugging purposes */ + /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ + tess.event = ((ActiveRegion) Dict.dictKey(Dict.dictMin(tess.dict))).eUp.Org; + DebugEvent(tess); + DoneEdgeDict(tess); + DonePriorityQ(tess); + + if (!RemoveDegenerateFaces(tess.mesh)) return false; + Mesh.__gl_meshCheckMesh(tess.mesh); + + return true; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessMono.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessMono.java new file mode 100644 index 000000000..ef89b1613 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessMono.java @@ -0,0 +1,241 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class TessMono { +/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region + * (what else would it do??) The region must consist of a single + * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this + * case means that any vertical line intersects the interior of the + * region in a single interval. + * + * Tessellation consists of adding interior edges (actually pairs of + * half-edges), to split the region into non-overlapping triangles. + * + * The basic idea is explained in Preparata and Shamos (which I don''t + * have handy right now), although their implementation is more + * complicated than this one. The are two edge chains, an upper chain + * and a lower chain. We process all vertices from both chains in order, + * from right to left. + * + * The algorithm ensures that the following invariant holds after each + * vertex is processed: the untessellated region consists of two + * chains, where one chain (say the upper) is a single edge, and + * the other chain is concave. The left vertex of the single edge + * is always to the left of all vertices in the concave chain. + * + * Each step consists of adding the rightmost unprocessed vertex to one + * of the two chains, and forming a fan of triangles from the rightmost + * of two chain endpoints. Determining whether we can add each triangle + * to the fan is a simple orientation test. By making the fan as large + * as possible, we restore the invariant (check it yourself). + */ + static boolean __gl_meshTessellateMonoRegion(GLUface face, boolean avoidDegenerateTris) { + GLUhalfEdge up, lo; + + /* All edges are oriented CCW around the boundary of the region. + * First, find the half-edge whose origin vertex is rightmost. + * Since the sweep goes from left to right, face->anEdge should + * be close to the edge we want. + */ + up = face.anEdge; + assert (up.Lnext != up && up.Lnext.Lnext != up); + + for (; Geom.VertLeq(up.Sym.Org, up.Org); up = up.Onext.Sym) + ; + for (; Geom.VertLeq(up.Org, up.Sym.Org); up = up.Lnext) + ; + lo = up.Onext.Sym; + + boolean mustConnect = false; // hack for avoidDegenerateTris + + while (up.Lnext != lo) { + if (avoidDegenerateTris && !mustConnect) { + // Skip over regions where several vertices are collinear, + // to try to avoid producing degenerate (zero-area) triangles + // + // The "mustConnect" flag is a hack to try to avoid + // skipping too large regions and causing incorrect + // triangulations. This entire modification is overall + // not robust and needs more work + if (Geom.EdgeCos(lo.Lnext.Org, lo.Org, lo.Lnext.Lnext.Org) <= -Geom.ONE_MINUS_EPSILON) { + // Lines around lo + do { + lo = lo.Onext.Sym; + mustConnect = true; + } while (up.Lnext != lo && + Geom.EdgeCos(lo.Lnext.Org, lo.Org, lo.Lnext.Lnext.Org) <= -Geom.ONE_MINUS_EPSILON); + } else if (Geom.EdgeCos(up.Onext.Sym.Org, up.Org, up.Onext.Sym.Onext.Sym.Org) <= -Geom.ONE_MINUS_EPSILON) { + // Lines around up + do { + up = up.Lnext; + mustConnect = true; + } while (up.Lnext != lo && + Geom.EdgeCos(up.Onext.Sym.Org, up.Org, up.Onext.Sym.Onext.Sym.Org) <= -Geom.ONE_MINUS_EPSILON); + } + + if (up.Lnext == lo) + break; + } + + if (Geom.VertLeq(up.Sym.Org, lo.Org)) { + /* up.Sym.Org is on the left. It is safe to form triangles from lo.Org. + * The EdgeGoesLeft test guarantees progress even when some triangles + * are CW, given that the upper and lower chains are truly monotone. + */ + while (lo.Lnext != up && (Geom.EdgeGoesLeft(lo.Lnext) + || Geom.EdgeSign(lo.Org, lo.Sym.Org, lo.Lnext.Sym.Org) <= 0)) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo); + mustConnect = false; + if (tempHalfEdge == null) return false; + lo = tempHalfEdge.Sym; + } + lo = lo.Onext.Sym; + } else { + /* lo.Org is on the left. We can make CCW triangles from up.Sym.Org. */ + while (lo.Lnext != up && (Geom.EdgeGoesRight(up.Onext.Sym) + || Geom.EdgeSign(up.Sym.Org, up.Org, up.Onext.Sym.Org) >= 0)) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(up, up.Onext.Sym); + mustConnect = false; + if (tempHalfEdge == null) return false; + up = tempHalfEdge.Sym; + } + up = up.Lnext; + } + } + + /* Now lo.Org == up.Sym.Org == the leftmost vertex. The remaining region + * can be tessellated in a fan from this leftmost vertex. + */ + assert (lo.Lnext != up); + while (lo.Lnext.Lnext != up) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo); + if (tempHalfEdge == null) return false; + lo = tempHalfEdge.Sym; + } + + return true; + } + + +/* __gl_meshTessellateInterior( mesh ) tessellates each region of + * the mesh which is marked "inside" the polygon. Each such region + * must be monotone. + */ + public static boolean __gl_meshTessellateInterior(GLUmesh mesh, boolean avoidDegenerateTris) { + GLUface f, next; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = next) { + /* Make sure we don''t try to tessellate the new triangles. */ + next = f.next; + if (f.inside) { + if (!__gl_meshTessellateMonoRegion(f, avoidDegenerateTris)) return false; + } + } + + return true; + } + + +/* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces + * which are not marked "inside" the polygon. Since further mesh operations + * on NULL faces are not allowed, the main purpose is to clean up the + * mesh so that exterior loops are not represented in the data structure. + */ + public static void __gl_meshDiscardExterior(GLUmesh mesh) { + GLUface f, next; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = next) { + /* Since f will be destroyed, save its next pointer. */ + next = f.next; + if (!f.inside) { + Mesh.__gl_meshZapFace(f); + } + } + } + + private static final int MARKED_FOR_DELETION = 0x7fffffff; + +/* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the + * winding numbers on all edges so that regions marked "inside" the + * polygon have a winding number of "value", and regions outside + * have a winding number of 0. + * + * If keepOnlyBoundary is TRUE, it also deletes all edges which do not + * separate an interior region from an exterior one. + */ + public static boolean __gl_meshSetWindingNumber(GLUmesh mesh, int value, boolean keepOnlyBoundary) { + GLUhalfEdge e, eNext; + + for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { + eNext = e.next; + if (e.Sym.Lface.inside != e.Lface.inside) { + + /* This is a boundary edge (one side is interior, one is exterior). */ + e.winding = (e.Lface.inside) ? value : -value; + } else { + + /* Both regions are interior, or both are exterior. */ + if (!keepOnlyBoundary) { + e.winding = 0; + } else { + if (!Mesh.__gl_meshDelete(e)) return false; + } + } + } + return true; + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessState.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessState.java new file mode 100644 index 000000000..a8aa41d9f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessState.java @@ -0,0 +1,59 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class TessState { + public static final int T_DORMANT = 0; + public static final int T_IN_POLYGON = 1; + public static final int T_IN_CONTOUR = 2; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java new file mode 100644 index 000000000..ebefaf466 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java @@ -0,0 +1,340 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; + +public abstract class MacOSXCGLContext extends GLContextImpl +{ + protected long nsContext; // NSOpenGLContext + protected long cglContext; // CGLContextObj + private CGLExt cglExt; + // Table that holds the addresses of the native C-language entry points for + // CGL extension functions. + private CGLExtProcAddressTable cglExtProcAddressTable; + + public MacOSXCGLContext(GLDrawableImpl drawable, GLDrawableImpl drawableRead, + GLContext shareWith) { + super(drawable, drawableRead, shareWith); + } + + public MacOSXCGLContext(GLDrawableImpl drawable, + GLContext shareWith) { + this(drawable, null, shareWith); + } + + public Object getPlatformGLExtensions() { + return getCGLExt(); + } + + public CGLExt getCGLExt() { + if (cglExt == null) { + cglExt = new CGLExtImpl(this); + } + return cglExt; + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return getCGLExtProcAddressTable(); + } + + public final CGLExtProcAddressTable getCGLExtProcAddressTable() { + return cglExtProcAddressTable; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return null; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return null; } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + return 0; // FIXME + } + + protected void destroyContextARBImpl(long _context) { + // FIXME + } + + /** + * Creates and initializes an appropriate OpenGl nsContext. Should only be + * called by {@link makeCurrentImpl()}. + */ + protected boolean create(boolean pbuffer, boolean floatingPoint) { + MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getNSContext(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilitiesRequested = (GLCapabilities)config.getRequestedCapabilities(); + GLProfile glProfile = capabilitiesRequested.getGLProfile(); + if(glProfile.isGL3()) { + throw new GLException("GL3 profile currently not supported on MacOSX, due to the lack of a OpenGL 3.1 implementation"); + } + // HACK .. bring in OnScreen/PBuffer selection to the DrawableFactory !! + GLCapabilities capabilities = (GLCapabilities) capabilitiesRequested.clone(); + capabilities.setPBuffer(pbuffer); + capabilities.setPbufferFloatingPointBuffers(floatingPoint); + + long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(capabilities); + if (pixelFormat == 0) { + throw new GLException("Unable to allocate pixel format with requested GLCapabilities"); + } + config.setChosenPixelFormat(pixelFormat); + try { + int[] viewNotReady = new int[1]; + // Try to allocate a context with this + nsContext = CGL.createContext(share, + drawable.getNativeWindow().getSurfaceHandle(), + pixelFormat, + viewNotReady, 0); + if (nsContext == 0) { + if (viewNotReady[0] == 1) { + if (DEBUG) { + System.err.println("!!! View not ready for " + getClass().getName()); + } + // View not ready at the window system level -- this is OK + return false; + } + throw new GLException("Error creating NSOpenGLContext with requested pixel format"); + } + + if (!pbuffer && !capabilities.isBackgroundOpaque()) { + // Set the context opacity + CGL.setContextOpacity(nsContext, 0); + } + + GLCapabilities caps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(glProfile, pixelFormat); + config.setChosenCapabilities(caps); + } finally { + CGL.deletePixelFormat(pixelFormat); + } + if (!CGL.makeCurrentContext(nsContext)) { + throw new GLException("Error making nsContext current"); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + GLContextShareSet.contextCreated(this); + return true; + } + + protected int makeCurrentImpl() throws GLException { + if (0 == cglContext && drawable.getNativeWindow().getSurfaceHandle() == 0) { + throw new GLException("drawable not properly initialized: "+drawable); + } + boolean created = false; + if ( 0 == cglContext && 0 == nsContext) { + create(); + created = 0 != cglContext || 0 != nsContext ; + if(!created) { + return CONTEXT_NOT_CURRENT; + } + if (DEBUG) { + System.err.println("!!! Created OpenGL context " + toHexString(nsContext) + " for " + getClass().getName()); + } + } + + if ( 0 != cglContext ) { + if (CGL.kCGLNoError != CGL.CGLSetCurrentContext(cglContext)) { + throw new GLException("Error making cglContext current"); + } + } else { + if (!CGL.makeCurrentContext(nsContext)) { + throw new GLException("Error making nsContext current"); + } + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + if ( 0 != cglContext ) { + CGL.CGLReleaseContext(cglContext); + } else { + if (!CGL.clearCurrentContext(nsContext)) { + throw new GLException("Error freeing OpenGL nsContext"); + } + } + } + + protected void destroyImpl() throws GLException { + boolean hadContext = isCreated(); + if ( 0 != cglContext ) { + if (CGL.kCGLNoError != CGL.CGLDestroyContext(cglContext)) { + throw new GLException("Unable to delete OpenGL cglContext"); + } + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL cglContext " + cglContext); + } + cglContext = 0; + GLContextShareSet.contextDestroyed(this); + } else if ( 0 != nsContext ) { + if (!CGL.deleteContext(nsContext)) { + throw new GLException("Unable to delete OpenGL nsContext"); + } + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL nsContext " + nsContext); + } + nsContext = 0; + } + if(hadContext) { + GLContextShareSet.contextDestroyed(this); + } + } + + public boolean isCreated() { + return 0 != cglContext || 0 != nsContext ; + } + + public void copy(GLContext source, int mask) throws GLException { + long dst = getCGLContext(); + long src = 0; + if( 0 != dst ) { + src = ((MacOSXCGLContext) source).getCGLContext(); + if (src == 0) { + throw new GLException("Source OpenGL cglContext has not been created ; Destination has a cglContext."); + } + CGL.CGLCopyContext(src, dst, mask); + } else { + dst = getNSContext(); + src = ((MacOSXCGLContext) source).getNSContext(); + if (src == 0) { + throw new GLException("Source OpenGL nsContext has not been created"); + } + if (dst == 0) { + throw new GLException("Destination OpenGL nsContext has not been created"); + } + CGL.copyContext(dst, src, mask); + } + } + + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if (DEBUG) { + System.err.println("!!! Initializing CGL extension address table"); + } + if (cglExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + cglExtProcAddressTable = new CGLExtProcAddressTable(); + } + resetProcAddressTable(getCGLExtProcAddressTable()); + super.updateGLProcAddressTable(major, minor, ctp); + } + + public String getPlatformExtensionsString() + { + return ""; + } + + protected void setSwapIntervalImpl(int interval) { + if ( 0 != cglContext ) { + int[] lval = new int[] { (int) interval } ; + CGL.CGLSetParameter(cglContext, CGL.kCGLCPSwapInterval, lval, 0); + } else if ( 0 != nsContext ) { + CGL.setSwapInterval(nsContext, interval); + } else { + throw new GLException("OpenGL context not current"); + } + currentSwapInterval = interval ; + } + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + // FIXME: apparently the Apple extension doesn't require a custom memory allocator + throw new GLException("Not yet implemented"); + } + + public boolean isFunctionAvailable(String glFunctionName) + { + return super.isFunctionAvailable(glFunctionName); + } + + public boolean isExtensionAvailable(String glExtensionName) { + if (glExtensionName.equals("GL_ARB_pbuffer") || + glExtensionName.equals("GL_ARB_pixel_format")) { + return true; + } + return super.isExtensionAvailable(glExtensionName); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + // Support for "mode switching" as described in MacOSXCGLDrawable + public abstract void setOpenGLMode(int mode); + public abstract int getOpenGLMode(); + + //---------------------------------------------------------------------- + // Internals only below this point + // + + public long getCGLContext() { + return cglContext; + } + public long getNSContext() { + return nsContext; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawable.java new file mode 100644 index 000000000..cf29d214b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawable.java @@ -0,0 +1,106 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.common.os.DynamicLookupHelper; + +public abstract class MacOSXCGLDrawable extends GLDrawableImpl { + // The Java2D/OpenGL pipeline on OS X uses low-level CGLContextObjs + // to represent the contexts for e.g. the Java2D back buffer. When + // the Java2D/JOGL bridge is active, this means that if we want to + // be able to share textures and display lists with the Java2D + // contexts, we need to use the CGL APIs rather than the NSOpenGL + // APIs on the JOGL side. For example, if we create a pbuffer using + // the NSOpenGL APIs and want to share textures and display lists + // between it and the Java2D back buffer, there is no way to do so, + // because the Java2D context is actually a CGLContextObj and the + // NSOpenGLContext's initWithFormat:shareContext: only accepts an + // NSOpenGLContext as its second argument. Of course there is no way + // to wrap an NSOpenGLContext around an arbitrary CGLContextObj. + // + // The situation we care most about is allowing a GLPbuffer to share + // textures, etc. with a GLJPanel when the Java2D/JOGL bridge is + // active; several of the demos rely on this functionality. We aim + // to get there by allowing a GLPBuffer to switch its implementation + // between using an NSOpenGLPixelBuffer and a CGLPBufferObj. In + // order to track whether this has been done we need to have the + // notion of a "mode" of both the MacOSXCGLDrawable and the + // MacOSXGLContext. Initially the mode is "unspecified", meaning it + // leans toward the default (NSOpenGL). If sharing is requested + // between either a GLJPanel and a GLPbuffer or a GLCanvas and a + // GLPbuffer, the GLPbuffer will be switched into the appropriate + // mode: CGL mode for a GLJPanel and NSOpenGL mode for a GLCanvas. + // To avoid thrashing we support exactly one such switch during the + // lifetime of a given GLPbuffer. This is not a fully general + // solution (for example, you can't share textures among a + // GLPbuffer, a GLJPanel and a GLCanvas simultaneously) but should + // be enough to get things off the ground. + public static final int NSOPENGL_MODE = 1; + public static final int CGL_MODE = 2; + + public MacOSXCGLDrawable(GLDrawableFactory factory, NativeWindow comp, boolean realized) { + super(factory, comp, realized); + } + + protected void setRealizedImpl() { + if(realized) { + if( NativeWindow.LOCK_SURFACE_NOT_READY == lockSurface() ) { + throw new GLException("Couldn't lock surface"); + } + // locking the surface is essential to update surface data + unlockSurface(); + } + } + + public DynamicLookupHelper getDynamicLookupHelper() { + return (MacOSXCGLDrawableFactory) getFactoryImpl() ; + } + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } + + // Support for "mode switching" as per above + public abstract void setOpenGLMode(int mode); + public abstract int getOpenGLMode(); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java new file mode 100644 index 000000000..d10434252 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -0,0 +1,164 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import com.jogamp.common.os.DynamicLookupHelper; +import java.nio.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { + public MacOSXCGLDrawableFactory() { + super(); + + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new MacOSXCGLGraphicsConfigurationFactory(); + + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.macosx.cgl.awt.MacOSXAWTCGLGraphicsConfigurationFactory", + new Object[] {}); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + } + + protected final GLDrawableImpl getSharedDrawable() { return null; } + protected final GLContextImpl getSharedContext() { return null; } + + public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new MacOSXOnscreenCGLDrawable(this, target); + } + + protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + return new MacOSXOffscreenCGLDrawable(this, target); + } + + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + return true; + } + + protected GLDrawableImpl createGLPbufferDrawableImpl(final NativeWindow target) { + /** + * FIXME: Think about this .. + * should not be necessary ? .. + final List returnList = new ArrayList(); + final GLDrawableFactory factory = this; + Runnable r = new Runnable() { + public void run() { + returnList.add(new MacOSXPbufferCGLDrawable(factory, target)); + } + }; + maybeDoSingleThreadedWorkaround(r); + return (GLDrawableImpl) returnList.get(0); + */ + return new MacOSXPbufferCGLDrawable(this, target); + } + + protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { + AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(); + NullWindow nw = new NullWindow(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, screen, true)); + nw.setSize(width, height); + return nw; + } + + public GLContext createExternalGLContext() { + return MacOSXExternalCGLContext.create(this, null); + } + + public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + return false; + } + + public GLDrawable createExternalGLDrawable() { + // FIXME + throw new GLException("Not yet implemented"); + } + + public void loadGLULibrary() { + // Nothing to do; already loaded by native code; not much point in + // making it lazier on this platform + } + + public long dynamicLookupFunction(String glFuncName) { + return CGL.getProcAddress(glFuncName); + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + throw new GLException("not supported in non AWT enviroment"); + } + + //------------------------------------------------------ + // Gamma-related functionality + // + + private static final int GAMMA_RAMP_LENGTH = 256; + + /** Returns the length of the computed gamma ramp for this OS and + hardware. Returns 0 if gamma changes are not supported. */ + protected int getGammaRampLength() { + return GAMMA_RAMP_LENGTH; + } + + protected boolean setGammaRamp(float[] ramp) { + return CGL.setGammaRamp(ramp.length, + ramp, 0, + ramp, 0, + ramp, 0); + } + + protected Buffer getGammaRamp() { + return null; + } + + protected void resetGammaRamp(Buffer originalGammaRamp) { + CGL.resetGammaRamp(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java new file mode 100644 index 000000000..889d1c333 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2008 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; + +public class MacOSXCGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { + long pixelformat; + + public MacOSXCGLGraphicsConfiguration(AbstractGraphicsScreen screen, GLCapabilities capsChosen, GLCapabilities capsRequested, + long pixelformat) { + super(screen, capsChosen, capsRequested); + this.pixelformat=pixelformat; + } + + public Object clone() { + return super.clone(); + } + + protected void setChosenPixelFormat(long pixelformat) { + this.pixelformat=pixelformat; + } + + protected void setChosenCapabilities(GLCapabilities caps) { + super.setChosenCapabilities(caps); + } + + protected static final int[] cglInternalAttributeToken = new int[] { + CGL.kCGLPFAColorFloat, + CGL.NSOpenGLPFAPixelBuffer, + CGL.NSOpenGLPFADoubleBuffer, + CGL.NSOpenGLPFAStereo, + CGL.NSOpenGLPFAColorSize, + CGL.NSOpenGLPFAAlphaSize, + CGL.NSOpenGLPFADepthSize, + CGL.NSOpenGLPFAAccumSize, + CGL.NSOpenGLPFAStencilSize, + CGL.NSOpenGLPFASampleBuffers, + CGL.NSOpenGLPFASamples }; + + protected static int[] GLCapabilities2AttribList(GLCapabilities caps) { + int[] ivalues = new int[cglInternalAttributeToken.length]; + + for (int idx = 0; idx < cglInternalAttributeToken.length; idx++) { + int attr = cglInternalAttributeToken[idx]; + switch (attr) { + case CGL.kCGLPFAColorFloat: + ivalues[idx] = caps.getPbufferFloatingPointBuffers() ? 1 : 0; + break; + + case CGL.NSOpenGLPFAPixelBuffer: + ivalues[idx] = caps.isPBuffer() ? 1 : 0; + break; + + case CGL.NSOpenGLPFADoubleBuffer: + ivalues[idx] = (caps.getDoubleBuffered() ? 1 : 0); + break; + + case CGL.NSOpenGLPFAStereo: + ivalues[idx] = (caps.getStereo() ? 1 : 0); + break; + + case CGL.NSOpenGLPFAColorSize: + ivalues[idx] = (caps.getRedBits() + caps.getGreenBits() + caps.getBlueBits()); + break; + + case CGL.NSOpenGLPFAAlphaSize: + ivalues[idx] = caps.getAlphaBits(); + break; + + case CGL.NSOpenGLPFADepthSize: + ivalues[idx] = caps.getDepthBits(); + break; + + case CGL.NSOpenGLPFAAccumSize: + ivalues[idx] = (caps.getAccumRedBits() + caps.getAccumGreenBits() + caps.getAccumBlueBits() + caps.getAccumAlphaBits()); + break; + + case CGL.NSOpenGLPFAStencilSize: + ivalues[idx] = caps.getStencilBits(); + break; + + case CGL.NSOpenGLPFASampleBuffers: + ivalues[idx] = caps.getSampleBuffers() ? 1 : 0; + break; + + case CGL.NSOpenGLPFASamples: + ivalues[idx] = caps.getSampleBuffers() ? ivalues[idx] = caps.getNumSamples() : 0; + break; + + default: + break; + } + } + return ivalues; + } + + protected static long GLCapabilities2NSPixelFormat(GLCapabilities caps) { + int[] ivalues = GLCapabilities2AttribList(caps); + return CGL.createPixelFormat(cglInternalAttributeToken, 0, cglInternalAttributeToken.length, ivalues, 0); + } + + protected static GLCapabilities NSPixelFormat2GLCapabilities(GLProfile glp, long pixelFormat) { + return PixelFormat2GLCapabilities(glp, pixelFormat, true); + } + + protected static GLCapabilities CGLPixelFormat2GLCapabilities(GLProfile glp, long pixelFormat) { + return PixelFormat2GLCapabilities(glp, pixelFormat, false); + } + + private static GLCapabilities PixelFormat2GLCapabilities(GLProfile glp, long pixelFormat, boolean nsUsage) { + int[] ivalues = new int[cglInternalAttributeToken.length]; + + // On this platform the pixel format is associated with the + // context and not the drawable. However it's a reasonable + // approximation to just store the chosen pixel format up in the + // NativeWindow's AbstractGraphicsConfiguration, + // since the public API doesn't provide for a different GLCapabilities per context. + // Note: These restrictions of the platform's API might be considered as a bug anyways. + + // Figure out what attributes we really got + GLCapabilities caps = new GLCapabilities(glp); + if(nsUsage) { + CGL.queryPixelFormat(pixelFormat, cglInternalAttributeToken, 0, cglInternalAttributeToken.length, ivalues, 0); + } else { + CGL.CGLQueryPixelFormat(pixelFormat, cglInternalAttributeToken, 0, cglInternalAttributeToken.length, ivalues, 0); + } + for (int i = 0; i < cglInternalAttributeToken.length; i++) { + int attr = cglInternalAttributeToken[i]; + switch (attr) { + case CGL.kCGLPFAColorFloat: + caps.setPbufferFloatingPointBuffers(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFAPixelBuffer: + caps.setPBuffer(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFADoubleBuffer: + caps.setDoubleBuffered(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFAStereo: + caps.setStereo(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFAColorSize: + { + int bitSize = ivalues[i]; + if (bitSize == 32) + bitSize = 24; + bitSize /= 3; + caps.setRedBits(bitSize); + caps.setGreenBits(bitSize); + caps.setBlueBits(bitSize); + } + break; + + case CGL.NSOpenGLPFAAlphaSize: + caps.setAlphaBits(ivalues[i]); + break; + + case CGL.NSOpenGLPFADepthSize: + caps.setDepthBits(ivalues[i]); + break; + + case CGL.NSOpenGLPFAAccumSize: + { + int bitSize = ivalues[i] / 4; + caps.setAccumRedBits(bitSize); + caps.setAccumGreenBits(bitSize); + caps.setAccumBlueBits(bitSize); + caps.setAccumAlphaBits(bitSize); + } + break; + + case CGL.NSOpenGLPFAStencilSize: + caps.setStencilBits(ivalues[i]); + break; + + case CGL.NSOpenGLPFASampleBuffers: + caps.setSampleBuffers(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFASamples: + caps.setNumSamples(ivalues[i]); + break; + + default: + break; + } + } + + return caps; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..ada5fb1a7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.macosx.*; +import com.jogamp.nativewindow.impl.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on OSX platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class MacOSXCGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public MacOSXCGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.macosx.MacOSXGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + return chooseGraphicsConfigurationStatic(capabilities, chooser, absScreen, false); + } + + protected static MacOSXCGLGraphicsConfiguration chooseGraphicsConfigurationStatic(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen, boolean usePBuffer) { + if (absScreen == null) { + throw new IllegalArgumentException("AbstractGraphicsScreen is null"); + } + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + + if (capabilities == null) { + capabilities = new GLCapabilities(null); + } + + return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilities)capabilities, (GLCapabilities)capabilities, 0); + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java new file mode 100644 index 000000000..eba3cf50e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2005 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +import javax.media.nativewindow.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class MacOSXExternalCGLContext extends MacOSXCGLContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + private MacOSXExternalCGLContext(Drawable drawable, long cglContext, long nsContext) { + super(drawable, null); + drawable.setExternalCGLContext(this); + this.cglContext = cglContext; + this.nsContext = nsContext; + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + protected static MacOSXExternalCGLContext create(GLDrawableFactory factory, GLProfile glp) { + ((GLDrawableFactoryImpl)factory).lockToolkit(); + try { + long pixelFormat = 0; + long currentDrawable = 0; + long cglContext = 0; + long nsContext = CGL.getCurrentContext(); // Check: MacOSX 10.3 .. + if( 0 != nsContext ) { + currentDrawable = CGL.getNSView(nsContext); + long ctx = CGL.getCGLContext(nsContext); + if (ctx == 0) { + throw new GLException("Error: NULL cglContext of nsContext 0x" +Long.toHexString(nsContext)); + } + pixelFormat = CGL.CGLGetPixelFormat(ctx); + if(DEBUG) { + System.err.println("MacOSXExternalCGLContext Create nsContext 0x"+Long.toHexString(nsContext)+ + ", cglContext 0x"+Long.toHexString(ctx)+ + ", pixelFormat 0x"+Long.toHexString(pixelFormat)); + } + } else { + cglContext = CGL.CGLGetCurrentContext(); + if (cglContext == 0) { + throw new GLException("Error: current cglContext null, no nsContext"); + } + pixelFormat = CGL.CGLGetPixelFormat(cglContext); + if(DEBUG) { + System.err.println("MacOSXExternalCGLContext Create cglContext 0x"+Long.toHexString(cglContext)+ + ", pixelFormat 0x"+Long.toHexString(pixelFormat)); + } + } + + if (0 == pixelFormat) { + throw new GLException("Error: current pixelformat of current cglContext 0x"+Long.toHexString(cglContext)+" is null"); + } + GLCapabilities caps = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(glp, pixelFormat); + if(DEBUG) { + System.err.println("MacOSXExternalCGLContext Create "+caps); + } + + AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(); + MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps, pixelFormat); + + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(currentDrawable); + return new MacOSXExternalCGLContext(new Drawable(factory, nw), cglContext, nsContext); + } finally { + ((GLDrawableFactoryImpl)factory).unlockToolkit(); + } + } + + protected void create() { + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + protected void swapBuffers() { + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities caps = (GLCapabilities)config.getChosenCapabilities(); + if(caps.isOnscreen()) { + if (CGL.kCGLNoError != CGL.CGLFlushDrawable(cglContext)) { + throw new GLException("Error swapping buffers"); + } + } + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } + + public void setOpenGLMode(int mode) { + if (mode != MacOSXCGLDrawable.CGL_MODE) + throw new GLException("OpenGL mode switching not supported for external GLContexts"); + } + + public int getOpenGLMode() { + return MacOSXCGLDrawable.CGL_MODE; + } + + // Need to provide the display connection to extension querying APIs + static class Drawable extends MacOSXCGLDrawable { + MacOSXExternalCGLContext extCtx; + + Drawable(GLDrawableFactory factory, NativeWindow comp) { + super(factory, comp, true); + } + + void setExternalCGLContext(MacOSXExternalCGLContext externalContext) { + extCtx = externalContext; + } + + public GLContext createContext(GLContext shareWith) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } + + public void setSize(int width, int height) { + throw new GLException("Should not call this"); + } + + protected void swapBuffersImpl() { + if (extCtx != null) { + extCtx.swapBuffers(); + } + } + + public void setOpenGLMode(int mode) { + if (mode != CGL_MODE) + throw new GLException("OpenGL mode switching not supported for external GLContext's drawables"); + } + + public int getOpenGLMode() { + return CGL_MODE; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLContext.java new file mode 100644 index 000000000..89e293665 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLContext.java @@ -0,0 +1,64 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXOffscreenCGLContext extends MacOSXPbufferCGLContext +{ + public MacOSXOffscreenCGLContext(MacOSXPbufferCGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + } + + public int getOffscreenContextPixelDataType() { + GL gl = getGL(); + return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1; + } + + public int getOffscreenContextReadBuffer() { + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + return true; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLDrawable.java new file mode 100644 index 000000000..adaa48f34 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLDrawable.java @@ -0,0 +1,56 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXOffscreenCGLDrawable extends MacOSXPbufferCGLDrawable { + + public MacOSXOffscreenCGLDrawable(GLDrawableFactory factory, + NativeWindow target) { + super(factory, target); + } + + public GLContext createContext(GLContext shareWith) { + return new MacOSXOffscreenCGLContext(this, shareWith); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLContext.java new file mode 100644 index 000000000..c4eaee489 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLContext.java @@ -0,0 +1,130 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXOnscreenCGLContext extends MacOSXCGLContext { + protected MacOSXOnscreenCGLDrawable drawable; + + public MacOSXOnscreenCGLContext(MacOSXOnscreenCGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + int ret = super.makeCurrentImpl(); + if ((ret == CONTEXT_CURRENT) || + (ret == CONTEXT_CURRENT_NEW)) { + // Assume the canvas might have been resized or moved and tell the OpenGL + // context to update itself. This used to be done only upon receiving a + // reshape event but that doesn't appear to be sufficient. An experiment + // was also done to add a HierarchyBoundsListener to the GLCanvas and + // do this updating only upon reshape of this component or reshape or movement + // of an ancestor, but this also wasn't sufficient and left garbage on the + // screen in some situations. + CGL.updateContext(nsContext); + } else { + if (!isOptimizable()) { + // This can happen if the window currently is zero-sized, for example. + // Make sure we don't leave the surface locked in this case. + drawable.unlockSurface(); + lockRes = NativeWindow.LOCK_SURFACE_NOT_READY; + } + } + return ret; + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY)) { + drawable.unlockSurface(); + } + } + } + + protected void releaseImpl() throws GLException { + try { + super.releaseImpl(); + } finally { + if (!isOptimizable() && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + protected void swapBuffers() { + if (!CGL.flushBuffer(nsContext)) { + throw new GLException("Error swapping buffers"); + } + } + + protected void update() throws GLException { + if (nsContext == 0) { + throw new GLException("Context not created"); + } + CGL.updateContext(nsContext); + } + + protected void create() { + create(false, false); + } + + public void setOpenGLMode(int mode) { + if (mode != MacOSXCGLDrawable.NSOPENGL_MODE) + throw new GLException("OpenGL mode switching not supported for on-screen GLContexts"); + } + + public int getOpenGLMode() { + return MacOSXCGLDrawable.NSOPENGL_MODE; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLDrawable.java new file mode 100644 index 000000000..6ee023867 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLDrawable.java @@ -0,0 +1,100 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import java.lang.ref.WeakReference; +import java.security.*; +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable { + private List/*<WeakReference<GLContext>>*/ createdContexts = + new ArrayList(); + + protected MacOSXOnscreenCGLDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, false); + } + + public GLContext createContext(GLContext shareWith) { + MacOSXOnscreenCGLContext context = + new MacOSXOnscreenCGLContext(this, shareWith); + // NOTE: we need to keep track of the created contexts in order to + // implement swapBuffers() because of how Mac OS X implements its + // OpenGL window interface + synchronized (this) { + List newContexts = new ArrayList(); + newContexts.addAll(createdContexts); + newContexts.add(new WeakReference(context)); + createdContexts = newContexts; + } + return context; + } + + public int getWidth() { + return component.getWidth(); + } + + public int getHeight() { + return component.getHeight(); + } + + protected void swapBuffersImpl() { + for (Iterator iter = createdContexts.iterator(); iter.hasNext(); ) { + WeakReference ref = (WeakReference) iter.next(); + MacOSXOnscreenCGLContext ctx = (MacOSXOnscreenCGLContext) ref.get(); + // FIXME: clear out unreachable contexts + if (ctx != null) { + ctx.swapBuffers(); + } + } + } + + public void setOpenGLMode(int mode) { + if (mode != NSOPENGL_MODE) + throw new GLException("OpenGL mode switching not supported for on-screen GLDrawables"); + } + + public int getOpenGLMode() { + return NSOPENGL_MODE; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLContext.java new file mode 100644 index 000000000..52a892b70 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLContext.java @@ -0,0 +1,359 @@ +package com.jogamp.opengl.impl.macosx.cgl; + +import com.jogamp.common.nio.PointerBuffer; +import java.security.*; +import java.util.*; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXPbufferCGLContext extends MacOSXCGLContext { + protected MacOSXPbufferCGLDrawable drawable; + + // State for render-to-texture and render-to-texture-rectangle support + private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV + private int texture; // actual texture object + + private static boolean isTigerOrLater; + + static { + String osVersion = Debug.getProperty("os.version", false, AccessController.getContext()); + StringTokenizer tok = new StringTokenizer(osVersion, ". "); + int major = Integer.parseInt(tok.nextToken()); + int minor = Integer.parseInt(tok.nextToken()); + isTigerOrLater = ((major > 10) || (minor > 3)); + } + + public MacOSXPbufferCGLContext(MacOSXPbufferCGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + initOpenGLImpl(); + } + + public void bindPbufferToTexture() { + GL gl = getGL(); + gl.glBindTexture(textureTarget, texture); + // FIXME: not clear whether this is really necessary, but since + // the API docs seem to imply it is and since it doesn't seem to + // impact performance, leaving it in + CGL.setContextTextureImageToPBuffer(nsContext, drawable.getPbuffer(), GL.GL_FRONT); + } + + public void releasePbufferFromTexture() { + } + + protected int makeCurrentImpl() throws GLException { + if (drawable.getPbuffer() == 0) { + if (DEBUG) { + System.err.println("Pbuffer not instantiated yet for " + this); + } + // pbuffer not instantiated yet + return CONTEXT_NOT_CURRENT; + } + + if (getOpenGLMode() != drawable.getOpenGLMode()) { + setOpenGLMode(drawable.getOpenGLMode()); + } + + boolean created = false; + if (nsContext == 0) { + create(); + created = 0 != nsContext ; + if(!created) { + return CONTEXT_NOT_CURRENT; + } + if (DEBUG) { + System.err.println("!!! Created OpenGL context " + toHexString(nsContext) + " for " + getClass().getName()); + } + } + + if (!impl.makeCurrent(nsContext)) { + throw new GLException("Error making nsContext current"); + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + + // Initialize render-to-texture support if requested + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + GL gl = getGL(); + boolean rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle(); + if (rect) { + if (!gl.isExtensionAvailable("GL_EXT_texture_rectangle")) { + System.err.println("MacOSXPbufferCGLContext: WARNING: GL_EXT_texture_rectangle extension not " + + "supported; skipping requested render_to_texture_rectangle support for pbuffer"); + rect = false; + } + } + textureTarget = (rect ? GL2.GL_TEXTURE_RECTANGLE : GL.GL_TEXTURE_2D); + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp, 0); + texture = tmp[0]; + gl.glBindTexture(textureTarget, texture); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); + gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0); + + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + if (!impl.release(nsContext)) { + throw new GLException("Error releasing OpenGL nsContext"); + } + } + + protected void destroyImpl() throws GLException { + if (nsContext != 0) { + if (!impl.destroy(nsContext)) { + throw new GLException("Unable to delete OpenGL context"); + } + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL context " + nsContext); + } + nsContext = 0; + GLContextShareSet.contextDestroyed(this); + } + } + + protected void setSwapIntervalImpl(int interval) { + if (nsContext == 0) { + throw new GLException("OpenGL context not current"); + } + impl.setSwapInterval(nsContext, interval); + currentSwapInterval = impl.getSwapInterval() ; + } + + public int getFloatingPointMode() { + return GLPbuffer.APPLE_FLOAT; + } + + protected void create() { + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + if (capabilities.getPbufferFloatingPointBuffers() && + !isTigerOrLater) { + throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later"); + } + // Change our OpenGL mode to match that of any share context before we create ourselves + MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(this); + if (other != null) { + setOpenGLMode(other.getOpenGLMode()); + } + // Will throw exception upon error + nsContext = impl.create(); + + if (!impl.makeCurrent(nsContext)) { + throw new GLException("Error making nsContext current"); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + } + + //--------------------------------------------------------------------------- + // OpenGL "mode switching" functionality + // + private boolean haveSetOpenGLMode = false; + // FIXME: should consider switching the default mode based on + // whether the Java2D/JOGL bridge is active -- need to ask ourselves + // whether it's more likely that we will share with a GLCanvas or a + // GLJPanel when the bridge is turned on + private int openGLMode = MacOSXCGLDrawable.NSOPENGL_MODE; + // Implementation object (either NSOpenGL-based or CGL-based) + protected Impl impl; + + public void setOpenGLMode(int mode) { + if (mode == openGLMode) { + return; + } + if (haveSetOpenGLMode) { + throw new GLException("Can't switch between using NSOpenGLPixelBuffer and CGLPBufferObj more than once"); + } + destroyImpl(); + drawable.setOpenGLMode(mode); + openGLMode = mode; + haveSetOpenGLMode = true; + if (DEBUG) { + System.err.println("Switching PBuffer context mode to " + + ((mode == MacOSXCGLDrawable.NSOPENGL_MODE) ? "NSOPENGL_MODE" : "CGL_MODE")); + } + initOpenGLImpl(); + } + + public int getOpenGLMode() { + return openGLMode; + } + + private void initOpenGLImpl() { + switch (openGLMode) { + case MacOSXCGLDrawable.NSOPENGL_MODE: + impl = new NSOpenGLImpl(); + break; + case MacOSXCGLDrawable.CGL_MODE: + impl = new CGLImpl(); + break; + default: + throw new InternalError("Illegal implementation mode " + openGLMode); + } + } + + // Abstract interface for implementation of this context (either + // NSOpenGL-based or CGL-based) + interface Impl { + public long create(); + public boolean destroy(long ctx); + public boolean makeCurrent(long ctx); + public boolean release(long ctx); + public void setSwapInterval(long ctx, int interval); + public int getSwapInterval(); + } + + // NSOpenGLContext-based implementation + class NSOpenGLImpl implements Impl { + public long create() { + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + if (capabilities.getPbufferFloatingPointBuffers() && + !isTigerOrLater) { + throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later"); + } + if (!MacOSXPbufferCGLContext.this.create(true, capabilities.getPbufferFloatingPointBuffers())) { + throw new GLException("Error creating context for pbuffer"); + } + // Must now associate the pbuffer with our newly-created context + CGL.setContextPBuffer(nsContext, drawable.getPbuffer()); + return nsContext; + } + + public boolean destroy(long ctx) { + return CGL.deleteContext(ctx); + } + + public boolean makeCurrent(long ctx) { + return CGL.makeCurrentContext(ctx); + } + + public boolean release(long ctx) { + return CGL.clearCurrentContext(ctx); + } + + private int currentSwapInterval = 0 ; + + public void setSwapInterval(long ctx, int interval) { + CGL.setSwapInterval(ctx, interval); + currentSwapInterval = interval ; + } + public int getSwapInterval() { + return currentSwapInterval; + } + } + + class CGLImpl implements Impl { + public long create() { + // Find and configure share context + MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(MacOSXPbufferCGLContext.this); + long share = 0; + if (other != null) { + // Reconfigure pbuffer-based GLContexts + if (other instanceof MacOSXPbufferCGLContext) { + MacOSXPbufferCGLContext ctx = (MacOSXPbufferCGLContext) other; + ctx.setOpenGLMode(MacOSXCGLDrawable.CGL_MODE); + } else { + if (other.getOpenGLMode() != MacOSXCGLDrawable.CGL_MODE) { + throw new GLException("Can't share between NSOpenGLContexts and CGLContextObjs"); + } + } + share = other.getNSContext(); + // Note we don't check for a 0 return value, since switching + // the context's mode causes it to be destroyed and not + // re-initialized until the next makeCurrent + } + + // Set up pixel format attributes + // FIXME: shall go into MacOSXCGLGraphicsConfiguration + int[] attrs = new int[256]; + int i = 0; + attrs[i++] = CGL.kCGLPFAPBuffer; + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + if (capabilities.getPbufferFloatingPointBuffers()) + attrs[i++] = CGL.kCGLPFAColorFloat; + if (capabilities.getDoubleBuffered()) + attrs[i++] = CGL.kCGLPFADoubleBuffer; + if (capabilities.getStereo()) + attrs[i++] = CGL.kCGLPFAStereo; + attrs[i++] = CGL.kCGLPFAColorSize; + attrs[i++] = (capabilities.getRedBits() + + capabilities.getGreenBits() + + capabilities.getBlueBits()); + attrs[i++] = CGL.kCGLPFAAlphaSize; + attrs[i++] = capabilities.getAlphaBits(); + attrs[i++] = CGL.kCGLPFADepthSize; + attrs[i++] = capabilities.getDepthBits(); + // FIXME: should validate stencil size as is done in MacOSXWindowSystemInterface.m + attrs[i++] = CGL.kCGLPFAStencilSize; + attrs[i++] = capabilities.getStencilBits(); + attrs[i++] = CGL.kCGLPFAAccumSize; + attrs[i++] = (capabilities.getAccumRedBits() + + capabilities.getAccumGreenBits() + + capabilities.getAccumBlueBits() + + capabilities.getAccumAlphaBits()); + if (capabilities.getSampleBuffers()) { + attrs[i++] = CGL.kCGLPFASampleBuffers; + attrs[i++] = 1; + attrs[i++] = CGL.kCGLPFASamples; + attrs[i++] = capabilities.getNumSamples(); + } + + // Use attribute array to select pixel format + PointerBuffer fmt = PointerBuffer.allocateDirect(1); + long[] numScreens = new long[1]; + int res = CGL.CGLChoosePixelFormat(attrs, 0, fmt, numScreens, 0); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while choosing pixel format"); + } + + // Create new context + PointerBuffer ctx = PointerBuffer.allocateDirect(1); + if (DEBUG) { + System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share)); + } + res = CGL.CGLCreateContext(fmt.get(0), share, ctx); + CGL.CGLDestroyPixelFormat(fmt.get(0)); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while creating context"); + } + // Attach newly-created context to the pbuffer + res = CGL.CGLSetPBuffer(ctx.get(0), drawable.getPbuffer(), 0, 0, 0); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while attaching context to pbuffer"); + } + return ctx.get(0); + } + + public boolean destroy(long ctx) { + return (CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError); + } + + public boolean makeCurrent(long ctx) { + return CGL.CGLSetCurrentContext(ctx) == CGL.kCGLNoError; + } + + public boolean release(long ctx) { + return (CGL.CGLSetCurrentContext(0) == CGL.kCGLNoError); + } + + public void setSwapInterval(long ctx, int interval) { + // For now not supported (not really relevant for off-screen contexts anyway) + } + public int getSwapInterval() { + return 0; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLDrawable.java new file mode 100644 index 000000000..afdc40dbb --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLDrawable.java @@ -0,0 +1,251 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import com.jogamp.common.nio.PointerBuffer; +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { + private static final boolean DEBUG = Debug.debug("MacOSXPbufferCGLDrawable"); + + // State for render-to-texture and render-to-texture-rectangle support + private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV + private int texture; // actual texture object + + // NSOpenGLPbuffer (for normal mode) + // CGLPbufferObj (for CGL_MODE situation, i.e., when Java2D/JOGL bridge is active) + // Note that we can not store this in the NativeWindow because the + // semantic is that contains an NSView + protected long pBuffer; + + public MacOSXPbufferCGLDrawable(GLDrawableFactory factory, NativeWindow target) { + super(factory, target, true); + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + initOpenGLImpl(); + createPbuffer(); + + if (DEBUG) { + System.err.println("Created pbuffer " + this); + } + } + + protected void setRealizedImpl() { + if(realized) { + createPbuffer(); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new MacOSXPbufferCGLContext(this, shareWith); + } + + public void destroy() { + if (this.pBuffer != 0) { + NativeWindow nw = getNativeWindow(); + impl.destroy(pBuffer); + this.pBuffer = 0; + ((SurfaceChangeable)nw).setSurfaceHandle(0); + if (DEBUG) { + System.err.println("Destroyed pbuffer: " + pBuffer); + } + } + } + + public long getPbuffer() { + return pBuffer; + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } + + private void createPbuffer() { + NativeWindow nw = getNativeWindow(); + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + GLProfile glProfile = capabilities.getGLProfile(); + int renderTarget; + if (glProfile.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle()) { + renderTarget = GL2.GL_TEXTURE_RECTANGLE; + } else { + int w = getNextPowerOf2(getWidth()); + int h = getNextPowerOf2(getHeight()); + ((SurfaceChangeable)nw).setSize(w, h); + renderTarget = GL.GL_TEXTURE_2D; + } + + int internalFormat = GL.GL_RGBA; + if (capabilities.getPbufferFloatingPointBuffers()) { + // FIXME: want to check availability of GL_APPLE_float_pixels + // extension, but need valid OpenGL context in order to do so -- + // in worst case would need to create dummy window / GLCanvas + // (undesirable) -- could maybe also do this with pbuffers + /* + if (!gl.isExtensionAvailable("GL_APPLE_float_pixels")) { + throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available"); + } + */ + if(glProfile.isGL2GL3()) { + switch (capabilities.getRedBits()) { + case 16: internalFormat = GL2.GL_RGBA_FLOAT16_APPLE; break; + case 32: internalFormat = GL2.GL_RGBA_FLOAT32_APPLE; break; + default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)"); + } + } else { + internalFormat = GL.GL_RGBA; + } + } + + pBuffer = impl.create(renderTarget, internalFormat, getWidth(), getHeight()); + if (pBuffer == 0) { + throw new GLException("pbuffer creation error: CGL.createPBuffer() failed"); + } + + ((SurfaceChangeable)nw).setSurfaceHandle(pBuffer); + + } + + private int getNextPowerOf2(int number) { + if (((number-1) & number) == 0) { + //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 + return number; + } + int power = 0; + while (number > 0) { + number = number>>1; + power++; + } + return (1<<power); + } + + //--------------------------------------------------------------------------- + // OpenGL "mode switching" functionality + // + private boolean haveSetOpenGLMode = false; + // FIXME: should consider switching the default mode based on + // whether the Java2D/JOGL bridge is active -- need to ask ourselves + // whether it's more likely that we will share with a GLCanvas or a + // GLJPanel when the bridge is turned on + private int openGLMode = NSOPENGL_MODE; + // Implementation object (either NSOpenGL-based or CGL-based) + protected Impl impl; + + public void setOpenGLMode(int mode) { + if (mode == openGLMode) { + return; + } + if (haveSetOpenGLMode) { + throw new GLException("Can't switch between using NSOpenGLPixelBuffer and CGLPBufferObj more than once"); + } + destroy(); + openGLMode = mode; + haveSetOpenGLMode = true; + if (DEBUG) { + System.err.println("Switching PBuffer drawable mode to " + + ((mode == MacOSXCGLDrawable.NSOPENGL_MODE) ? "NSOPENGL_MODE" : "CGL_MODE")); + } + initOpenGLImpl(); + createPbuffer(); + } + + public int getOpenGLMode() { + return openGLMode; + } + + private void initOpenGLImpl() { + switch (openGLMode) { + case NSOPENGL_MODE: + impl = new NSOpenGLImpl(); + break; + case CGL_MODE: + impl = new CGLImpl(); + break; + default: + throw new InternalError("Illegal implementation mode " + openGLMode); + } + } + + // Abstract interface for implementation of this drawable (either + // NSOpenGL-based or CGL-based) + interface Impl { + public long create(int renderTarget, int internalFormat, int width, int height); + public void destroy(long pbuffer); + } + + // NSOpenGLPixelBuffer implementation + class NSOpenGLImpl implements Impl { + public long create(int renderTarget, int internalFormat, int width, int height) { + return CGL.createPBuffer(renderTarget, internalFormat, width, height); + } + + public void destroy(long pbuffer) { + CGL.destroyPBuffer(pbuffer); + } + } + + // CGL implementation + class CGLImpl implements Impl { + public long create(int renderTarget, int internalFormat, int width, int height) { + PointerBuffer pbuffer = PointerBuffer.allocateDirect(1); + int res = CGL.CGLCreatePBuffer(width, height, renderTarget, internalFormat, 0, pbuffer); + if (res != CGL.kCGLNoError) { + throw new GLException("Error creating CGL-based pbuffer: error code " + res); + } + return pbuffer.get(0); + } + + public void destroy(long pbuffer) { + int res = CGL.CGLDestroyPBuffer(pbuffer); + if (res != CGL.kCGLNoError) { + throw new GLException("Error destroying CGL-based pbuffer: error code " + res); + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java new file mode 100644 index 000000000..eff01ca18 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java @@ -0,0 +1,65 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl.awt; + +import java.lang.reflect.InvocationTargetException; +import java.nio.*; +import java.util.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.awt.*; +import com.jogamp.opengl.impl.macosx.cgl.*; + +public class MacOSXAWTCGLDrawableFactory extends MacOSXCGLDrawableFactory { + + public MacOSXAWTCGLDrawableFactory() { + super(); + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + return true; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + return new MacOSXJava2DCGLContext(shareWith); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..0d59da32e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.macosx.cgl.awt; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import javax.media.nativewindow.*; +import javax.media.nativewindow.macosx.*; +import javax.media.nativewindow.awt.*; +import javax.media.opengl.*; +import javax.media.opengl.awt.*; + +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.macosx.cgl.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.macosx.*; + +public class MacOSXAWTCGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public MacOSXAWTCGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GraphicsDevice device = null; + if (absScreen != null && + !(absScreen instanceof AWTGraphicsScreen)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); + } + + if(null==absScreen) { + absScreen = AWTGraphicsScreen.createScreenDevice(-1); + } + AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; + device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilitiesChooser objects"); + } + + if(DEBUG) { + System.err.println("MacOSXAWTCGLGraphicsConfigurationFactory: got "+absScreen); + } + + long displayHandle = 0; + + MacOSXGraphicsDevice macDevice = new MacOSXGraphicsDevice(); + DefaultGraphicsScreen macScreen = new DefaultGraphicsScreen(macDevice, awtScreen.getIndex()); + if(DEBUG) { + System.err.println("MacOSXAWTCGLGraphicsConfigurationFactory: made "+macScreen); + } + + GraphicsConfiguration gc = device.getDefaultConfiguration(); + AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capabilities, gc); + if(DEBUG) { + System.err.println("AWT Colormodel compatible: "+capabilities); + } + + MacOSXCGLGraphicsConfiguration macConfig = (MacOSXCGLGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(macDevice).chooseGraphicsConfiguration(capabilities, + chooser, + macScreen); + + if (macConfig == null) { + throw new GLException("Unable to choose a GraphicsConfiguration: "+capabilities+",\n\t"+chooser+"\n\t"+macScreen); + } + + // FIXME: we have nothing to match .. so choose the default + return new AWTGraphicsConfiguration(awtScreen, macConfig.getChosenCapabilities(), macConfig.getRequestedCapabilities(), gc, macConfig); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXJava2DCGLContext.java new file mode 100644 index 000000000..97a1435bc --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXJava2DCGLContext.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2006 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl.awt; + +import com.jogamp.opengl.impl.macosx.cgl.*; + +import java.awt.Graphics; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.awt.*; +import com.jogamp.opengl.impl.macosx.cgl.*; + +/** MacOSXCGLContext implementation supporting the Java2D/JOGL bridge + * on Mac OS X. The external GLDrawable mechanism does not work on Mac + * OS X due to how drawables and contexts are operated upon on this + * platform, so it is necessary to supply an alternative means to + * create, make current, and destroy contexts on the Java2D "drawable" + * on the Mac platform. + */ + +public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGLContext { + private Graphics graphics; + + // FIXME: ignoring context sharing for the time being; will need to + // rethink this in particular if using FBOs to implement the + // Java2D/OpenGL pipeline on Mac OS X + + public MacOSXJava2DCGLContext(GLContext shareWith) { + super(null, shareWith); + } + + public void setGraphics(Graphics g) { + this.graphics = g; + } + + protected int makeCurrentImpl() throws GLException { + boolean created = false; + if (nsContext == 0) { + create(); + created = 0 != nsContext ; + if(!created) { + return CONTEXT_NOT_CURRENT; + } + if (DEBUG) { + System.err.println("!!! Created GL nsContext for " + getClass().getName()); + } + created = true; + } + + if (!Java2D.makeOGLContextCurrentOnSurface(graphics, nsContext)) { + throw new GLException("Error making context current"); + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void create() { + // Find and configure share context + MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + // Reconfigure pbuffer-based GLContexts + if (other instanceof MacOSXPbufferCGLContext) { + MacOSXPbufferCGLContext ctx = (MacOSXPbufferCGLContext) other; + ctx.setOpenGLMode(MacOSXCGLDrawable.CGL_MODE); + } else { + if (other.getOpenGLMode() != MacOSXCGLDrawable.CGL_MODE) { + throw new GLException("Can't share between NSOpenGLContexts and CGLContextObjs"); + } + } + share = other.getNSContext(); + // Note we don't check for a 0 return value, since switching + // the context's mode causes it to be destroyed and not + // re-initialized until the next makeCurrent + } + + if (DEBUG) { + System.err.println("!!! Share context is " + toHexString(share) + " for " + getClass().getName()); + } + + long ctx = Java2D.createOGLContextOnSurface(graphics, share); + if (ctx == 0) { + return; + } + // FIXME: think about GLContext sharing + nsContext = ctx; + } + + protected void releaseImpl() throws GLException { + // FIXME: would need another primitive in the Java2D class in + // order to implement this; hopefully should not matter for + // correctness + } + + protected void destroyImpl() throws GLException { + if (nsContext != 0) { + Java2D.destroyOGLContext(nsContext); + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL context " + nsContext); + } + nsContext = 0; + // FIXME + // GLContextShareSet.contextDestroyed(this); + } + } + + public void setOpenGLMode(int mode) { + if (mode != MacOSXCGLDrawable.CGL_MODE) + throw new GLException("OpenGL mode switching not supported for Java2D GLContexts"); + } + + public int getOpenGLMode() { + return MacOSXCGLDrawable.CGL_MODE; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java new file mode 100644 index 000000000..87a37da04 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java @@ -0,0 +1,102 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { + private long hwnd, hdc; + + public WindowsDummyWGLDrawable(GLDrawableFactory factory, GLProfile glp) { + super(factory, new NullWindow(WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(glp, null, true, true)), true); + // All entries to CreateDummyWindow must synchronize on one object + // to avoid accidentally registering the dummy window class twice + synchronized (WindowsDummyWGLDrawable.class) { + hwnd = WGL.CreateDummyWindow(0, 0, 1, 1); + } + hdc = WGL.GetDC(hwnd); + NullWindow nw = (NullWindow) getNativeWindow(); + nw.setSurfaceHandle(hdc); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + // Choose a (hopefully hardware-accelerated) OpenGL pixel format for this device context + GLCapabilities caps = (GLCapabilities) config.getChosenCapabilities(); + caps.setDepthBits(16); + PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(caps); + int pixelFormat = WGL.ChoosePixelFormat(hdc, pfd); + if ((pixelFormat == 0) || + (!WGL.SetPixelFormat(hdc, pixelFormat, pfd))) { + destroy(); + } + } + + public void setSize(int width, int height) { + } + + public int getWidth() { + return 1; + } + + public int getHeight() { + return 1; + } + + public GLContext createContext(GLContext shareWith) { + if (hdc == 0) { + // Construction failed + return null; + } + // FIXME: figure out how to hook back in the Java 2D / JOGL bridge + return new WindowsWGLContext(this, shareWith); + } + + public void destroy() { + if (hdc != 0) { + WGL.ReleaseDC(hwnd, hdc); + hdc = 0; + } + if (hwnd != 0) { + WGL.ShowWindow(hwnd, WGL.SW_HIDE); + WGL.DestroyWindow(hwnd); + hwnd = 0; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java new file mode 100755 index 000000000..e712d8568 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java @@ -0,0 +1,146 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsExternalWGLContext extends WindowsWGLContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + private WindowsExternalWGLContext(Drawable drawable, long hglrc, WindowsWGLGraphicsConfiguration cfg) { + super(drawable, null); + this.context = hglrc; + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created external OpenGL context " + toHexString(hglrc) + " for " + this); + } + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + cfg.updateCapabilitiesByWGL(this); + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + protected static WindowsExternalWGLContext create(GLDrawableFactory factory, GLProfile glp) { + long hdc = WGL.wglGetCurrentDC(); + if (0==hdc) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable current"); + } + long hglrc = WGL.wglGetCurrentContext(); + if (hglrc == 0) { + throw new GLException("Error: attempted to make an external GLContext without a context current"); + } + int pfdID = WGL.GetPixelFormat(hdc); + if (pfdID == 0) { + throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat"); + } + + AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(); + WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.create(hdc, pfdID, glp, aScreen, true, true); + + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(hdc); + + return new WindowsExternalWGLContext(new Drawable(factory, nw), hglrc, cfg); + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } + + // Need to provide the display connection to extension querying APIs + static class Drawable extends WindowsWGLDrawable { + Drawable(GLDrawableFactory factory, NativeWindow comp) { + super(factory, comp, true); + } + + public GLContext createContext(GLContext shareWith) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } + + public void setSize(int width, int height) { + throw new GLException("Should not call this"); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java new file mode 100755 index 000000000..74db45932 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java @@ -0,0 +1,90 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { + + private WindowsExternalWGLDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, true); + } + + protected static WindowsExternalWGLDrawable create(GLDrawableFactory factory, GLProfile glp) { + long hdc = WGL.wglGetCurrentDC(); + if (0==hdc) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable current"); + } + int pfdID = WGL.GetPixelFormat(hdc); + if (pfdID == 0) { + throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat"); + } + + AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(); + WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.create(hdc, pfdID, glp, aScreen, true, true); + + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(hdc); + + cfg.updateGraphicsConfiguration(factory, nw); + + return new WindowsExternalWGLDrawable(factory, nw); + } + + + public GLContext createContext(GLContext shareWith) { + return new WindowsWGLContext(this, shareWith); + } + + public void setSize(int newWidth, int newHeight) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLContext.java new file mode 100644 index 000000000..25d93b50e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLContext.java @@ -0,0 +1,64 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsOffscreenWGLContext extends WindowsWGLContext { + public WindowsOffscreenWGLContext(WindowsOffscreenWGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + } + + public int getOffscreenContextPixelDataType() { + return GL.GL_UNSIGNED_BYTE; + } + + public int getOffscreenContextReadBuffer() { + // On Windows these contexts are always single-buffered + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + // We can take care of this in the DIB creation (see below) + return false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java new file mode 100644 index 000000000..bf466d455 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java @@ -0,0 +1,139 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsOffscreenWGLDrawable extends WindowsWGLDrawable { + private long origbitmap; + private long hbitmap; + + public WindowsOffscreenWGLDrawable(GLDrawableFactory factory, NativeWindow target) { + super(factory, target, true); + create(); + } + + protected void setRealizedImpl() { + if(realized) { + create(); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsOffscreenWGLContext(this, shareWith); + } + + private void create() { + NativeWindow nw = getNativeWindow(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getRequestedCapabilities(); + int width = getWidth(); + int height = getHeight(); + BITMAPINFO info = BITMAPINFO.create(); + BITMAPINFOHEADER header = info.getBmiHeader(); + int bitsPerPixel = (capabilities.getRedBits() + + capabilities.getGreenBits() + + capabilities.getBlueBits() + + capabilities.getAlphaBits()); + header.setBiSize(header.size()); + header.setBiWidth(width); + // NOTE: negating the height causes the DIB to be in top-down row + // order rather than bottom-up; ends up being correct during pixel + // readback + header.setBiHeight(-1 * height); + header.setBiPlanes((short) 1); + header.setBiBitCount((short) bitsPerPixel); + header.setBiXPelsPerMeter(0); + header.setBiYPelsPerMeter(0); + header.setBiClrUsed(0); + header.setBiClrImportant(0); + header.setBiCompression(WGL.BI_RGB); + header.setBiSizeImage(width * height * bitsPerPixel / 8); + + long hdc = WGL.CreateCompatibleDC(0); + if (hdc == 0) { + System.out.println("LastError: " + WGL.GetLastError()); + throw new GLException("Error creating device context for offscreen OpenGL context"); + } + ((SurfaceChangeable)nw).setSurfaceHandle(hdc); + + hbitmap = WGL.CreateDIBSection(hdc, info, WGL.DIB_RGB_COLORS, null, 0, 0); + if (hbitmap == 0) { + WGL.DeleteDC(hdc); + hdc = 0; + throw new GLException("Error creating offscreen bitmap of width " + width + + ", height " + height); + } + if ((origbitmap = WGL.SelectObject(hdc, hbitmap)) == 0) { + WGL.DeleteObject(hbitmap); + hbitmap = 0; + WGL.DeleteDC(hdc); + hdc = 0; + throw new GLException("Error selecting bitmap into new device context"); + } + + config.updateGraphicsConfiguration(getFactory(), nw); + } + + public void destroy() { + NativeWindow nw = getNativeWindow(); + if (nw.getSurfaceHandle() != 0) { + // Must destroy bitmap and device context + WGL.SelectObject(nw.getSurfaceHandle(), origbitmap); + WGL.DeleteObject(hbitmap); + WGL.DeleteDC(nw.getSurfaceHandle()); + origbitmap = 0; + hbitmap = 0; + ((SurfaceChangeable)nw).setSurfaceHandle(0); + } + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java new file mode 100644 index 000000000..aeb13110e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java @@ -0,0 +1,88 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsOnscreenWGLContext extends WindowsWGLContext { + protected WindowsOnscreenWGLDrawable drawable; + + public WindowsOnscreenWGLContext(WindowsOnscreenWGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + int ret = super.makeCurrentImpl(); + return ret; + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY) && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected void releaseImpl() throws GLException { + try { + super.releaseImpl(); + } finally { + if (!isOptimizable() && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java new file mode 100644 index 000000000..401b8c3c6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java @@ -0,0 +1,63 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable { + protected WindowsOnscreenWGLDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, false); + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsOnscreenWGLContext(this, shareWith); + } + + public int getWidth() { + return component.getWidth(); + } + + public int getHeight() { + return component.getHeight(); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java new file mode 100644 index 000000000..a9e02e11f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java @@ -0,0 +1,155 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsPbufferWGLContext extends WindowsWGLContext { + private static final boolean DEBUG = Debug.debug("WindowsPbufferWGLContext"); + + // State for render-to-texture and render-to-texture-rectangle support + private WindowsPbufferWGLDrawable drawable; + private boolean rtt; // render-to-texture? + private boolean hasRTT; // render-to-texture extension available? + private boolean rect; // render-to-texture-rectangle? + private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV + private int texture; // actual texture object + + public WindowsPbufferWGLContext(WindowsPbufferWGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + public void bindPbufferToTexture() { + if (!rtt) { + throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " + + "specified in its GLCapabilities"); + } + GL gl = getGL(); + WGLExt wglExt = getWGLExt(); + gl.glBindTexture(textureTarget, texture); + if (rtt && hasRTT) { + if (!wglExt.wglBindTexImageARB(drawable.getPbuffer(), WGLExt.WGL_FRONT_LEFT_ARB)) { + throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError()); + } + } + // FIXME: comment is wrong now + // Note that if the render-to-texture extension is not supported, + // we perform a glCopyTexImage2D in swapBuffers(). + } + + public void releasePbufferFromTexture() { + if (!rtt) { + throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " + + "specified in its GLCapabilities"); + } + if (rtt && hasRTT) { + WGLExt wglExt = getWGLExt(); + if (!wglExt.wglReleaseTexImageARB(drawable.getPbuffer(), WGLExt.WGL_FRONT_LEFT_ARB)) { + throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError()); + } + } + } + + protected int makeCurrentImpl() throws GLException { + int res = super.makeCurrentImpl(); + if (DEBUG && VERBOSE) { + System.err.println("WindowsPbufferWGLContext: super.makeCurrentImpl() = " + res); + } + if (res == CONTEXT_CURRENT_NEW) { + GLCapabilities capabilities = drawable.getChosenGLCapabilities(); + + // Initialize render-to-texture support if requested + GL gl = getGL(); + rtt = capabilities.getPbufferRenderToTexture(); + rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle(); + + if (rtt) { + if (DEBUG) { + System.err.println("Initializing render-to-texture support"); + } + + if (!gl.isExtensionAvailable("WGL_ARB_render_texture")) { + System.err.println("WindowsPbufferWGLContext: WARNING: WGL_ARB_render_texture extension not " + + "supported; implementing render_to_texture support using slow texture readback"); + } else { + hasRTT = true; + + if (rect && !gl.isExtensionAvailable("GL_NV_texture_rectangle")) { + System.err.println("WindowsPbufferWGLContext: WARNING: GL_NV_texture_rectangle extension not " + + "supported; skipping requested render_to_texture_rectangle support for pbuffer"); + rect = false; + } + if (rect) { + if (DEBUG) { + System.err.println(" Using render-to-texture-rectangle"); + } + textureTarget = GL2.GL_TEXTURE_RECTANGLE_ARB; + } else { + if (DEBUG) { + System.err.println(" Using vanilla render-to-texture"); + } + textureTarget = GL.GL_TEXTURE_2D; + } + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp, 0); + texture = tmp[0]; + gl.glBindTexture(textureTarget, texture); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); + gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0); + } + } + } + return res; + } + + public int getFloatingPointMode() { + return drawable.getFloatingPointMode(); + } + + private static String wglGetLastError() { + return WindowsWGLDrawableFactory.wglGetLastError(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java new file mode 100644 index 000000000..c7034e93b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -0,0 +1,330 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; + +public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { + private long cachedParentHdc; + private WGLExt cachedWGLExt; // cached WGLExt instance from parent GLCanvas, + // needed to destroy pbuffer + private long buffer; // pbuffer handle + + private int floatMode; + + public WindowsPbufferWGLDrawable(GLDrawableFactory factory, NativeWindow target, + WindowsWGLDrawable dummyDrawable, + WGLExt wglExt) { + super(factory, target, true); + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + createPbuffer(dummyDrawable.getNativeWindow().getSurfaceHandle(), wglExt); + + if (DEBUG) { + System.err.println("Created pbuffer " + this); + } + } + + protected void setRealizedImpl() { + if(realized) { + throw new GLException("Recreation via setRealized not supported."); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsPbufferWGLContext(this, shareWith); + } + + public void destroy() { + NativeWindow nw = getNativeWindow(); + if(0!=buffer) { + WGLExt wglExt = cachedWGLExt; + if (nw.getSurfaceHandle() != 0) { + // Must release DC and pbuffer + // NOTE that since the context is not current, glGetError() can + // not be called here, so we skip the use of any composable + // pipelines (see WindowsOnscreenWGLContext.makeCurrentImpl) + if (wglExt.wglReleasePbufferDCARB(buffer, nw.getSurfaceHandle()) == 0) { + throw new GLException("Error releasing pbuffer device context: error code " + WGL.GetLastError()); + } + ((SurfaceChangeable)nw).setSurfaceHandle(0); + } + if (!wglExt.wglDestroyPbufferARB(buffer)) { + throw new GLException("Error destroying pbuffer: error code " + WGL.GetLastError()); + } + buffer = 0; + } + } + + public long getPbuffer() { + return buffer; + } + + public int getFloatingPointMode() { + return floatMode; + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } + + private void createPbuffer(long parentHdc, WGLExt wglExt) { + int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; + float[] fattributes = new float[1]; + int[] floatModeTmp = new int[1]; + int niattribs = 0; + int width, height; + + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getRequestedCapabilities(); + GLProfile glProfile = capabilities.getGLProfile(); + + if (DEBUG) { + System.out.println("Pbuffer parentHdc = " + toHexString(parentHdc)); + System.out.println("Pbuffer caps: " + capabilities); + } + + if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, + iattributes, + wglExt, + true, + floatModeTmp)){ + throw new GLException("Pbuffer-related extensions not supported"); + } + + floatMode = floatModeTmp[0]; + boolean rtt = capabilities.getPbufferRenderToTexture(); + boolean rect = capabilities.getPbufferRenderToTextureRectangle(); + boolean useFloat = capabilities.getPbufferFloatingPointBuffers(); + boolean ati = false; + + if (useFloat) { + ati = (floatMode == GLPbuffer.ATI_FLOAT); + } + + int[] pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; + int nformats; + int[] nformatsTmp = new int[1]; + if (!wglExt.wglChoosePixelFormatARB(parentHdc, + iattributes, 0, + fattributes, 0, + WindowsWGLGraphicsConfiguration.MAX_PFORMATS, + pformats, 0, + nformatsTmp, 0)) { + throw new GLException("pbuffer creation error: wglChoosePixelFormat() failed"); + } + nformats = nformatsTmp[0]; + if (nformats <= 0) { + throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format"); + } + + boolean haveMultisample = wglExt.isExtensionAvailable("WGL_ARB_multisample"); + + if (DEBUG) { + System.err.println("" + nformats + " suitable pixel formats found"); + // query pixel format + iattributes[0] = WGLExt.WGL_RED_BITS_ARB; + iattributes[1] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[2] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[3] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[4] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[5] = (useFloat ? (ati ? WGLExt.WGL_PIXEL_TYPE_ARB : WGLExt.WGL_FLOAT_COMPONENTS_NV) : WGLExt.WGL_RED_BITS_ARB); + iattributes[6] = (haveMultisample ? WGLExt.WGL_SAMPLE_BUFFERS_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[7] = (haveMultisample ? WGLExt.WGL_SAMPLES_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[8] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + int[] ivalues = new int[9]; + for (int i = 0; i < nformats; i++) { + if (!wglExt.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 9, iattributes, 0, ivalues, 0)) { + throw new GLException("Error while querying pixel format " + pformats[i] + + "'s (index " + i + "'s) capabilities for debugging"); + } + System.err.print("pixel format " + pformats[i] + " (index " + i + "): "); + System.err.print( "r: " + ivalues[0]); + System.err.print(" g: " + ivalues[1]); + System.err.print(" b: " + ivalues[2]); + System.err.print(" a: " + ivalues[3]); + System.err.print(" depth: " + ivalues[4]); + if (haveMultisample) { + System.err.print(" multisample: " + ivalues[6]); + } + System.err.print(" samples: " + ivalues[7]); + if (useFloat) { + if (ati) { + if (ivalues[5] == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) { + System.err.print(" [ati float]"); + } else if (ivalues[5] != WGLExt.WGL_TYPE_RGBA_ARB) { + System.err.print(" [unknown pixel type " + ivalues[5] + "]"); + } + } else { + if (ivalues[5] != 0) { + System.err.print(" [float]"); + } + } + } + + if (ivalues[8] != 0) { + System.err.print(" [pbuffer]"); + } + System.err.println(); + } + } + + long tmpBuffer = 0; + int whichFormat = -1; + // Loop is a workaround for bugs in NVidia's recent drivers + for (whichFormat = 0; whichFormat < nformats; whichFormat++) { + int format = pformats[whichFormat]; + + // Create the p-buffer. + niattribs = 0; + + if (rtt) { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FORMAT_ARB; + if (useFloat) { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FLOAT_RGB_NV; + } else { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_RGBA_ARB; + } + + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_TARGET_ARB; + iattributes[niattribs++] = rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB; + + iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB; + iattributes[niattribs++] = GL.GL_FALSE; + + iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = 0; + + tmpBuffer = wglExt.wglCreatePbufferARB(parentHdc, format, getWidth(), getHeight(), iattributes, 0); + if (tmpBuffer != 0) { + // Done + break; + } + } + + if (tmpBuffer == 0) { + throw new GLException("pbuffer creation error: wglCreatePbuffer() failed: tried " + nformats + + " pixel formats, last error was: " + wglGetLastError()); + } + + // Get the device context. + long tmpHdc = wglExt.wglGetPbufferDCARB(tmpBuffer); + if (tmpHdc == 0) { + throw new GLException("pbuffer creation error: wglGetPbufferDC() failed"); + } + + NativeWindow nw = getNativeWindow(); + // Set up instance variables + buffer = tmpBuffer; + ((SurfaceChangeable)nw).setSurfaceHandle(tmpHdc); + cachedWGLExt = wglExt; + cachedParentHdc = parentHdc; + + // Re-query chosen pixel format + { + niattribs = 0; + iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; + iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; + iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; + iattributes[niattribs++] = (useFloat ? (ati ? WGLExt.WGL_PIXEL_TYPE_ARB : WGLExt.WGL_FLOAT_COMPONENTS_NV) : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = (haveMultisample ? WGLExt.WGL_SAMPLE_BUFFERS_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = (haveMultisample ? WGLExt.WGL_SAMPLES_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + int[] ivalues = new int[niattribs]; + if (wglExt.wglGetPixelFormatAttribivARB(parentHdc, pformats[whichFormat], 0, niattribs, iattributes, 0, ivalues, 0)) { + GLCapabilities newCaps = WindowsWGLGraphicsConfiguration.AttribList2GLCapabilities(glProfile, iattributes, niattribs, ivalues, true, false, true); + PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); + if (WGL.DescribePixelFormat(parentHdc, pformats[whichFormat], pfd.size(), pfd) == 0) { + if (DEBUG) { + System.err.println("Unable to describe pixel format (Continue: true) " + whichFormat + "/" + nformats + " pfdID " + pformats[whichFormat]+":\n\t"+newCaps); + } + } + if(newCaps.isOnscreen()) { + throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps+"\n\t"+newCaps); + } + config.setCapsPFD(newCaps, pfd, pformats[whichFormat], true); + } else { + PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); + if (WGL.DescribePixelFormat(parentHdc, pformats[whichFormat], pfd.size(), pfd) == 0) { + throw new GLException("Unable to describe pixel format " + pformats[whichFormat]); + } + GLCapabilities newCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, pfd, false, true); + if(newCaps.isOnscreen()) { + throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps+"\n\t"+newCaps); + } + config.setCapsPFD(newCaps, pfd, pformats[whichFormat], false); + } + } + + // Determine the actual width and height we were able to create. + int[] tmp = new int[1]; + wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB, tmp, 0 ); + width = tmp[0]; + wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 ); + height = tmp[0]; + ((SurfaceChangeable)nw).setSize(width, height); + } + + private static String wglGetLastError() { + return WindowsWGLDrawableFactory.wglGetLastError(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java new file mode 100644 index 000000000..0f1f9813f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java @@ -0,0 +1,445 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; + +public class WindowsWGLContext extends GLContextImpl { + protected long hglrc; + private boolean wglGetExtensionsStringEXTInitialized; + private boolean wglGetExtensionsStringEXTAvailable; + private boolean wglMakeContextCurrentInitialized; + private boolean wglMakeContextCurrentARBAvailable; + private boolean wglMakeContextCurrentEXTAvailable; + private static final Map/*<String, String>*/ functionNameMap; + private static final Map/*<String, String>*/ extensionNameMap; + private WGLExt wglExt; + // Table that holds the addresses of the native C-language entry points for + // WGL extension functions. + private WGLExtProcAddressTable wglExtProcAddressTable; + + static { + functionNameMap = new HashMap(); + functionNameMap.put("glAllocateMemoryNV", "wglAllocateMemoryNV"); + functionNameMap.put("glFreeMemoryNV", "wglFreeMemoryNV"); + + extensionNameMap = new HashMap(); + extensionNameMap.put("GL_ARB_pbuffer", "WGL_ARB_pbuffer"); + extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format"); + } + + // FIXME: figure out how to hook back in the Java 2D / JOGL bridge + public WindowsWGLContext(GLDrawableImpl drawable, GLDrawableImpl drawableRead, + GLContext shareWith) { + super(drawable, drawableRead, shareWith); + } + + public WindowsWGLContext(GLDrawableImpl drawable, + GLContext shareWith) { + this(drawable, null, shareWith); + } + + public Object getPlatformGLExtensions() { + return getWGLExt(); + } + + public WGLExt getWGLExt() { + if (wglExt == null) { + wglExt = new WGLExtImpl(this); + } + return wglExt; + } + + public boolean wglMakeContextCurrent(long hDrawDC, long hReadDC, long hglrc) { + WGLExt wglExt = getWGLExt(); + if (!wglMakeContextCurrentInitialized) { + wglMakeContextCurrentARBAvailable = isFunctionAvailable("wglMakeContextCurrentARB"); + wglMakeContextCurrentEXTAvailable = isFunctionAvailable("wglMakeContextCurrentEXT"); + wglMakeContextCurrentInitialized = true; + if(DEBUG) { + System.err.println("WindowsWGLContext.wglMakeContextCurrent: ARB "+wglMakeContextCurrentARBAvailable+", EXT "+wglMakeContextCurrentEXTAvailable); + } + } + if(wglMakeContextCurrentARBAvailable) { + return wglExt.wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc); + } else if(wglMakeContextCurrentEXTAvailable) { + return wglExt.wglMakeContextCurrentEXT(hDrawDC, hReadDC, hglrc); + } + return WGL.wglMakeCurrent(hDrawDC, hglrc); + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return getWGLExtProcAddressTable(); + } + + public final WGLExtProcAddressTable getWGLExtProcAddressTable() { + return wglExtProcAddressTable; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return functionNameMap; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return extensionNameMap; } + + protected void destroyContextARBImpl(long context) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(context); + } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); + WGLExt wglExt; + if(null==factory.getSharedContext()) { + wglExt = getWGLExt(); + } else { + wglExt = ((WindowsWGLContext)factory.getSharedContext()).getWGLExt(); + } + + boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; + boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; + boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; + + long _context=0; + + int attribs[] = { + /* 0 */ WGLExt.WGL_CONTEXT_MAJOR_VERSION_ARB, major, + /* 2 */ WGLExt.WGL_CONTEXT_MINOR_VERSION_ARB, minor, + /* 4 */ WGLExt.WGL_CONTEXT_LAYER_PLANE_ARB, WGLExt.WGL_CONTEXT_LAYER_PLANE_ARB, // default + /* 6 */ WGLExt.WGL_CONTEXT_FLAGS_ARB, 0, + /* 8 */ 0, 0, + /* 10 */ 0 + }; + + if ( major > 3 || major == 3 && minor >= 2 ) { + // FIXME: Verify with a None drawable binding (default framebuffer) + attribs[8+0] = WGLExt.WGL_CONTEXT_PROFILE_MASK_ARB; + if( ctBwdCompat ) { + attribs[8+1] = WGLExt.WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + } else { + attribs[8+1] = WGLExt.WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + } + } + + if ( major >= 3 ) { + if( !ctBwdCompat && ctFwdCompat ) { + attribs[6+1] |= WGLExt.WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + } + if( ctDebug) { + attribs[6+1] |= WGLExt.WGL_CONTEXT_DEBUG_BIT_ARB; + } + } + + _context = wglExt.wglCreateContextAttribsARB(drawable.getNativeWindow().getSurfaceHandle(), share, attribs, 0); + if(0==_context) { + if(DEBUG) { + System.err.println("WindowsWGLContext.createContextARB couldn't create "+getGLVersion(null, major, minor, ctp, "@creation")); + } + } else { + // In contrast to GLX no verification with a drawable binding, ie default framebuffer, is necessary, + // if no 3.2 is available creation fails already! + // Nevertheless .. we do it .. + if (!WGL.wglMakeCurrent(drawable.getNativeWindow().getSurfaceHandle(), _context)) { + if(DEBUG) { + System.err.println("WindowsWGLContext.createContextARB couldn't make current "+getGLVersion(null, major, minor, ctp, "@creation")); + } + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(_context); + _context = 0; + } + } + return _context; + } + + /** + * Creates and initializes an appropriate OpenGL context. Should only be + * called by {@link #makeCurrentImpl()}. + */ + protected void create() { + if(0!=context) { + throw new GLException("context is not null: "+context); + } + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); + GLCapabilities glCaps = drawable.getChosenGLCapabilities(); + + if (drawable.getNativeWindow().getSurfaceHandle() == 0) { + throw new GLException("Internal error: attempted to create OpenGL context without an associated drawable"); + } + // Windows can set up sharing of display lists after creation time + WindowsWGLContext other = (WindowsWGLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getHGLRC(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + + int minor[] = new int[1]; + int major[] = new int[1]; + int ctp[] = new int[1]; + boolean createContextARBTried = false; + + // utilize the shared context's GLXExt in case it was using the ARB method and it already exists + if(null!=factory.getSharedContext() && factory.getSharedContext().isCreatedWithARBMethod()) { + if(DEBUG) { + System.err.println("WindowsWGLContext.createContext using shared Context: "+factory.getSharedContext()); + } + hglrc = createContextARB(share, true, major, minor, ctp); + createContextARBTried = true; + } + + long temp_hglrc = 0; + if(0==hglrc) { + // To use WGL_ARB_create_context, we have to make a temp context current, + // so we are able to use GetProcAddress + temp_hglrc = WGL.wglCreateContext(drawable.getNativeWindow().getSurfaceHandle()); + if (temp_hglrc == 0) { + throw new GLException("Unable to create temp OpenGL context for device context " + toHexString(drawable.getNativeWindow().getSurfaceHandle())); + } + if (!WGL.wglMakeCurrent(drawable.getNativeWindow().getSurfaceHandle(), temp_hglrc)) { + throw new GLException("Error making temp context current: 0x" + Integer.toHexString(WGL.GetLastError())); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + + if( createContextARBTried || + !isFunctionAvailable("wglCreateContextAttribsARB") || + !isExtensionAvailable("WGL_ARB_create_context") ) { + if(glCaps.getGLProfile().isGL3()) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(temp_hglrc); + throw new GLException("Unable to create OpenGL >= 3.1 context (no WGL_ARB_create_context)"); + } + + // continue with temp context for GL < 3.0 + hglrc = temp_hglrc; + return; + } + hglrc = createContextARB(share, true, major, minor, ctp); + createContextARBTried=true; + } + + if(0!=hglrc) { + share = 0; // mark as shared .. + + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(temp_hglrc); + + if (!wglMakeContextCurrent(drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), hglrc)) { + throw new GLException("Cannot make previous verified context current: 0x" + Integer.toHexString(WGL.GetLastError())); + } + } else { + if(glCaps.getGLProfile().isGL3()) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(temp_hglrc); + throw new GLException("WindowsWGLContext.createContext failed, but context > GL2 requested "+getGLVersion(null, major[0], minor[0], ctp[0], "@creation")+", "); + } + if(DEBUG) { + System.err.println("WindowsWGLContext.createContext failed, fall back to !ARB context "+getGLVersion(null, major[0], minor[0], ctp[0], "@creation")); + } + + // continue with temp context for GL < 3.0 + hglrc = temp_hglrc; + if (!wglMakeContextCurrent(drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), hglrc)) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(hglrc); + throw new GLException("Error making old context current: 0x" + Integer.toHexString(WGL.GetLastError())); + } + } + + if(0!=share) { + if (!WGL.wglShareLists(share, hglrc)) { + throw new GLException("wglShareLists(" + toHexString(share) + + ", " + toHexString(hglrc) + ") failed: error code 0x" + + Integer.toHexString(WGL.GetLastError())); + } + } + GLContextShareSet.contextCreated(this); + } + + protected int makeCurrentImpl() throws GLException { + if (drawable.getNativeWindow().getSurfaceHandle() == 0) { + throw new GLException("drawable not properly initialized: "+drawable); + } + boolean created = false; + if (hglrc == 0) { + create(); + created = true; + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName()); + } + } + + if (WGL.wglGetCurrentContext() != hglrc) { + if (!wglMakeContextCurrent(drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), hglrc)) { + throw new GLException("Error making context current: 0x" + Integer.toHexString(WGL.GetLastError()) + ", " + this); + } else { + if (DEBUG && VERBOSE) { + System.err.println(getThreadName() + ": wglMakeCurrent(hdc " + toHexString(drawable.getNativeWindow().getSurfaceHandle()) + + ", hglrc " + toHexString(hglrc) + ") succeeded"); + } + } + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + + WindowsWGLGraphicsConfiguration config = + (WindowsWGLGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateCapabilitiesByWGL(this); + + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + if (!wglMakeContextCurrent(0, 0, 0)) { + throw new GLException("Error freeing OpenGL context: 0x" + Integer.toHexString(WGL.GetLastError())); + } + } + + protected void destroyImpl() throws GLException { + if (DEBUG) { + Exception e = new Exception(getThreadName() + ": !!! Destroyed OpenGL context " + toHexString(hglrc)); + e.printStackTrace(); + } + if (hglrc != 0) { + if (!WGL.wglDeleteContext(hglrc)) { + throw new GLException("Unable to delete OpenGL context"); + } + hglrc = 0; + GLContextShareSet.contextDestroyed(this); + } + } + + public boolean isCreated() { + return (hglrc != 0); + } + + public void copy(GLContext source, int mask) throws GLException { + long dst = getHGLRC(); + long src = ((WindowsWGLContext) source).getHGLRC(); + if (src == 0) { + throw new GLException("Source OpenGL context has not been created"); + } + if (dst == 0) { + throw new GLException("Destination OpenGL context has not been created"); + } + if (!WGL.wglCopyContext(src, dst, mask)) { + throw new GLException("wglCopyContext failed"); + } + } + + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing WGL extension address table for " + this); + } + wglGetExtensionsStringEXTInitialized=false; + wglGetExtensionsStringEXTAvailable=false; + wglMakeContextCurrentInitialized=false; + wglMakeContextCurrentARBAvailable=false; + wglMakeContextCurrentEXTAvailable=false; + + if (wglExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + wglExtProcAddressTable = new WGLExtProcAddressTable(); + } + resetProcAddressTable(getWGLExtProcAddressTable()); + super.updateGLProcAddressTable(major, minor, ctp); + } + + public String getPlatformExtensionsString() { + if (!wglGetExtensionsStringEXTInitialized) { + wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0); + wglGetExtensionsStringEXTInitialized = true; + } + if (wglGetExtensionsStringEXTAvailable) { + return getWGLExt().wglGetExtensionsStringEXT(); + } else { + return ""; + } + } + + protected void setSwapIntervalImpl(int interval) { + WGLExt wglExt = getWGLExt(); + if (wglExt.isExtensionAvailable("WGL_EXT_swap_control")) { + if ( wglExt.wglSwapIntervalEXT(interval) ) { + currentSwapInterval = interval ; + } + } + } + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + public long getHGLRC() { + return hglrc; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java new file mode 100644 index 000000000..43c1ff5e0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java @@ -0,0 +1,129 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import com.jogamp.common.os.DynamicLookupHelper; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public abstract class WindowsWGLDrawable extends GLDrawableImpl { + private static final int MAX_SET_PIXEL_FORMAT_FAIL_COUNT = 5; + private static final boolean PROFILING = Debug.debug("WindowsWGLDrawable.profiling"); + private static final int PROFILING_TICKS = 200; + private int profilingLockSurfaceTicks; + private long profilingLockSurfaceTime; + private int profilingUnlockSurfaceTicks; + private long profilingUnlockSurfaceTime; + private int profilingSwapBuffersTicks; + private long profilingSwapBuffersTime; + + + public WindowsWGLDrawable(GLDrawableFactory factory, NativeWindow comp, boolean realized) { + super(factory, comp, realized); + } + + protected void setRealizedImpl() { + if(!realized) { + return; // nothing todo .. + } + + if(NativeWindow.LOCK_SURFACE_NOT_READY == lockSurface()) { + throw new GLException("WindowsWGLDrawable.setRealized(true): lockSurface - surface not ready"); + } + try { + NativeWindow nativeWindow = getNativeWindow(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)nativeWindow.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateGraphicsConfiguration(getFactory(), nativeWindow); + if (DEBUG) { + System.err.println("!!! WindowsWGLDrawable.setRealized(true): "+config); + } + } finally { + unlockSurface(); + } + } + + protected void swapBuffersImpl() { + boolean didLock = false; + + if ( !isSurfaceLocked() ) { + // Usually the surface shall be locked within [makeCurrent .. swap .. release] + if (lockSurface() == NativeWindow.LOCK_SURFACE_NOT_READY) { + return; + } + didLock = true; + } + try { + + long startTime = 0; + if (PROFILING) { + startTime = System.currentTimeMillis(); + } + + if (!WGL.SwapBuffers(getNativeWindow().getSurfaceHandle()) && (WGL.GetLastError() != 0)) { + throw new GLException("Error swapping buffers"); + } + + if (PROFILING) { + long endTime = System.currentTimeMillis(); + profilingSwapBuffersTime += (endTime - startTime); + int ticks = PROFILING_TICKS; + if (++profilingSwapBuffersTicks == ticks) { + System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + ticks + " calls (" + + ((float) profilingSwapBuffersTime / (float) ticks) + " ms/call)"); + profilingSwapBuffersTime = 0; + profilingSwapBuffersTicks = 0; + } + } + } finally { + if (didLock) { + unlockSurface(); + } + } + } + + public DynamicLookupHelper getDynamicLookupHelper() { + return (WindowsWGLDrawableFactory) getFactoryImpl() ; + } + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java new file mode 100644 index 000000000..a4bf89b81 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java @@ -0,0 +1,311 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import com.jogamp.common.os.DynamicLookupHelper; +import java.nio.*; +import java.util.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.windows.*; +import javax.media.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { + private static final boolean VERBOSE = Debug.verbose(); + + // Handle to GLU32.dll + // FIXME: this should go away once we delete support for the C GLU library + private long hglu32; + + // Handle to core OpenGL32.dll + private long hopengl32; + + public WindowsWGLDrawableFactory() { + super(); + + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new WindowsWGLGraphicsConfigurationFactory(); + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory", + new Object[] {}); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + + loadOpenGL32Library(); + + sharedDrawable = new WindowsDummyWGLDrawable(this, null); + WindowsWGLContext ctx = (WindowsWGLContext) sharedDrawable.createContext(null); + ctx.makeCurrent(); + canCreateGLPbuffer = ctx.getGL().isExtensionAvailable("GL_ARB_pbuffer"); + ctx.release(); + sharedContext = ctx; + if(null==sharedContext) { + throw new GLException("Couldn't init shared resources"); + } + if (DEBUG) { + System.err.println("!!! SharedContext: "+sharedContext+", pbuffer supported "+canCreateGLPbuffer); + } + } + + WindowsDummyWGLDrawable sharedDrawable=null; + WindowsWGLContext sharedContext=null; + boolean canCreateGLPbuffer = false; + + protected final GLDrawableImpl getSharedDrawable() { + validate(); + return sharedDrawable; + } + + protected final GLContextImpl getSharedContext() { + validate(); + return sharedContext; + } + + public void shutdown() { + super.shutdown(); + if (DEBUG) { + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! CTX : "+sharedContext); + System.err.println("!!! Drawable: "+sharedDrawable); + Exception e = new Exception("Debug"); + e.printStackTrace(); + } + if(null!=sharedContext) { + sharedContext.destroy(); // implies release, if current + } + if(null!=sharedDrawable) { + sharedDrawable.destroy(); + } + } + + public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new WindowsOnscreenWGLDrawable(this, target); + } + + protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new WindowsOffscreenWGLDrawable(this, target); + } + + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + validate(); + return canCreateGLPbuffer; + } + + protected GLDrawableImpl createGLPbufferDrawableImpl(final NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + final List returnList = new ArrayList(); + final GLDrawableFactory factory = this; + final WindowsWGLContext _sharedContext = sharedContext; + final WindowsDummyWGLDrawable _sharedDrawable = sharedDrawable; + Runnable r = new Runnable() { + public void run() { + GLContext lastContext = GLContext.getCurrent(); + if (lastContext != null) { + lastContext.release(); + } + _sharedContext.makeCurrent(); + WGLExt wglExt = _sharedContext.getWGLExt(); + try { + GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(factory, target, + _sharedDrawable, + wglExt); + returnList.add(pbufferDrawable); + } finally { + _sharedContext.release(); + if (lastContext != null) { + lastContext.makeCurrent(); + } + } + } + }; + maybeDoSingleThreadedWorkaround(r); + return (GLDrawableImpl) returnList.get(0); + } + + protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { + validate(); + AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(); + NullWindow nw = new NullWindow(WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capabilities, chooser, screen) ); + nw.setSize(width, height); + return nw; + } + + public GLContext createExternalGLContext() { + validate(); + return WindowsExternalWGLContext.create(this, null); + } + + public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + validate(); + return true; + } + + public GLDrawable createExternalGLDrawable() { + validate(); + return WindowsExternalWGLDrawable.create(this, null); + } + + public void loadOpenGL32Library() { + validate(); + if (hopengl32 == 0) { + hopengl32 = WGL.LoadLibraryA("OpenGL32"); + if (DEBUG) { + if (hopengl32 == 0) { + System.err.println("WindowsWGLDrawableFactory: Could not load OpenGL32.dll - maybe an embedded device"); + } + } + } + } + + public void loadGLULibrary() { + validate(); + if (hglu32 == 0) { + hglu32 = WGL.LoadLibraryA("GLU32"); + if (hglu32 == 0) { + throw new GLException("Error loading GLU32.DLL"); + } + } + } + + public long dynamicLookupFunction(String glFuncName) { + validate(); + long res = WGL.wglGetProcAddress(glFuncName); + if (res == 0) { + // It may happen that a driver doesn't return the OpenGL32 core function pointer + // with wglGetProcAddress (e.g. NVidia GL 3.1) - hence we have to look harder. + if (hopengl32 != 0) { + res = WGL.GetProcAddress(hopengl32, glFuncName); + } + } + if (res == 0) { + // GLU routines aren't known to the OpenGL function lookup + if (hglu32 != 0) { + res = WGL.GetProcAddress(hglu32, glFuncName); + } + } + return res; + } + + static String wglGetLastError() { + long err = WGL.GetLastError(); + String detail = null; + switch ((int) err) { + case WGL.ERROR_INVALID_PIXEL_FORMAT: detail = "ERROR_INVALID_PIXEL_FORMAT"; break; + case WGL.ERROR_NO_SYSTEM_RESOURCES: detail = "ERROR_NO_SYSTEM_RESOURCES"; break; + case WGL.ERROR_INVALID_DATA: detail = "ERROR_INVALID_DATA"; break; + case WGL.ERROR_PROC_NOT_FOUND: detail = "ERROR_PROC_NOT_FOUND"; break; + case WGL.ERROR_INVALID_WINDOW_HANDLE:detail = "ERROR_INVALID_WINDOW_HANDLE"; break; + default: detail = "(Unknown error code " + err + ")"; break; + } + return detail; + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + validate(); + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + validate(); + throw new GLException("Unimplemented on this platform"); + } + + //------------------------------------------------------ + // Gamma-related functionality + // + + private static final int GAMMA_RAMP_LENGTH = 256; + + protected int getGammaRampLength() { + return GAMMA_RAMP_LENGTH; + } + + protected boolean setGammaRamp(float[] ramp) { + short[] rampData = new short[3 * GAMMA_RAMP_LENGTH]; + for (int i = 0; i < GAMMA_RAMP_LENGTH; i++) { + short scaledValue = (short) (ramp[i] * 65535); + rampData[i] = scaledValue; + rampData[i + GAMMA_RAMP_LENGTH] = scaledValue; + rampData[i + 2 * GAMMA_RAMP_LENGTH] = scaledValue; + } + + long screenDC = WGL.GetDC(0); + boolean res = WGL.SetDeviceGammaRamp(screenDC, ShortBuffer.wrap(rampData)); + WGL.ReleaseDC(0, screenDC); + return res; + } + + protected Buffer getGammaRamp() { + ShortBuffer rampData = ShortBuffer.wrap(new short[3 * GAMMA_RAMP_LENGTH]); + long screenDC = WGL.GetDC(0); + boolean res = WGL.GetDeviceGammaRamp(screenDC, rampData); + WGL.ReleaseDC(0, screenDC); + if (!res) { + return null; + } + return rampData; + } + + protected void resetGammaRamp(Buffer originalGammaRamp) { + if (originalGammaRamp == null) { + // getGammaRamp failed earlier + return; + } + long screenDC = WGL.GetDC(0); + WGL.SetDeviceGammaRamp(screenDC, originalGammaRamp); + WGL.ReleaseDC(0, screenDC); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java new file mode 100644 index 000000000..aed4012a4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { + // Keep this under the same debug flag as the drawable factory for convenience + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + protected static final int MAX_PFORMATS = 256; + protected static final int MAX_ATTRIBS = 256; + + private PIXELFORMATDESCRIPTOR pixelfmt; + private int pixelfmtID; + private boolean isChosen = false; + private GLCapabilitiesChooser chooser; + private boolean choosenByWGLPixelFormat=false; + + public WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen, GLCapabilities capsChosen, GLCapabilities capsRequested, + PIXELFORMATDESCRIPTOR pixelfmt, int pixelfmtID, GLCapabilitiesChooser chooser) { + super(screen, capsChosen, capsRequested); + this.chooser=chooser; + this.pixelfmt = pixelfmt; + this.pixelfmtID = pixelfmtID; + } + + public static WindowsWGLGraphicsConfiguration create(long hdc, int pfdID, + GLProfile glp, AbstractGraphicsScreen screen, boolean onscreen, boolean usePBuffer) + { + if(pfdID<=0) { + throw new GLException("Invalid pixelformat id "+pfdID); + } + if(null==glp) { + glp = GLProfile.getDefault(); + } + PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); + if (WGL.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { + throw new GLException("Unable to describe pixel format " + pfdID); + } + + GLCapabilities caps = PFD2GLCapabilities(glp, pfd, onscreen, usePBuffer); + if(null==caps) { + throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+", pfdID "+pfdID); + } + WindowsWGLGraphicsConfiguration cfg = new WindowsWGLGraphicsConfiguration(screen, caps, caps, pfd, pfdID, new DefaultGLCapabilitiesChooser()); + cfg.setCapsPFD(caps, pfd, pfdID, false); + + return cfg; + } + + public Object clone() { + return super.clone(); + } + + /** Update config - before having a valid context */ + protected void updateGraphicsConfiguration(GLDrawableFactory factory, NativeWindow nativeWindow) { + WindowsWGLGraphicsConfigurationFactory.updateGraphicsConfiguration(chooser, factory, nativeWindow); + } + + /** Update config - after having a valid and current context */ + protected void updateCapabilitiesByWGL(GLContextImpl context) { + if(choosenByWGLPixelFormat) return; // already done .. + + GLCapabilities capabilities = (GLCapabilities) getRequestedCapabilities(); + boolean onscreen = capabilities.isOnscreen(); + boolean usePBuffer = capabilities.isPBuffer(); + GLProfile glp = capabilities.getGLProfile(); + + WGLExt wglExt = (WGLExt) context.getPlatformGLExtensions(); + GLDrawable drawable = context.getGLDrawable(); + NativeWindow nativeWindow = drawable.getNativeWindow(); + long hdc = nativeWindow.getSurfaceHandle(); + + GLCapabilities[] caps = HDC2GLCapabilities(wglExt, hdc, getPixelFormatID(), glp, true, onscreen, usePBuffer); + if(null!=caps && null!=caps[0]) { + setCapsPFD(caps[0], getPixelFormat(), getPixelFormatID(), true); + } + } + + protected void setCapsPFD(GLCapabilities caps, PIXELFORMATDESCRIPTOR pfd, int pfdID, boolean choosenByWGLPixelFormat) { + this.pixelfmt = pfd; + this.pixelfmtID = pfdID; + setChosenCapabilities(caps); + this.isChosen=true; + this.choosenByWGLPixelFormat=choosenByWGLPixelFormat; + if (DEBUG) { + System.err.println("*** setCapsPFD: WGL-Choosen "+choosenByWGLPixelFormat+", pfdID "+pfdID+", "+caps); + } + } + + public boolean getCapabilitiesChosen() { + return isChosen; + } + + public PIXELFORMATDESCRIPTOR getPixelFormat() { return pixelfmt; } + public int getPixelFormatID() { return pixelfmtID; } + public boolean isChoosenByWGL() { return choosenByWGLPixelFormat; } + + private static int haveWGLChoosePixelFormatARB = -1; + private static int haveWGLARBMultisample = -1; + + public static GLCapabilities[] HDC2GLCapabilities(WGLExt wglExt, long hdc, int pfdIDOnly, + GLProfile glp, boolean relaxed, boolean onscreen, boolean usePBuffer) { + + if(haveWGLChoosePixelFormatARB<0) { + haveWGLChoosePixelFormatARB = wglExt.isExtensionAvailable("WGL_ARB_pixel_format")?1:0; + } + if(haveWGLARBMultisample<0) { + haveWGLARBMultisample = wglExt.isExtensionAvailable("WGL_ARB_multisample")?1:0; + } + if (0==haveWGLChoosePixelFormatARB) { + return null; + } + + // Produce a list of GLCapabilities to give to the + // GLCapabilitiesChooser. + // Use wglGetPixelFormatAttribivARB instead of + // DescribePixelFormat to get higher-precision information + // about the pixel format (should make the GLCapabilities + // more precise as well...i.e., remove the + // "HardwareAccelerated" bit, which is basically + // meaningless, and put in whether it can render to a + // window, to a pbuffer, or to a pixmap) + GLCapabilities[] availableCaps = null; + int numFormats = 0; + int niattribs = 0; + int[] iattributes = new int [2*MAX_ATTRIBS]; + int[] iresults = new int [2*MAX_ATTRIBS]; + + iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB; + if (wglExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) { + numFormats = iresults[0]; + + if (DEBUG) { + System.err.println("wglGetPixelFormatAttribivARB reported WGL_NUMBER_PIXEL_FORMATS = " + numFormats); + } + + if(pfdIDOnly>0 && pfdIDOnly>numFormats) { + throw new GLException("Invalid pixelformat ID " + pfdIDOnly + " (should be between 1 and " + numFormats + ")"); + } + + // Should we be filtering out the pixel formats which aren't + // applicable, as we are doing here? + // We don't have enough information in the GLCapabilities to + // represent those that aren't... + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; + iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; + iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; + iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; + if (1==haveWGLARBMultisample) { + iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; + iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; + } + + if(pfdIDOnly>0) { + availableCaps = new GLCapabilities[1]; + if (!wglExt.wglGetPixelFormatAttribivARB(hdc, pfdIDOnly, 0, niattribs, iattributes, 0, iresults, 0)) { + throw new GLException("Error getting pixel format attributes for pixel format " + pfdIDOnly + " of device context"); + } + availableCaps[0] = AttribList2GLCapabilities(glp, iattributes, niattribs, iresults, + relaxed, onscreen, usePBuffer); + } else { + availableCaps = new GLCapabilities[numFormats]; + for (int i = 0; i < numFormats; i++) { + if (!wglExt.wglGetPixelFormatAttribivARB(hdc, i+1, 0, niattribs, iattributes, 0, iresults, 0)) { + throw new GLException("Error getting pixel format attributes for pixel format " + (i + 1) + " of device context"); + } + availableCaps[i] = AttribList2GLCapabilities(glp, iattributes, niattribs, iresults, + relaxed, onscreen, usePBuffer); + } + } + } else { + long lastErr = WGL.GetLastError(); + // Intel Extreme graphics fails with a zero error code + if (lastErr != 0) { + throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: error code " + WGL.GetLastError()); + } + } + return availableCaps; + } + + public static boolean GLCapabilities2AttribList(GLCapabilities caps, + int[] iattributes, + WGLExt wglExt, + boolean pbuffer, + int[] floatMode) throws GLException { + if (!wglExt.isExtensionAvailable("WGL_ARB_pixel_format")) { + return false; + } + + int niattribs = 0; + + iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + if (pbuffer) { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } + + iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; + if (caps.getDoubleBuffered()) { + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; + if (caps.getStereo()) { + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[niattribs++] = caps.getDepthBits(); + iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; + iattributes[niattribs++] = caps.getRedBits(); + iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[niattribs++] = caps.getGreenBits(); + iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[niattribs++] = caps.getBlueBits(); + iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[niattribs++] = caps.getAlphaBits(); + iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; + iattributes[niattribs++] = caps.getStencilBits(); + if (caps.getAccumRedBits() > 0 || + caps.getAccumGreenBits() > 0 || + caps.getAccumBlueBits() > 0 || + caps.getAccumAlphaBits() > 0) { + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BITS_ARB; + iattributes[niattribs++] = (caps.getAccumRedBits() + + caps.getAccumGreenBits() + + caps.getAccumBlueBits() + + caps.getAccumAlphaBits()); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; + iattributes[niattribs++] = caps.getAccumRedBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; + iattributes[niattribs++] = caps.getAccumGreenBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; + iattributes[niattribs++] = caps.getAccumBlueBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; + iattributes[niattribs++] = caps.getAccumAlphaBits(); + } + + if (wglExt.isExtensionAvailable("WGL_ARB_multisample")) { + if (caps.getSampleBuffers()) { + iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; + iattributes[niattribs++] = caps.getNumSamples(); + } + } + + boolean rtt = caps.getPbufferRenderToTexture(); + boolean rect = caps.getPbufferRenderToTextureRectangle(); + boolean useFloat = caps.getPbufferFloatingPointBuffers(); + boolean ati = false; + if (pbuffer) { + // Check some invariants and set up some state + if (rect && !rtt) { + throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified"); + } + + if (rect) { + if (!wglExt.isExtensionAvailable("GL_NV_texture_rectangle")) { + throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension"); + } + } + + if (useFloat) { + if (!wglExt.isExtensionAvailable("WGL_ATI_pixel_format_float") && + !wglExt.isExtensionAvailable("WGL_NV_float_buffer")) { + throw new GLException("Floating-point pbuffers not supported by this hardware"); + } + + // Prefer NVidia extension over ATI + if (wglExt.isExtensionAvailable("WGL_NV_float_buffer")) { + ati = false; + floatMode[0] = GLPbuffer.NV_FLOAT; + } else { + ati = true; + floatMode[0] = GLPbuffer.ATI_FLOAT; + } + if (DEBUG) { + System.err.println("Using " + (ati ? "ATI" : "NVidia") + " floating-point extension"); + } + } + + // See whether we need to change the pixel type to support ATI's + // floating-point pbuffers + if (useFloat && ati) { + if (rtt) { + throw new GLException("Render-to-floating-point-texture not supported on ATI hardware"); + } else { + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_FLOAT_ARB; + } + } else { + if (!rtt) { + // Currently we don't support non-truecolor visuals in the + // GLCapabilities, so we don't offer the option of making + // color-index pbuffers. + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB; + } + } + + if (useFloat && !ati) { + iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; + iattributes[niattribs++] = GL.GL_TRUE; + } + + if (rtt) { + if (useFloat) { + assert(!ati); + if (!rect) { + throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle"); + } + iattributes[niattribs++] = WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV; + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = rect ? WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : WGLExt.WGL_BIND_TO_TEXTURE_RGB_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } + } + } else { + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB; + } + iattributes[niattribs++] = 0; + + return true; + } + + public static final int WINDOW_BIT = 1 << 0 ; + public static final int BITMAP_BIT = 1 << 1 ; + public static final int PBUFFER_BIT = 1 << 2 ; + + public static int WGLConfig2DrawableTypeBits(int[] iattribs, + int niattribs, + int[] iresults) { + int val = 0; + + for (int i = 0; i < niattribs; i++) { + int attr = iattribs[i]; + switch (attr) { + case WGLExt.WGL_DRAW_TO_WINDOW_ARB: + if(iresults[i] == GL.GL_TRUE) val |= WINDOW_BIT; + break; + case WGLExt.WGL_DRAW_TO_BITMAP_ARB: + if(iresults[i] == GL.GL_TRUE) val |= BITMAP_BIT; + break; + case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: + if(iresults[i] == GL.GL_TRUE) val |= PBUFFER_BIT; + break; + } + } + return val; + } + + public static boolean WGLConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { + boolean res; + + if ( onscreen ) { + res = ( 0 != (val & WINDOW_BIT) ) ; + } else { + if ( usePBuffer ) { + res = ( 0 != (val & PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & BITMAP_BIT) ) ; + } + } + + return res; + } + + public static GLCapabilities AttribList2GLCapabilities(GLProfile glp, int[] iattribs, + int niattribs, + int[] iresults, + boolean relaxed, boolean onscreen, boolean usePBuffer) { + GLCapabilities res = new GLCapabilities(glp); + int drawableTypeBits = WGLConfig2DrawableTypeBits(iattribs, niattribs, iresults); + if(WGLConfigDrawableTypeVerify(drawableTypeBits, onscreen, usePBuffer)) { + res.setOnscreen(onscreen); + res.setPBuffer(usePBuffer); + } else if(relaxed) { + res.setOnscreen( 0 != (drawableTypeBits & WINDOW_BIT) ); + res.setPBuffer ( 0 != (drawableTypeBits & PBUFFER_BIT) ); + } else { + if(DEBUG) { + System.err.println("WGL DrawableType does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (drawableTypeBits & WINDOW_BIT) )+", pbuffer "+( 0 != (drawableTypeBits & PBUFFER_BIT) )+", pixmap "+( 0 != (drawableTypeBits & BITMAP_BIT))+")"); + } + return null; + } + + for (int i = 0; i < niattribs; i++) { + int attr = iattribs[i]; + switch (attr) { + case WGLExt.WGL_DRAW_TO_WINDOW_ARB: + case WGLExt.WGL_DRAW_TO_BITMAP_ARB: + case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: + break; + + case WGLExt.WGL_ACCELERATION_ARB: + res.setHardwareAccelerated(iresults[i] == WGLExt.WGL_FULL_ACCELERATION_ARB); + break; + + case WGLExt.WGL_SUPPORT_OPENGL_ARB: + if (iresults[i] != GL.GL_TRUE) { + return null; + } + break; + + case WGLExt.WGL_DEPTH_BITS_ARB: + res.setDepthBits(iresults[i]); + break; + + case WGLExt.WGL_STENCIL_BITS_ARB: + res.setStencilBits(iresults[i]); + break; + + case WGLExt.WGL_DOUBLE_BUFFER_ARB: + res.setDoubleBuffered(iresults[i] == GL.GL_TRUE); + break; + + case WGLExt.WGL_STEREO_ARB: + res.setStereo(iresults[i] == GL.GL_TRUE); + break; + + case WGLExt.WGL_PIXEL_TYPE_ARB: + // Fail softly with unknown results here + if (iresults[i] == WGLExt.WGL_TYPE_RGBA_ARB|| + iresults[i] == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) { + res.setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_FLOAT_COMPONENTS_NV: + if (iresults[i] != 0) { + res.setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_RED_BITS_ARB: + res.setRedBits(iresults[i]); + break; + + case WGLExt.WGL_GREEN_BITS_ARB: + res.setGreenBits(iresults[i]); + break; + + case WGLExt.WGL_BLUE_BITS_ARB: + res.setBlueBits(iresults[i]); + break; + + case WGLExt.WGL_ALPHA_BITS_ARB: + res.setAlphaBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_RED_BITS_ARB: + res.setAccumRedBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_GREEN_BITS_ARB: + res.setAccumGreenBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_BLUE_BITS_ARB: + res.setAccumBlueBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_ALPHA_BITS_ARB: + res.setAccumAlphaBits(iresults[i]); + break; + + case WGLExt.WGL_SAMPLE_BUFFERS_ARB: + res.setSampleBuffers(iresults[i] != 0); + break; + + case WGLExt.WGL_SAMPLES_ARB: + res.setNumSamples(iresults[i]); + break; + + default: + throw new GLException("Unknown pixel format attribute " + iattribs[i]); + } + } + return res; + } + + // PIXELFORMAT + + public static GLCapabilities PFD2GLCapabilities(GLProfile glp, PIXELFORMATDESCRIPTOR pfd, boolean onscreen, boolean usePBuffer) { + if ((pfd.getDwFlags() & WGL.PFD_SUPPORT_OPENGL) == 0) { + return null; + } + GLCapabilities res = new GLCapabilities(glp); + res.setRedBits (pfd.getCRedBits()); + res.setGreenBits (pfd.getCGreenBits()); + res.setBlueBits (pfd.getCBlueBits()); + res.setAlphaBits (pfd.getCAlphaBits()); + res.setAccumRedBits (pfd.getCAccumRedBits()); + res.setAccumGreenBits(pfd.getCAccumGreenBits()); + res.setAccumBlueBits (pfd.getCAccumBlueBits()); + res.setAccumAlphaBits(pfd.getCAccumAlphaBits()); + res.setDepthBits (pfd.getCDepthBits()); + res.setStencilBits (pfd.getCStencilBits()); + res.setDoubleBuffered((pfd.getDwFlags() & WGL.PFD_DOUBLEBUFFER) != 0); + res.setStereo ((pfd.getDwFlags() & WGL.PFD_STEREO) != 0); + res.setHardwareAccelerated( ((pfd.getDwFlags() & WGL.PFD_GENERIC_FORMAT) == 0) || + ((pfd.getDwFlags() & WGL.PFD_GENERIC_ACCELERATED) != 0) ); + res.setOnscreen ( onscreen && ((pfd.getDwFlags() & WGL.PFD_DRAW_TO_WINDOW) != 0) ); + res.setPBuffer ( usePBuffer ); + /* FIXME: Missing ?? + if (GLXUtil.isMultisampleAvailable()) { + res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); + res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); + } + res.setBackgroundOpaque(glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_TYPE, tmp, 0) != GLX.GLX_NONE); + try { + res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); + } catch (Exception e) {} + */ + return res; + } + + public static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilities caps) { + int colorDepth = (caps.getRedBits() + + caps.getGreenBits() + + caps.getBlueBits()); + if (colorDepth < 15) { + throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); + } + PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); + int pfdFlags = (WGL.PFD_SUPPORT_OPENGL | + WGL.PFD_GENERIC_ACCELERATED); + if (caps.getDoubleBuffered()) { + pfdFlags |= WGL.PFD_DOUBLEBUFFER; + } + if (caps.isOnscreen()) { + pfdFlags |= WGL.PFD_DRAW_TO_WINDOW; + } else { + pfdFlags |= WGL.PFD_DRAW_TO_BITMAP; + } + if (caps.getStereo()) { + pfdFlags |= WGL.PFD_STEREO; + } + pfd.setDwFlags(pfdFlags); + pfd.setIPixelType((byte) WGL.PFD_TYPE_RGBA); + pfd.setCColorBits((byte) colorDepth); + pfd.setCRedBits ((byte) caps.getRedBits()); + pfd.setCGreenBits((byte) caps.getGreenBits()); + pfd.setCBlueBits ((byte) caps.getBlueBits()); + pfd.setCAlphaBits((byte) caps.getAlphaBits()); + int accumDepth = (caps.getAccumRedBits() + + caps.getAccumGreenBits() + + caps.getAccumBlueBits()); + pfd.setCAccumBits ((byte) accumDepth); + pfd.setCAccumRedBits ((byte) caps.getAccumRedBits()); + pfd.setCAccumGreenBits((byte) caps.getAccumGreenBits()); + pfd.setCAccumBlueBits ((byte) caps.getAccumBlueBits()); + pfd.setCAccumAlphaBits((byte) caps.getAccumAlphaBits()); + pfd.setCDepthBits((byte) caps.getDepthBits()); + pfd.setCStencilBits((byte) caps.getStencilBits()); + pfd.setILayerType((byte) WGL.PFD_MAIN_PLANE); + + /* FIXME: Missing: + caps.getSampleBuffers() + caps.getNumSamples () + } + caps.getBackgroundOpaque() + try { + caps.getPbufferFloatingPointBuffers() + } catch (Exception e) {} + */ + return pfd; + } + + public static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor() { + PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create(); + pfd.setNSize((short) pfd.size()); + pfd.setNVersion((short) 1); + return pfd; + } + + public String toString() { + return "WindowsWGLGraphicsConfiguration["+getScreen()+", pfdID " + pixelfmtID + ", wglChoosen "+choosenByWGLPixelFormat+ + ",\n\trequested " + getRequestedCapabilities() + + ",\n\tchosen " + getChosenCapabilities() + + "]"; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..ab3227257 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.windows.*; +import com.jogamp.nativewindow.impl.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on Windows platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public WindowsWGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GLCapabilities caps = (GLCapabilities)capabilities; + return chooseGraphicsConfigurationStatic(caps, chooser, absScreen); + } + + protected static WindowsWGLGraphicsConfiguration createDefaultGraphicsConfiguration(GLProfile glp, AbstractGraphicsScreen absScreen, boolean onscreen, boolean usePBuffer) { + GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(onscreen); // FIXME DBLBUFOFFSCRN + caps.setOnscreen (onscreen); + caps.setPBuffer (usePBuffer); + + if(null==absScreen) { + absScreen = DefaultGraphicsScreen.createScreenDevice(0); + } + return new WindowsWGLGraphicsConfiguration(absScreen, caps, caps, WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(caps), -1, null); + + } + + protected static WindowsWGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilities caps, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if(null==absScreen) { + absScreen = DefaultGraphicsScreen.createScreenDevice(0); + } + GLCapabilities caps2 = (GLCapabilities) caps.clone(); + if(!caps2.isOnscreen()) { + // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN + caps2.setDoubleBuffered(false); + } + return new WindowsWGLGraphicsConfiguration(absScreen, caps2, caps, WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(caps2), -1, + (GLCapabilitiesChooser)chooser); + } + + protected static void updateGraphicsConfiguration(CapabilitiesChooser chooser, + GLDrawableFactory _factory, NativeWindow nativeWindow) { + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory; + if (nativeWindow == null) { + throw new IllegalArgumentException("NativeWindow is null"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + + boolean choosenBywGLPixelFormat = false; + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) nativeWindow.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities) config.getRequestedCapabilities(); + boolean onscreen = capabilities.isOnscreen(); + boolean usePBuffer = capabilities.isPBuffer(); + GLProfile glProfile = capabilities.getGLProfile(); + long hdc = nativeWindow.getSurfaceHandle(); + + if (DEBUG) { + Exception ex = new Exception("WindowsWGLGraphicsConfigurationFactory got HDC "+toHexString(hdc)); + ex.printStackTrace(); + System.err.println("WindowsWGLGraphicsConfigurationFactory got NW "+nativeWindow); + } + + PIXELFORMATDESCRIPTOR pfd = null; + int pixelFormat = -1; // 1-based pixel format + boolean pixelFormatSet = false; + GLCapabilities chosenCaps = null; + + if (onscreen) { + if ((pixelFormat = WGL.GetPixelFormat(hdc)) != 0) { + // Pixelformat already set by either + // - a previous updateGraphicsConfiguration() call on the same HDC, + // - the graphics driver, copying the HDC's pixelformat to the new one, + // - or the Java2D/OpenGL pipeline's configuration + if (DEBUG) { + System.err.println("!!!! NOTE: pixel format already chosen for HDC: " + toHexString(hdc)+ + ", pixelformat "+pixelFormat); + } + pixelFormatSet = true; + } + + GLCapabilities[] availableCaps = null; + int numFormats = 0; + pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); + // Produce a recommended pixel format selection for the GLCapabilitiesChooser. + // Use wglChoosePixelFormatARB if user requested multisampling and if we have it available + factory.sharedContext.makeCurrent(); + WGLExt wglExt = factory.sharedContext.getWGLExt(); + + int recommendedPixelFormat = pixelFormat; // 1-based pixel format + boolean haveWGLChoosePixelFormatARB = false; + boolean gotAvailableCaps = false; + if (wglExt != null) { + try { + haveWGLChoosePixelFormatARB = wglExt.isExtensionAvailable("WGL_ARB_pixel_format"); + if (haveWGLChoosePixelFormatARB) { + if(pixelFormat<=0) { + int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; + float[] fattributes = new float[1]; + + if(WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, + iattributes, + wglExt, + false, + null)) { + int[] pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; + int[] numFormatsTmp = new int[1]; + if (wglExt.wglChoosePixelFormatARB(hdc, + iattributes, 0, + fattributes, 0, + WindowsWGLGraphicsConfiguration.MAX_PFORMATS, + pformats, 0, + numFormatsTmp, 0)) { + numFormats = numFormatsTmp[0]; + if (recommendedPixelFormat<=0 && numFormats > 0) { + recommendedPixelFormat = pformats[0]; + if (DEBUG) { + System.err.println(getThreadName() + ": Used wglChoosePixelFormatARB to recommend pixel format " + recommendedPixelFormat); + } + } + } else { + if (DEBUG) { + System.err.println(getThreadName() + ": wglChoosePixelFormatARB failed: " + WGL.GetLastError() ); + Thread.dumpStack(); + } + } + if (DEBUG) { + if (recommendedPixelFormat <= 0) { + System.err.print(getThreadName() + ": wglChoosePixelFormatARB didn't recommend a pixel format: "+WGL.GetLastError()); + if (capabilities.getSampleBuffers()) { + System.err.print(" for multisampled GLCapabilities"); + } + System.err.println(); + } + } + } + } + + availableCaps = WindowsWGLGraphicsConfiguration.HDC2GLCapabilities(wglExt, hdc, -1, glProfile, pixelFormatSet, onscreen, usePBuffer); + gotAvailableCaps = null!=availableCaps ; + choosenBywGLPixelFormat = gotAvailableCaps ; + } else if (DEBUG) { + System.err.println(getThreadName() + ": wglChoosePixelFormatARB not available"); + } + } finally { + factory.sharedContext.release(); + } + } + + if (!gotAvailableCaps) { + if (DEBUG) { + System.err.println(getThreadName() + ": Using ChoosePixelFormat ... (LastError: "+WGL.GetLastError()+")"); + } + pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capabilities); + recommendedPixelFormat = WGL.ChoosePixelFormat(hdc, pfd); + if (DEBUG) { + System.err.println(getThreadName() + ": ChoosePixelFormat(HDC "+toHexString(hdc)+") = " + recommendedPixelFormat + " (LastError: "+WGL.GetLastError()+")"); + System.err.println(getThreadName() + ": Used " + capabilities); + } + + numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null); + if (numFormats == 0) { + throw new GLException("Unable to enumerate pixel formats of window " + + toHexString(hdc) + " for GLCapabilitiesChooser (LastError: "+WGL.GetLastError()+")"); + } + availableCaps = new GLCapabilities[numFormats]; + for (int i = 0; i < numFormats; i++) { + if (WGL.DescribePixelFormat(hdc, 1 + i, pfd.size(), pfd) == 0) { + throw new GLException("Error describing pixel format " + (1 + i) + " of device context"); + } + availableCaps[i] = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, pfd, onscreen, usePBuffer); + } + } + + // NOTE: officially, should make a copy of all of these + // GLCapabilities to avoid mutation by the end user during the + // chooseCapabilities call, but for the time being, assume they + // won't be changed + + if(pixelFormat<=0) { + if(null!=chooser) { + // Supply information to chooser + try { + pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, recommendedPixelFormat) + 1; + } catch (NativeWindowException e) { + if(DEBUG) { + e.printStackTrace(); + } + pixelFormat = -1; + } + } else { + pixelFormat = recommendedPixelFormat; + } + if (pixelFormat <= 0) { + // keep on going .. + if(DEBUG) { + System.err.println("WindowsWGLGraphicsConfigurationFactory.updateGraphicsConfiguration .. unable to choose config, using first"); + } + pixelFormat = 1; // default .. + } else if ( pixelFormat > numFormats ) { + // keep on going .. + if(DEBUG) { + System.err.println("GLCapabilitiesChooser specified invalid index (expected 1.." + numFormats + ", got "+pixelFormat+")"); + } + pixelFormat = 1; // default .. + } + } + chosenCaps = availableCaps[pixelFormat-1]; + if (DEBUG) { + System.err.println(getThreadName() + ": Chosen pixel format (" + pixelFormat + "):"); + System.err.println(chosenCaps); + } + if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) { + throw new GLException("Error re-describing the chosen pixel format: " + WGL.GetLastError()); + } + } else { + // For now, use ChoosePixelFormat for offscreen surfaces until + // we figure out how to properly choose an offscreen- + // compatible pixel format + pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capabilities); + pixelFormat = WGL.ChoosePixelFormat(hdc, pfd); + } + if(!pixelFormatSet) { + if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) { + long lastError = WGL.GetLastError(); + if (DEBUG) { + System.err.println(getThreadName() + ": SetPixelFormat failed: current context = " + WGL.wglGetCurrentContext() + + ", current DC = " + WGL.wglGetCurrentDC()); + System.err.println(getThreadName() + ": GetPixelFormat(hdc " + toHexString(hdc) + ") returns " + WGL.GetPixelFormat(hdc)); + } + throw new GLException("Unable to set pixel format " + pixelFormat + " for device context " + toHexString(hdc) + ": error code " + lastError); + } + pixelFormatSet=true; + } + // Reuse the previously-constructed GLCapabilities because it + // turns out that using DescribePixelFormat on some pixel formats + // (which, for example, support full-scene antialiasing) for some + // reason return that they are not OpenGL-capable + if (chosenCaps != null) { + capabilities = chosenCaps; + } else { + capabilities = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, pfd, onscreen, usePBuffer); + } + config.setCapsPFD(capabilities, pfd, pixelFormat, choosenBywGLPixelFormat); + } + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } + public static String toHexString(long hex) { + return "0x" + Long.toHexString(hex); + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..02cfd14c3 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.windows.wgl.awt; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import javax.media.nativewindow.*; +import javax.media.nativewindow.windows.*; +import javax.media.nativewindow.awt.*; +import javax.media.opengl.*; +import javax.media.opengl.awt.*; + +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.windows.wgl.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.windows.*; + +public class WindowsAWTWGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public WindowsAWTWGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GraphicsDevice device = null; + if (absScreen != null && + !(absScreen instanceof AWTGraphicsScreen)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); + } + + if(null==absScreen) { + absScreen = AWTGraphicsScreen.createScreenDevice(-1); + } + AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; + device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilitiesChooser objects"); + } + + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: got "+absScreen); + } + GraphicsConfiguration gc = device.getDefaultConfiguration(); + AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capabilities, gc); + if(DEBUG) { + System.err.println("AWT Colormodel compatible: "+capabilities); + } + + long displayHandle = 0; + + WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(); + DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex()); + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: made "+winScreen); + } + + WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(winDevice).chooseGraphicsConfiguration(capabilities, + chooser, + winScreen); + + if (winConfig == null) { + throw new GLException("Unable to choose a GraphicsConfiguration: "+capabilities+",\n\t"+chooser+"\n\t"+winScreen); + } + + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: chosen "+winConfig); + } + + // FIXME: we have nothing to match .. so choose the default + return new AWTGraphicsConfiguration(awtScreen, winConfig.getChosenCapabilities(), winConfig.getRequestedCapabilities(), gc, winConfig); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java new file mode 100644 index 000000000..ec0eaf94f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; + +import com.jogamp.nativewindow.impl.x11.*; + +public class GLXUtil { + public static boolean isMultisampleAvailable(long display) { + X11Lib.XLockDisplay(display); + try { + String exts = GLX.glXGetClientString(display, GLX.GLX_EXTENSIONS); + if (exts != null) { + return (exts.indexOf("GLX_ARB_multisample") >= 0); + } + return false; + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + /** Workaround for apparent issue with ATI's proprietary drivers + where direct contexts still send GLX tokens for GL calls */ + public static String getVendorName(long display) { + X11Lib.XLockDisplay(display); + try { + return GLX.glXGetClientString(display, GLX.GLX_VENDOR); + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + public static boolean isVendorNVIDIA(String vendor) { + return vendor != null && vendor.startsWith("NVIDIA") ; + } + + public static boolean isVendorATI(String vendor) { + return vendor != null && vendor.startsWith("ATI") ; + } + + public static boolean isVendorATI(long display) { + return isVendorATI(getVendorName(display)); + } + + public static boolean isVendorNVIDIA(long display) { + return isVendorNVIDIA(getVendorName(display)); + } + + public static void getGLXVersion(long display, int major[], int minor[]) { + if(0 == display) { + throw new GLException("null display handle"); + } + if(major.length<1||minor.length<1) { + throw new GLException("passed int arrays size is not >= 1"); + } + + if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) { + throw new GLException("glXQueryVersion failed"); + } + + // Work around bugs in ATI's Linux drivers where they report they + // only implement GLX version 1.2 on the server side + if (major[0] == 1 && minor[0] == 2) { + String str = GLX.glXGetClientString(display, GLX.GLX_VERSION); + try { + // e.g. "1.3" + major[0] = Integer.valueOf(str.substring(0, 1)).intValue(); + minor[0] = Integer.valueOf(str.substring(2, 3)).intValue(); + } catch (Exception e) { + major[0] = 1; + minor[0] = 2; + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java new file mode 100644 index 000000000..1f148bead --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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 + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import com.jogamp.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { + + private long dummyWindow = 0; + + /** + * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277, + * we cannot switch the Display as we please, + * hence we reuse the target's screen configuration. + */ + public X11DummyGLXDrawable(X11GraphicsScreen screen, GLDrawableFactory factory, GLProfile glp) { + super(factory, + new NullWindow(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + new GLCapabilities(glp), null, screen))); + this.realized = true; + + NullWindow nw = (NullWindow) getNativeWindow(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities caps = (GLCapabilities) config.getChosenCapabilities(); + + X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); + long dpy = device.getHandle(); + int scrn = screen.getIndex(); + long visualID = config.getVisualID(); + + X11Lib.XLockDisplay(dpy); + try{ + dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID); + } finally { + X11Lib.XUnlockDisplay(dpy); + } + nw.setSurfaceHandle( dummyWindow ); + } + + public void setSize(int width, int height) { + } + + public int getWidth() { + return 1; + } + + public int getHeight() { + return 1; + } + + public void destroy() { + if(0!=dummyWindow) { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long dpy = config.getScreen().getDevice().getHandle(); + X11Lib.DestroyDummyWindow(dpy, dummyWindow); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java new file mode 100755 index 000000000..139c0deed --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java @@ -0,0 +1,154 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11ExternalGLXContext extends X11GLXContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + private X11ExternalGLXContext(Drawable drawable, long context) { + super(drawable, null); + this.context = context; + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + protected static X11ExternalGLXContext create(GLDrawableFactory factory, GLProfile glp) { + ((GLDrawableFactoryImpl)factory).lockToolkit(); + try { + long context = GLX.glXGetCurrentContext(); + if (context == 0) { + throw new GLException("Error: current context null"); + } + long display = GLX.glXGetCurrentDisplay(); + if (display == 0) { + throw new GLException("Error: current display null"); + } + long drawable = GLX.glXGetCurrentDrawable(); + if (drawable == 0) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable/context current"); + } + int[] val = new int[1]; + GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val, 0); + X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0]); + + GLX.glXQueryContext(display, context, GLX.GLX_FBCONFIG_ID, val, 0); + X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]); + + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(drawable); + return new X11ExternalGLXContext(new Drawable(factory, nw), context); + } finally { + ((GLDrawableFactoryImpl)factory).unlockToolkit(); + } + } + + protected void create() { + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } + + // Need to provide the display connection to extension querying APIs + static class Drawable extends X11GLXDrawable { + Drawable(GLDrawableFactory factory, NativeWindow comp) { + super(factory, comp, true); + } + + public GLContext createContext(GLContext shareWith) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } + + public void setSize(int width, int height) { + throw new GLException("Should not call this"); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java new file mode 100755 index 000000000..f10bd38c6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java @@ -0,0 +1,132 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + + +public class X11ExternalGLXDrawable extends X11GLXDrawable { + private int fbConfigID; + private int renderType; + + private X11ExternalGLXDrawable(GLDrawableFactory factory, NativeWindow component, int renderType) { + super(factory, component, true); + + this.renderType = renderType; + + // Need GLXFBConfig ID in order to properly create new contexts + // on this drawable + X11GLXGraphicsConfiguration cfg = (X11GLXGraphicsConfiguration) component.getGraphicsConfiguration(); + fbConfigID = cfg.getFBConfigID(); + } + + protected static X11ExternalGLXDrawable create(GLDrawableFactory factory, GLProfile glp) { + ((GLDrawableFactoryImpl)factory).lockToolkit(); + try { + long context = GLX.glXGetCurrentContext(); + if (context == 0) { + throw new GLException("Error: current context null"); + } + long display = GLX.glXGetCurrentDisplay(); + if (display == 0) { + throw new GLException("Error: current display null"); + } + long drawable = GLX.glXGetCurrentDrawable(); + if (drawable == 0) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable current"); + } + int[] val = new int[1]; + GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val, 0); + X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0]); + + GLX.glXQueryContext(display, context, GLX.GLX_FBCONFIG_ID, val, 0); + X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]); + + int w, h; + GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val, 0); + w=val[0]; + GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val, 0); + h=val[0]; + + GLX.glXQueryContext(display, context, GLX.GLX_RENDER_TYPE, val, 0); + if ((val[0] & GLX.GLX_RGBA_TYPE) == 0) { + if (DEBUG) { + System.err.println("X11ExternalGLXDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts (current 0x"+Integer.toHexString(val[0])+")"); + } + } + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(drawable); + nw.setSize(w, h); + return new X11ExternalGLXDrawable(factory, nw, GLX.GLX_RGBA_TYPE); + } finally { + ((GLDrawableFactoryImpl)factory).unlockToolkit(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new Context(this, shareWith); + } + + public void setSize(int newWidth, int newHeight) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + return getNativeWindow().getWidth(); + } + + public int getHeight() { + return getNativeWindow().getHeight(); + } + + class Context extends X11GLXContext { + Context(X11GLXDrawable drawable, GLContext shareWith) { + super(drawable, shareWith); + } + + protected void create() { + createContext(true); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java new file mode 100644 index 000000000..dce25978c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java @@ -0,0 +1,582 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.glx.*; +import com.jogamp.nativewindow.impl.x11.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; + +public abstract class X11GLXContext extends GLContextImpl { + protected long context; + private boolean glXQueryExtensionsStringInitialized; + private boolean glXQueryExtensionsStringAvailable; + private static final Map/*<String, String>*/ functionNameMap; + private static final Map/*<String, String>*/ extensionNameMap; + private GLXExt glXExt; + // Table that holds the addresses of the native C-language entry points for + // GLX extension functions. + private GLXExtProcAddressTable glXExtProcAddressTable; + + static { + functionNameMap = new HashMap(); + functionNameMap.put("glAllocateMemoryNV", "glXAllocateMemoryNV"); + functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV"); + + extensionNameMap = new HashMap(); + extensionNameMap.put("GL_ARB_pbuffer", "GLX_SGIX_pbuffer"); + extensionNameMap.put("GL_ARB_pixel_format", "GLX_SGIX_pbuffer"); // good enough + } + + public X11GLXContext(GLDrawableImpl drawable, GLDrawableImpl drawableRead, + GLContext shareWith) { + super(drawable, drawableRead, shareWith); + } + + public X11GLXContext(GLDrawableImpl drawable, + GLContext shareWith) { + this(drawable, null, shareWith); + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return getGLXExtProcAddressTable(); + } + + public final GLXExtProcAddressTable getGLXExtProcAddressTable() { + return glXExtProcAddressTable; + } + + public Object getPlatformGLExtensions() { + return getGLXExt(); + } + + public GLXExt getGLXExt() { + if (glXExt == null) { + glXExt = new GLXExtImpl(this); + } + return glXExt; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return functionNameMap; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return extensionNameMap; } + + protected boolean glXMakeContextCurrent(long dpy, long writeDrawable, long readDrawable, long ctx) { + boolean res = false; + + try { + res = GLX.glXMakeContextCurrent(dpy, writeDrawable, readDrawable, ctx); + } catch (RuntimeException re) { + if(DEBUG) { + System.err.println("X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+ + "dpy "+toHexString(dpy)+ + ", write "+toHexString(writeDrawable)+ + ", read "+toHexString(readDrawable)+ + ", ctx "+toHexString(ctx)); + re.printStackTrace(); + } + } + return res; + } + + protected void destroyContextARBImpl(long _context) { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long display = config.getScreen().getDevice().getHandle(); + + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, _context); + } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long display = config.getScreen().getDevice().getHandle(); + + GLXExt glXExt; + if(null==factory.getSharedContext()) { + glXExt = getGLXExt(); + } else { + glXExt = ((X11GLXContext)factory.getSharedContext()).getGLXExt(); + } + + boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; + boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; + boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; + + long _context=0; + + int attribs[] = { + /* 0 */ GLX.GLX_CONTEXT_MAJOR_VERSION_ARB, major, + /* 2 */ GLX.GLX_CONTEXT_MINOR_VERSION_ARB, minor, + /* 4 */ GLX.GLX_RENDER_TYPE, GLX.GLX_RGBA_TYPE, // default + /* 6 */ GLX.GLX_CONTEXT_FLAGS_ARB, 0, + /* 8 */ 0, 0, + /* 10 */ 0 + }; + + if ( major > 3 || major == 3 && minor >= 2 ) { + // FIXME: Verify with a None drawable binding (default framebuffer) + attribs[8+0] = GLX.GLX_CONTEXT_PROFILE_MASK_ARB; + if( ctBwdCompat ) { + attribs[8+1] = GLX.GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + } else { + attribs[8+1] = GLX.GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + } + } + + if ( major >= 3 ) { + if( !ctBwdCompat && ctFwdCompat ) { + attribs[6+1] |= GLX.GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + } + if( ctDebug) { + attribs[6+1] |= GLX.GLX_CONTEXT_DEBUG_BIT_ARB; + } + } + + try { + _context = glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs, 0); + } catch (RuntimeException re) { + if(DEBUG) { + System.err.println("X11GLXContext.createContextARB glXCreateContextAttribsARB failed: "+re+", with "+getGLVersion(null, major, minor, ctp, "@creation")); + re.printStackTrace(); + } + } + if(0==_context) { + if(DEBUG) { + System.err.println("X11GLXContext.createContextARB couldn't create "+getGLVersion(null, major, minor, ctp, "@creation")); + } + } else { + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + _context)) { + if(DEBUG) { + System.err.println("X11GLXContext.createContextARB couldn't make current "+getGLVersion(null, major, minor, ctp, "@creation")); + } + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, _context); + _context = 0; + } + } + return _context; + } + + /** + * Creates and initializes an appropriate OpenGL context. Should only be + * called by {@link #create()}. + * Note: The direct parameter may be overwritten by the direct state of a shared context. + */ + protected void createContext(boolean direct) { + if(0!=context) { + throw new GLException("context is not null: "+context); + } + X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long display = config.getScreen().getDevice().getHandle(); + + X11GLXContext other = (X11GLXContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getContext(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + direct = GLX.glXIsDirect(display, share); + } + + GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); + GLProfile glp = glCaps.getGLProfile(); + isVendorATI = factory.isVendorATI(); + + if(config.getFBConfigID()<0) { + // not able to use FBConfig + if(glp.isGL3()) { + throw new GLException("Unable to create OpenGL >= 3.1 context"); + } + context = GLX.glXCreateContext(display, config.getXVisualInfo(), share, direct); + if (context == 0) { + throw new GLException("Unable to create context(0)"); + } + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + context)) { + throw new GLException("Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + return; + } + + int minor[] = new int[1]; + int major[] = new int[1]; + int ctp[] = new int[1]; + boolean createContextARBTried = false; + + // utilize the shared context's GLXExt in case it was using the ARB method and it already exists + if(null!=factory.getSharedContext() && factory.getSharedContext().isCreatedWithARBMethod()) { + if(DEBUG) { + System.err.println("X11GLXContext.createContext using shared Context: "+factory.getSharedContext()); + } + context = createContextARB(share, direct, major, minor, ctp); + createContextARBTried = true; + } + + long temp_context = 0; + if(0==context) { + // To use GLX_ARB_create_context, we have to make a temp context current, + // so we are able to use GetProcAddress + temp_context = GLX.glXCreateNewContext(display, config.getFBConfig(), GLX.GLX_RGBA_TYPE, share, direct); + if (temp_context == 0) { + throw new GLException("Unable to create temp OpenGL context(1)"); + } + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + temp_context)) { + throw new GLException("Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + + if( createContextARBTried || + !isFunctionAvailable("glXCreateContextAttribsARB") || + !isExtensionAvailable("GLX_ARB_create_context") ) { + if(glp.isGL3()) { + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, temp_context); + throw new GLException("Unable to create OpenGL >= 3.1 context (failed GLX_ARB_create_context), GLProfile "+glp+", Drawable "+drawable); + } + + // continue with temp context for GL < 3.0 + context = temp_context; + return; + } + context = createContextARB(share, direct, major, minor, ctp); + createContextARBTried=true; + } + + if(0!=context) { + if(0!=temp_context) { + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, temp_context); + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + context)) { + throw new GLException("Cannot make previous verified context current"); + } + } + } else { + if(glp.isGL3()) { + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, temp_context); + throw new GLException("X11GLXContext.createContext failed, but context > GL2 requested "+getGLVersion(null, major[0], minor[0], ctp[0], "@creation")+", "); + } + if(DEBUG) { + System.err.println("X11GLXContext.createContext failed, fall back to !ARB context "+getGLVersion(null, major[0], minor[0], ctp[0], "@creation")); + } + + // continue with temp context for GL <= 3.0 + context = temp_context; + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + context)) { + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, temp_context); + throw new GLException("Error making context(1) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); + } + } + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + return makeCurrentImplAfterLock(); + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY) && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected void releaseImpl() throws GLException { + try { + releaseImplAfterLock(); + } finally { + if (!isOptimizable() && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + protected int makeCurrentImplAfterLock() throws GLException { + long dpy = drawable.getNativeWindow().getDisplayHandle(); + + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (drawable.getNativeWindow().getSurfaceHandle() == 0) { + throw new GLException("drawable not properly initialized: "+drawable); + } + boolean created = false; + if (context == 0) { + create(); + created = true; + GLContextShareSet.contextCreated(this); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName()); + } + } + + if (GLX.glXGetCurrentContext() != context) { + + if (!glXMakeContextCurrent(dpy, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + context)) { + throw new GLException("Error making context current: "+this); + } + if (DEBUG && (VERBOSE || created)) { + System.err.println(getThreadName() + ": glXMakeCurrent(display " + + toHexString(dpy)+ + ", drawable " + toHexString(drawable.getNativeWindow().getSurfaceHandle()) + + ", drawableRead " + toHexString(drawableRead.getNativeWindow().getSurfaceHandle()) + + ", context " + toHexString(context) + ") succeeded"); + } + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected void releaseImplAfterLock() throws GLException { + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (!glXMakeContextCurrent(drawable.getNativeWindow().getDisplayHandle(), 0, 0, 0)) { + throw new GLException("Error freeing OpenGL context"); + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected void destroyImpl() throws GLException { + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (context != 0) { + if (DEBUG) { + System.err.println("glXDestroyContext(" + + toHexString(drawable.getNativeWindow().getDisplayHandle()) + + ", " + + toHexString(context) + ")"); + } + GLX.glXDestroyContext(drawable.getNativeWindow().getDisplayHandle(), context); + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL context " + context); + } + context = 0; + GLContextShareSet.contextDestroyed(this); + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + public boolean isCreated() { + return (context != 0); + } + + public void copy(GLContext source, int mask) throws GLException { + long dst = getContext(); + long src = ((X11GLXContext) source).getContext(); + if (src == 0) { + throw new GLException("Source OpenGL context has not been created"); + } + if (dst == 0) { + throw new GLException("Destination OpenGL context has not been created"); + } + if (drawable.getNativeWindow().getDisplayHandle() == 0) { + throw new GLException("Connection to X display not yet set up"); + } + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + GLX.glXCopyContext(drawable.getNativeWindow().getDisplayHandle(), src, dst, mask); + // Should check for X errors and raise GLException + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing GLX extension address table"); + } + glXQueryExtensionsStringInitialized = false; + glXQueryExtensionsStringAvailable = false; + + if (glXExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + glXExtProcAddressTable = new GLXExtProcAddressTable(); + } + resetProcAddressTable(getGLXExtProcAddressTable()); + super.updateGLProcAddressTable(major, minor, ctp); + } + + public synchronized String getPlatformExtensionsString() { + if (!glXQueryExtensionsStringInitialized) { + glXQueryExtensionsStringAvailable = + getDrawableImpl().getDynamicLookupHelper().dynamicLookupFunction("glXQueryExtensionsString") != 0; + glXQueryExtensionsStringInitialized = true; + } + if (glXQueryExtensionsStringAvailable) { + GLDrawableFactoryImpl factory = getDrawableImpl().getFactoryImpl(); + factory.lockToolkit(); + try { + String ret = GLX.glXQueryExtensionsString(drawable.getNativeWindow().getDisplayHandle(), + drawable.getNativeWindow().getScreenIndex()); + if (DEBUG) { + System.err.println("!!! GLX extensions: " + ret); + } + return ret; + } finally { + factory.unlockToolkit(); + } + } else { + return ""; + } + } + + public boolean isExtensionAvailable(String glExtensionName) { + if (glExtensionName.equals("GL_ARB_pbuffer") || + glExtensionName.equals("GL_ARB_pixel_format")) { + return getGLDrawable().getFactory().canCreateGLPbuffer( + drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice() ); + } + return super.isExtensionAvailable(glExtensionName); + } + + + private int hasSwapIntervalSGI = 0; + + protected void setSwapIntervalImpl(int interval) { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); + if(!glCaps.isOnscreen()) return; + + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + GLXExt glXExt = getGLXExt(); + if(0==hasSwapIntervalSGI) { + try { + hasSwapIntervalSGI = glXExt.isExtensionAvailable("GLX_SGI_swap_control")?1:-1; + } catch (Throwable t) { hasSwapIntervalSGI=1; } + } + if (hasSwapIntervalSGI>0) { + try { + if( 0 == glXExt.glXSwapIntervalSGI(interval) ) { + currentSwapInterval = interval; + } + } catch (Throwable t) { hasSwapIntervalSGI=-1; } + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + return getGLXExt().glXAllocateMemoryNV(arg0, arg1, arg2, arg3); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + public boolean isOptimizable() { + return (super.isOptimizable() && !isVendorATI); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + public long getContext() { + return context; + } + + private boolean isVendorATI = false; + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java new file mode 100644 index 000000000..95dfc0a1c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java @@ -0,0 +1,97 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.common.os.DynamicLookupHelper; + +public abstract class X11GLXDrawable extends GLDrawableImpl { + protected X11GLXDrawable(GLDrawableFactory factory, NativeWindow comp, boolean realized) { + super(factory, comp, realized); + } + + public DynamicLookupHelper getDynamicLookupHelper() { + return (X11GLXDrawableFactory) getFactoryImpl() ; + } + + protected void setRealizedImpl() { + if(!realized) { + return; // nothing to do + } + + if(NativeWindow.LOCK_SURFACE_NOT_READY == lockSurface()) { + throw new GLException("X11GLXDrawable.setRealized(true): lockSurface - surface not ready"); + } + try { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateGraphicsConfiguration(); + + if (DEBUG) { + System.err.println("!!! X11GLXDrawable.setRealized(true): "+config); + } + } finally { + unlockSurface(); + } + } + + protected void swapBuffersImpl() { + boolean didLock = false; + if (!isSurfaceLocked()) { + // Usually the surface shall be locked within [makeCurrent .. swap .. release] + if (lockSurface() == NativeWindow.LOCK_SURFACE_NOT_READY) { + return; + } + didLock = true; + } + try { + GLX.glXSwapBuffers(component.getDisplayHandle(), component.getSurfaceHandle()); + } finally { + if (didLock) { + unlockSurface(); + } + } + } + + //--------------------------------------------------------------------------- + // Internals only below this point + // +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java new file mode 100644 index 000000000..d8e5f7646 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java @@ -0,0 +1,398 @@ +/* + * 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.impl.x11.glx; + +import com.jogamp.common.os.DynamicLookupHelper; +import java.nio.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.opengl.*; +import com.jogamp.gluegen.runtime.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import com.jogamp.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { + + public X11GLXDrawableFactory() { + super(); + // Must initialize GLX support eagerly in case a pbuffer is the + // first thing instantiated + GLProcAddressHelper.resetProcAddressTable(GLX.getGLXProcAddressTable(), this); + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new X11GLXGraphicsConfigurationFactory(); + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.x11.glx.awt.X11AWTGLXGraphicsConfigurationFactory", + new Object[] {}); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + + X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createThreadLocalDisplay(null)); + vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); + isVendorATI = GLXUtil.isVendorATI(vendorName); + isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(sharedDevice.getHandle()); // ATI hack .. + } + sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + X11Lib.XLockDisplay(sharedScreen.getDevice().getHandle()); + try{ + sharedDrawable = new X11DummyGLXDrawable(sharedScreen, this, null); + X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); + ctx.makeCurrent(); + ctx.release(); + sharedContext = ctx; + }finally{ + X11Lib.XUnlockDisplay(sharedScreen.getDevice().getHandle()); + } + if(null==sharedContext) { + throw new GLException("Couldn't init shared resources"); + } + if (DEBUG) { + System.err.println("!!! Vendor: "+vendorName+", ATI: "+isVendorATI+", NV: "+isVendorNVIDIA); + System.err.println("!!! SharedScreen: "+sharedScreen); + System.err.println("!!! SharedContext: "+sharedContext); + } + } + + private X11GraphicsScreen sharedScreen; + private String vendorName; + private boolean isVendorATI; + private boolean isVendorNVIDIA; + + public String getVendorName() { return vendorName; } + public boolean isVendorATI() { return isVendorATI; } + public boolean isVendorNVIDIA() { return isVendorNVIDIA; } + + private X11DummyGLXDrawable sharedDrawable=null; + private X11GLXContext sharedContext=null; + + protected final GLDrawableImpl getSharedDrawable() { + validate(); + return sharedDrawable; + } + + protected final GLContextImpl getSharedContext() { + validate(); + return sharedContext; + } + + public void shutdown() { + super.shutdown(); + if (DEBUG) { + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! CTX : "+sharedContext); + System.err.println("!!! Drawable: "+sharedDrawable); + System.err.println("!!! Screen : "+sharedScreen); + Exception e = new Exception("Debug"); + e.printStackTrace(); + } + if(null!=sharedContext) { + sharedContext.destroy(); // implies release, if current + } + if(null!=sharedDrawable) { + sharedDrawable.destroy(); + } + if(null!=sharedScreen) { + X11GraphicsDevice sharedDevice = (X11GraphicsDevice) sharedScreen.getDevice(); + if(null!=sharedDevice) { + X11Util.closeThreadLocalDisplay(null); + } + sharedScreen = null; + } + X11Util.shutdown( !isVendorATI(), DEBUG ); + } + + public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. + } + return new X11OnscreenGLXDrawable(this, target); + } + + protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. + } + return new X11OffscreenGLXDrawable(this, target); + } + + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + validate(); + return glxVersionGreaterEqualThan(device, 1, 3); + } + + private boolean glxVersionsQueried = false; + private int glxVersionMajor=0, glxVersionMinor=0; + public boolean glxVersionGreaterEqualThan(AbstractGraphicsDevice device, int majorReq, int minorReq) { + validate(); + if (!glxVersionsQueried) { + if(null == device) { + device = (X11GraphicsDevice) sharedScreen.getDevice(); + } + if(null == device) { + throw new GLException("FIXME: No AbstractGraphicsDevice (passed or shared-device"); + } + long display = device.getHandle(); + int[] major = new int[1]; + int[] minor = new int[1]; + + GLXUtil.getGLXVersion(display, major, minor); + if (DEBUG) { + System.err.println("!!! GLX version: major " + major[0] + + ", minor " + minor[0]); + } + + glxVersionMajor = major[0]; + glxVersionMinor = minor[0]; + glxVersionsQueried = true; + } + return ( glxVersionMajor > majorReq ) || ( glxVersionMajor == majorReq && glxVersionMinor >= minorReq ) ; + } + + protected GLDrawableImpl createGLPbufferDrawableImpl(final NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + + GLDrawableImpl pbufferDrawable; + + /** + * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277, + * we need to have a context current on the same Display to create a PBuffer. + * The dummy context shall also use the same Display, + * since switching Display in this regard is another ATI bug. + */ + boolean usedSharedContext=false; + if( isVendorATI() && null == GLContext.getCurrent() ) { + sharedContext.makeCurrent(); + usedSharedContext=true; + } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. + } + try { + pbufferDrawable = new X11PbufferGLXDrawable(this, target); + } finally { + if(usedSharedContext) { + sharedContext.release(); + } + } + return pbufferDrawable; + } + + + protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { + validate(); + NullWindow nw = null; + X11Lib.XLockDisplay(sharedScreen.getDevice().getHandle()); + try{ + nw = new NullWindow(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, sharedScreen)); + }finally{ + X11Lib.XUnlockDisplay(sharedScreen.getDevice().getHandle()); + } + if(nw != null) { + nw.setSize(width, height); + } + return nw; + } + + public GLContext createExternalGLContext() { + validate(); + return X11ExternalGLXContext.create(this, null); + } + + public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + validate(); + return canCreateGLPbuffer(device); + } + + public GLDrawable createExternalGLDrawable() { + validate(); + return X11ExternalGLXDrawable.create(this, null); + } + + public void loadGLULibrary() { + validate(); + X11Lib.dlopen("/usr/lib/libGLU.so"); + } + + public long dynamicLookupFunction(String glFuncName) { + long res = 0; + res = GLX.glXGetProcAddressARB(glFuncName); + if (res == 0) { + // GLU routines aren't known to the OpenGL function lookup + res = X11Lib.dlsym(glFuncName); + } + return res; + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + validate(); + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + throw new GLException("Unimplemented on this platform"); + } + + //---------------------------------------------------------------------- + // Gamma-related functionality + // + + private boolean gotGammaRampLength; + private int gammaRampLength; + protected synchronized int getGammaRampLength() { + if (gotGammaRampLength) { + return gammaRampLength; + } + + long display = sharedScreen.getDevice().getHandle(); + + X11Lib.XLockDisplay(display); + try { + int[] size = new int[1]; + boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, + X11Lib.DefaultScreen(display), + size, 0); + if (!res) { + return 0; + } + gotGammaRampLength = true; + gammaRampLength = size[0]; + return gammaRampLength; + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + protected boolean setGammaRamp(float[] ramp) { + int len = ramp.length; + short[] rampData = new short[len]; + for (int i = 0; i < len; i++) { + rampData[i] = (short) (ramp[i] * 65535); + } + + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); + try { + boolean res = X11Lib.XF86VidModeSetGammaRamp(display, + X11Lib.DefaultScreen(display), + rampData.length, + rampData, 0, + rampData, 0, + rampData, 0); + return res; + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + protected Buffer getGammaRamp() { + int size = getGammaRampLength(); + ShortBuffer rampData = ShortBuffer.wrap(new short[3 * size]); + rampData.position(0); + rampData.limit(size); + ShortBuffer redRampData = rampData.slice(); + rampData.position(size); + rampData.limit(2 * size); + ShortBuffer greenRampData = rampData.slice(); + rampData.position(2 * size); + rampData.limit(3 * size); + ShortBuffer blueRampData = rampData.slice(); + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); + try { + boolean res = X11Lib.XF86VidModeGetGammaRamp(display, + X11Lib.DefaultScreen(display), + size, + redRampData, + greenRampData, + blueRampData); + if (!res) { + return null; + } + return rampData; + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + protected void resetGammaRamp(Buffer originalGammaRamp) { + if (originalGammaRamp == null) + return; // getGammaRamp failed originally + ShortBuffer rampData = (ShortBuffer) originalGammaRamp; + int capacity = rampData.capacity(); + if ((capacity % 3) != 0) { + throw new IllegalArgumentException("Must not be the original gamma ramp"); + } + int size = capacity / 3; + rampData.position(0); + rampData.limit(size); + ShortBuffer redRampData = rampData.slice(); + rampData.position(size); + rampData.limit(2 * size); + ShortBuffer greenRampData = rampData.slice(); + rampData.position(2 * size); + rampData.limit(3 * size); + ShortBuffer blueRampData = rampData.slice(); + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); + try { + X11Lib.XF86VidModeSetGammaRamp(display, + X11Lib.DefaultScreen(display), + size, + redRampData, + greenRampData, + blueRampData); + } finally { + X11Lib.XUnlockDisplay(display); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java new file mode 100644 index 000000000..35daf0ae0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import com.jogamp.common.nio.PointerBuffer; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implements Cloneable { + protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + + public static final int MAX_ATTRIBS = 128; + private long fbConfig; + private int fbConfigID; + private GLCapabilitiesChooser chooser; + + public X11GLXGraphicsConfiguration(X11GraphicsScreen screen, + GLCapabilities capsChosen, GLCapabilities capsRequested, GLCapabilitiesChooser chooser, + XVisualInfo info, long fbcfg, int fbcfgID) { + super(screen, capsChosen, capsRequested, info); + this.chooser=chooser; + fbConfig = fbcfg; + fbConfigID = fbcfgID; + } + + public static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) { + long display = x11Screen.getDevice().getHandle(); + if(0==display) { + throw new GLException("Display null of "+x11Screen); + } + int screen = x11Screen.getIndex(); + long fbcfg = glXFBConfigID2FBConfig(display, screen, fbcfgID); + if(0==fbcfg) { + throw new GLException("FBConfig null of "+toHexString(fbcfgID)); + } + if(null==glp) { + glp = GLProfile.getDefault(); + } + GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); + if(null==caps) { + throw new GLException("GLCapabilities null of "+toHexString(fbcfg)); + } + XVisualInfo xvi = GLX.glXGetVisualFromFBConfigCopied(display, fbcfg); + if(null==xvi) { + throw new GLException("XVisualInfo null of "+toHexString(fbcfg)); + } + return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser(), xvi, fbcfg, fbcfgID); + } + + public Object clone() { + return super.clone(); + } + + public long getFBConfig() { return fbConfig; } + public int getFBConfigID() { return fbConfigID; } + + protected void updateGraphicsConfiguration() { + X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(getRequestedCapabilities(), + chooser, + getScreen()); + if(null!=newConfig) { + // FIXME: setScreen( ... ); + setXVisualInfo(newConfig.getXVisualInfo()); + setChosenCapabilities(newConfig.getChosenCapabilities()); + fbConfig = newConfig.getFBConfig(); + fbConfigID = newConfig.getFBConfigID(); + if(DEBUG) { + System.err.println("!!! updateGraphicsConfiguration: "+this); + } + } + } + + private static int nonZeroOrDontCare(int value) { + return value != 0 ? value : (int)GLX.GLX_DONT_CARE ; + } + + public static int[] GLCapabilities2AttribList(GLCapabilities caps, + boolean forFBAttr, + boolean isMultisampleAvailable, + long display, + int screen) + { + int colorDepth = (caps.getRedBits() + + caps.getGreenBits() + + caps.getBlueBits()); + if (colorDepth < 15) { + throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); + } + int[] res = new int[MAX_ATTRIBS]; + int idx = 0; + + if (forFBAttr) { + res[idx++] = GLX.GLX_DRAWABLE_TYPE; + res[idx++] = caps.isOnscreen() ? ( GLX.GLX_WINDOW_BIT ) : ( caps.isPBuffer() ? GLX.GLX_PBUFFER_BIT : GLX.GLX_PIXMAP_BIT ) ; + } + + if (forFBAttr) { + res[idx++] = GLX.GLX_RENDER_TYPE; + res[idx++] = GLX.GLX_RGBA_BIT; + } else { + res[idx++] = GLX.GLX_RGBA; + } + + // FIXME: Still a bug is Mesa: PBUFFER && GLX_STEREO==GL_FALSE ? + if (forFBAttr) { + res[idx++] = GLX.GLX_DOUBLEBUFFER; + res[idx++] = caps.getDoubleBuffered()?GL.GL_TRUE:GL.GL_FALSE; + res[idx++] = GLX.GLX_STEREO; + res[idx++] = caps.getStereo()?GL.GL_TRUE:GL.GL_FALSE; + res[idx++] = GLX.GLX_TRANSPARENT_TYPE; + res[idx++] = caps.isBackgroundOpaque()?GLX.GLX_NONE:GLX.GLX_TRANSPARENT_RGB; + if(!caps.isBackgroundOpaque()) { + res[idx++] = GLX.GLX_TRANSPARENT_RED_VALUE; + res[idx++] = caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():(int)GLX.GLX_DONT_CARE; + res[idx++] = GLX.GLX_TRANSPARENT_GREEN_VALUE; + res[idx++] = caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():(int)GLX.GLX_DONT_CARE; + res[idx++] = GLX.GLX_TRANSPARENT_BLUE_VALUE; + res[idx++] = caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():(int)GLX.GLX_DONT_CARE; + res[idx++] = GLX.GLX_TRANSPARENT_ALPHA_VALUE; + res[idx++] = caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():(int)GLX.GLX_DONT_CARE; + } + } else { + if (caps.getDoubleBuffered()) { + res[idx++] = GLX.GLX_DOUBLEBUFFER; + } + if (caps.getStereo()) { + res[idx++] = GLX.GLX_STEREO; + } + } + + res[idx++] = GLX.GLX_RED_SIZE; + res[idx++] = caps.getRedBits(); + res[idx++] = GLX.GLX_GREEN_SIZE; + res[idx++] = caps.getGreenBits(); + res[idx++] = GLX.GLX_BLUE_SIZE; + res[idx++] = caps.getBlueBits(); + res[idx++] = GLX.GLX_ALPHA_SIZE; + res[idx++] = caps.getAlphaBits(); + res[idx++] = GLX.GLX_DEPTH_SIZE; + res[idx++] = caps.getDepthBits(); + if (caps.getStencilBits() > 0) { + res[idx++] = GLX.GLX_STENCIL_SIZE; + res[idx++] = caps.getStencilBits(); + } + if (caps.getAccumRedBits() > 0 || + caps.getAccumGreenBits() > 0 || + caps.getAccumBlueBits() > 0 || + caps.getAccumAlphaBits() > 0) { + res[idx++] = GLX.GLX_ACCUM_RED_SIZE; + res[idx++] = caps.getAccumRedBits(); + res[idx++] = GLX.GLX_ACCUM_GREEN_SIZE; + res[idx++] = caps.getAccumGreenBits(); + res[idx++] = GLX.GLX_ACCUM_BLUE_SIZE; + res[idx++] = caps.getAccumBlueBits(); + res[idx++] = GLX.GLX_ACCUM_ALPHA_SIZE; + res[idx++] = caps.getAccumAlphaBits(); + } + if (isMultisampleAvailable && caps.getSampleBuffers()) { + res[idx++] = GLX.GLX_SAMPLE_BUFFERS; + res[idx++] = GL.GL_TRUE; + res[idx++] = GLX.GLX_SAMPLES; + res[idx++] = caps.getNumSamples(); + } + if (caps.isPBuffer()) { + if (caps.getPbufferFloatingPointBuffers()) { + String glXExtensions = GLX.glXQueryExtensionsString(display, screen); + if (glXExtensions == null || + glXExtensions.indexOf("GLX_NV_float_buffer") < 0) { + throw new GLException("Floating-point pbuffers on X11 currently require NVidia hardware: "+glXExtensions); + } + res[idx++] = GLXExt.GLX_FLOAT_COMPONENTS_NV; + res[idx++] = GL.GL_TRUE; + } + } + res[idx++] = 0; + return res; + } + + // FBConfig + + public static boolean GLXFBConfigValid(long display, long fbcfg) { + int[] tmp = new int[1]; + if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0)) { + return false; + } + return true; + } + + public static boolean GLXFBConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { + boolean res; + + if ( onscreen ) { + res = ( 0 != (val & GLX.GLX_WINDOW_BIT) ) ; + } else { + if ( usePBuffer ) { + res = ( 0 != (val & GLX.GLX_PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & GLX.GLX_PIXMAP_BIT) ) ; + } + } + + return res; + } + + public static GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg, + boolean relaxed, boolean onscreen, boolean usePBuffer, boolean isMultisampleEnabled) { + int[] tmp = new int[1]; + int val; + val = glXGetFBConfig(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0); + if (val != GLX.GLX_RGBA_BIT) { + if(DEBUG) { + System.err.println("FBConfig ("+toHexString(fbcfg)+") does not support RGBA: "+toHexString(val)); + } + return null; + } + GLCapabilities res = new GLCapabilities(glp); + + val = glXGetFBConfig(display, fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0); + if(GLXFBConfigDrawableTypeVerify(val, onscreen, usePBuffer)) { + res.setOnscreen(onscreen); + res.setPBuffer(usePBuffer); + } else if(relaxed) { + res.setOnscreen( 0 != (val & GLX.GLX_WINDOW_BIT) ); + res.setPBuffer ( 0 != (val & GLX.GLX_PBUFFER_BIT) ); + } else { + if(DEBUG) { + System.err.println("FBConfig ("+toHexString(fbcfg)+") GLX_DRAWABLE_TYPE does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (val & GLX.GLX_WINDOW_BIT) )+", pbuffer "+( 0 != (val & GLX.GLX_PBUFFER_BIT) )+", pixmap "+( 0 != (val & GLX.GLX_PIXMAP_BIT) )+")"); + } + return null; + } + res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); + res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0); + res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG); + res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0)); + res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0)); + res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0)); + res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0)); + res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0)); + res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0)); + res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); + res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); + res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); + res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); + if (isMultisampleEnabled) { + res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); + res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); + } + res.setBackgroundOpaque(glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_TYPE, tmp, 0) == GLX.GLX_NONE); + if(!res.isBackgroundOpaque()) { + glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_RED_VALUE, tmp, 0); + res.setTransparentRedValue(tmp[0]==GLX.GLX_DONT_CARE?-1:tmp[0]); + + glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_GREEN_VALUE, tmp, 0); + res.setTransparentGreenValue(tmp[0]==GLX.GLX_DONT_CARE?-1:tmp[0]); + + glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_BLUE_VALUE, tmp, 0); + res.setTransparentBlueValue(tmp[0]==GLX.GLX_DONT_CARE?-1:tmp[0]); + + glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_ALPHA_VALUE, tmp, 0); + res.setTransparentAlphaValue(tmp[0]==GLX.GLX_DONT_CARE?-1:tmp[0]); + } + try { + res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); + } catch (Exception e) {} + return res; + } + + private static String glXGetFBConfigErrorCode(int err) { + switch (err) { + case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION"; + case GLX.GLX_BAD_ATTRIBUTE: return "GLX_BAD_ATTRIBUTE"; + default: return "Unknown error code " + err; + } + } + + public static int glXGetFBConfig(long display, long cfg, int attrib, int[] tmp, int tmp_offset) { + if (display == 0) { + throw new GLException("No display connection"); + } + int res = GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp, tmp_offset); + if (res != 0) { + throw new GLException("glXGetFBConfig("+toHexString(attrib)+") failed: error code " + glXGetFBConfigErrorCode(res)); + } + return tmp[tmp_offset]; + } + + public static int glXFBConfig2FBConfigID(long display, long cfg) { + int[] tmpID = new int[1]; + return glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID, 0); + } + + public static long glXFBConfigID2FBConfig(long display, int screen, int id) { + int[] attribs = new int[] { GLX.GLX_FBCONFIG_ID, id, 0 }; + int[] count = { -1 }; + PointerBuffer fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { + return 0; + } + return fbcfgsL.get(0); + } + + // Visual Info + + public static XVisualInfo XVisualID2XVisualInfo(long display, long visualID) { + XVisualInfo res = null; + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try{ + int[] count = new int[1]; + XVisualInfo template = XVisualInfo.create(); + template.setVisualid(visualID); + XVisualInfo[] infos = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualIDMask, template, count, 0); + if (infos == null || infos.length == 0) { + return null; + } + res = XVisualInfo.create(infos[0]); + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + if (DEBUG) { + System.err.println("!!! Fetched XVisualInfo for visual ID " + toHexString(visualID)); + System.err.println("!!! Resulting XVisualInfo: visualid = " + toHexString(res.getVisualid())); + } + return res; + } + + public static GLCapabilities XVisualInfo2GLCapabilities(GLProfile glp, long display, XVisualInfo info, boolean onscreen, boolean usePBuffer, boolean isMultisampleEnabled) { + int[] tmp = new int[1]; + int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp, 0); + if (val == 0) { + if(DEBUG) { + System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support OpenGL"); + } + return null; + } + val = glXGetConfig(display, info, GLX.GLX_RGBA, tmp, 0); + if (val == 0) { + if(DEBUG) { + System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support RGBA"); + } + return null; + } + GLCapabilities res = new GLCapabilities(glp); + res.setOnscreen (onscreen); + res.setPBuffer (usePBuffer); + res.setDoubleBuffered(glXGetConfig(display, info, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); + res.setStereo (glXGetConfig(display, info, GLX.GLX_STEREO, tmp, 0) != 0); + // Note: use of hardware acceleration is determined by + // glXCreateContext, not by the XVisualInfo. Optimistically claim + // that all GLCapabilities have the capability to be hardware + // accelerated. + res.setHardwareAccelerated(true); + res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0)); + res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0)); + res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0)); + res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0)); + res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0)); + res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0)); + res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); + res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); + res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); + res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); + if (isMultisampleEnabled) { + res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); + res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp, 0)); + } + return res; + } + + private static String glXGetConfigErrorCode(int err) { + switch (err) { + case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION"; + case GLX.GLX_BAD_SCREEN: return "GLX_BAD_SCREEN"; + case GLX.GLX_BAD_ATTRIBUTE: return "GLX_BAD_ATTRIBUTE"; + case GLX.GLX_BAD_VISUAL: return "GLX_BAD_VISUAL"; + default: return "Unknown error code " + err; + } + } + + public static int glXGetConfig(long display, XVisualInfo info, int attrib, int[] tmp, int tmp_offset) { + if (display == 0) { + throw new GLException("No display connection"); + } + int res = GLX.glXGetConfig(display, info, attrib, tmp, tmp_offset); + if (res != 0) { + throw new GLException("glXGetConfig("+toHexString(attrib)+") failed: error code " + glXGetConfigErrorCode(res)); + } + return tmp[tmp_offset]; + } + + public static String toHexString(int val) { + return "0x"+Integer.toHexString(val); + } + + public static String toHexString(long val) { + return "0x"+Long.toHexString(val); + } + + public String toString() { + return "X11GLXGraphicsConfiguration["+getScreen()+", visualID " + toHexString(getVisualID()) + ", fbConfigID " + toHexString(fbConfigID) + + ",\n\trequested " + getRequestedCapabilities()+ + ",\n\tchosen " + getChosenCapabilities()+ + "]"; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java new file mode 100644 index 000000000..e65fb5e90 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import com.jogamp.common.nio.PointerBuffer; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import com.jogamp.nativewindow.impl.x11.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on X11 platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + + public X11GLXGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.x11.X11GraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + return chooseGraphicsConfigurationStatic(capabilities, chooser, absScreen); + } + + /** + protected static X11GLXGraphicsConfiguration createDefaultGraphicsConfigurationFBConfig(AbstractGraphicsScreen absScreen, boolean onscreen, boolean usePBuffer) { + if (absScreen == null) { + throw new IllegalArgumentException("AbstractGraphicsScreen is null"); + } + if (!(absScreen instanceof X11GraphicsScreen)) { + throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here"); + } + X11GraphicsScreen x11Screen = (X11GraphicsScreen)absScreen; + + GLProfile glProfile = GLProfile.getDefault(); + GLCapabilities caps=null; + XVisualInfo xvis=null; + long fbcfg = 0; + int fbid = -1; + + // Utilizing FBConfig + // + GLCapabilities capsFB = null; + long display = x11Screen.getDevice().getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + X11Lib.XLockDisplay(display); + try { + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + + long visID = X11Lib.DefaultVisualID(display, x11Screen.getIndex()); + xvis = X11GLXGraphicsConfiguration.XVisualID2XVisualInfo(display, visID); + caps = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, xvis, onscreen, usePBuffer, isMultisampleAvailable); + + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(caps, true, isMultisampleAvailable, display, screen); + int[] count = { -1 }; + PointerBuffer fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { + throw new Exception("Could not fetch FBConfig for "+caps); + } + fbcfg = fbcfgsL.get(0); + capsFB = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfg, true, onscreen, usePBuffer, isMultisampleAvailable); + + fbid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg); + + xvis = GLX.glXGetVisualFromFBConfigCopied(display, fbcfg); + if (xvis==null) { + throw new GLException("Error: Choosen FBConfig has no visual"); + } + } catch (Throwable t) { + } finally { + X11Lib.XUnlockDisplay(display); + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + + return new X11GLXGraphicsConfiguration(x11Screen, (null!=capsFB)?capsFB:caps, caps, null, xvis, fbcfg, fbid); + } */ + + protected static X11GLXGraphicsConfiguration chooseGraphicsConfigurationStatic(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if (absScreen == null) { + throw new IllegalArgumentException("AbstractGraphicsScreen is null"); + } + if (!(absScreen instanceof X11GraphicsScreen)) { + throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here"); + } + X11GraphicsScreen x11Screen = (X11GraphicsScreen)absScreen; + + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + + if (capabilities == null) { + capabilities = new GLCapabilities(null); + } + + boolean onscreen = capabilities.isOnscreen(); + boolean usePBuffer = ((GLCapabilities)capabilities).isPBuffer(); + + GLCapabilities caps2 = (GLCapabilities) capabilities.clone(); + if(!caps2.isOnscreen()) { + // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN + caps2.setDoubleBuffered(false); + } + + X11GLXGraphicsConfiguration res; + res = chooseGraphicsConfigurationFBConfig((GLCapabilities) caps2, + (GLCapabilitiesChooser) chooser, + x11Screen); + if(null==res) { + if(usePBuffer) { + throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for "+caps2); + } + res = chooseGraphicsConfigurationXVisual((GLCapabilities) caps2, + (GLCapabilitiesChooser) chooser, + x11Screen); + } + if(null==res) { + throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for "+caps2); + } + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic("+x11Screen+","+caps2+"): "+res); + } + return res; + } + + protected static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + X11GraphicsScreen x11Screen) { + long recommendedFBConfig = 0; + int recommendedIndex = -1; + GLCapabilities[] caps = null; + PointerBuffer fbcfgsL = null; + int chosen=-1; + int retFBID=-1; + XVisualInfo retXVisualInfo = null; + GLProfile glProfile = capabilities.getGLProfile(); + boolean onscreen = capabilities.isOnscreen(); + boolean usePBuffer = capabilities.isPBuffer(); + + // Utilizing FBConfig + // + AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + long display = absDevice.getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + X11Lib.XLockDisplay(display); + try{ + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, true, isMultisampleAvailable, display, screen); + int[] count = { -1 }; + + // determine the recommended FBConfig .. + fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXChooseFBConfig ("+x11Screen+","+capabilities+"): "+fbcfgsL+", "+count[0]); + } + } else if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(0) ) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed - GLX FBConfig invalid: ("+x11Screen+","+capabilities+"): "+fbcfgsL+", fbcfg: "+toHexString(fbcfgsL.get(0))); + } + } else { + recommendedFBConfig = fbcfgsL.get(0); + } + + // get all, glXChooseFBConfig(.. attribs==null ..) == glXGetFBConfig(..) + fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, null, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXGetFBConfig ("+x11Screen+"): "+fbcfgsL+", "+count[0]); + } + return null; + } + + // make GLCapabilities and seek the recommendedIndex + caps = new GLCapabilities[fbcfgsL.limit()]; + for (int i = 0; i < fbcfgsL.limit(); i++) { + if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(i) ) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid: ("+x11Screen+","+capabilities+"): fbcfg: "+toHexString(fbcfgsL.get(i))); + } + } else { + caps[i] = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfgsL.get(i), + false, onscreen, usePBuffer, isMultisampleAvailable); + if(caps[i]!=null && recommendedFBConfig==fbcfgsL.get(i)) { + recommendedIndex=i; + if (DEBUG) { + System.err.println("!!! glXChooseFBConfig recommended "+i+", "+caps[i]); + } + } + } + } + + if(null==chooser) { + chosen = recommendedIndex; // may still be -1 in case nothing was recommended (-1) + } + + if (chosen < 0) { + if(null==chooser) { + // nothing recommended .. so use our default implementation + chooser = new DefaultGLCapabilitiesChooser(); + } + try { + chosen = chooser.chooseCapabilities(capabilities, caps, recommendedIndex); + } catch (NativeWindowException e) { + if(DEBUG) { + e.printStackTrace(); + } + chosen = -1; + } + } + if (chosen < 0) { + // keep on going .. + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig Failed .. unable to choose config, using first"); + } + // seek first available one .. + for(chosen = 0; chosen < caps.length && caps[chosen]==null; chosen++) ; + if(chosen==caps.length) { + // give up .. + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig Failed .. nothing available, bail out"); + } + return null; + } + } else if (chosen >= caps.length) { + if(DEBUG) { + System.err.println("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ", got "+chosen+")"); + } + return null; + } + + retFBID = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfgsL.get(chosen)); + + retXVisualInfo = GLX.glXGetVisualFromFBConfigCopied(display, fbcfgsL.get(chosen)); + if (retXVisualInfo==null) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXGetVisualFromFBConfig ("+x11Screen+", "+fbcfgsL.get(chosen) +" (Continue: "+(false==caps[chosen].isOnscreen())+"):\n\t"+caps[chosen]); + } + if(caps[chosen].isOnscreen()) { + // Onscreen drawables shall have a XVisual .. + return null; + } + } + }finally{ + X11Lib.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + + return new X11GLXGraphicsConfiguration(x11Screen, caps[chosen], capabilities, chooser, retXVisualInfo, fbcfgsL.get(chosen), retFBID); + } + + protected static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + X11GraphicsScreen x11Screen) { + if (chooser == null) { + chooser = new DefaultGLCapabilitiesChooser(); + } + + // Until we have a rock-solid visual selection algorithm written + // in pure Java, we're going to provide the underlying window + // system's selection to the chooser as a hint + + GLProfile glProfile = capabilities.getGLProfile(); + boolean onscreen = capabilities.isOnscreen(); + GLCapabilities[] caps = null; + int recommendedIndex = -1; + XVisualInfo retXVisualInfo = null; + int chosen=-1; + + AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + long display = absDevice.getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + X11Lib.XLockDisplay(display); + try{ + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, false, isMultisampleAvailable, display, screen); + XVisualInfo[] infos = null; + + XVisualInfo recommendedVis = GLX.glXChooseVisualCopied(display, screen, attribs, 0); + if (DEBUG) { + System.err.print("!!! glXChooseVisual recommended "); + if (recommendedVis == null) { + System.err.println("null visual"); + } else { + System.err.println("visual id " + toHexString(recommendedVis.getVisualid())); + } + } + int[] count = new int[1]; + XVisualInfo template = XVisualInfo.create(); + template.setScreen(screen); + infos = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualScreenMask, template, count, 0); + if (infos == null || infos.length<1) { + throw new GLException("Error while enumerating available XVisualInfos"); + } + caps = new GLCapabilities[infos.length]; + for (int i = 0; i < infos.length; i++) { + caps[i] = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, infos[i], onscreen, false, isMultisampleAvailable); + // Attempt to find the visual chosen by glXChooseVisual + if (recommendedVis != null && recommendedVis.getVisualid() == infos[i].getVisualid()) { + recommendedIndex = i; + } + } + try { + chosen = chooser.chooseCapabilities(capabilities, caps, recommendedIndex); + } catch (NativeWindowException e) { + if(DEBUG) { + e.printStackTrace(); + } + chosen = -1; + } + if (chosen < 0) { + // keep on going .. + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual Failed .. unable to choose config, using first"); + } + chosen = 0; // default .. + } else if (chosen >= caps.length) { + throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")"); + } + if (infos[chosen] == null) { + throw new GLException("GLCapabilitiesChooser chose an invalid visual for "+caps[chosen]); + } + retXVisualInfo = XVisualInfo.create(infos[chosen]); + }finally{ + X11Lib.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + return new X11GLXGraphicsConfiguration(x11Screen, caps[chosen], capabilities, chooser, retXVisualInfo, 0, -1); + } + + public static String toHexString(int val) { + return "0x"+Integer.toHexString(val); + } + + public static String toHexString(long val) { + return "0x"+Long.toHexString(val); + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXContext.java new file mode 100644 index 000000000..bea953ee9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXContext.java @@ -0,0 +1,77 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.*; + +public class X11OffscreenGLXContext extends X11GLXContext { + private X11OffscreenGLXDrawable drawable; + + public X11OffscreenGLXContext(X11OffscreenGLXDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + public int getOffscreenContextPixelDataType() { + GL gl = getGL(); + return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1; + } + + public int getOffscreenContextReadBuffer() { + GLCapabilities caps = (GLCapabilities)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + if (caps.getDoubleBuffered()) { + return GL.GL_BACK; + } + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + // There doesn't seem to be a way to do this in the construction + // of the Pixmap or GLXPixmap + return true; + } + + protected void create() { + createContext(false); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java new file mode 100644 index 000000000..14d07e74f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java @@ -0,0 +1,157 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11OffscreenGLXDrawable extends X11GLXDrawable { + private long pixmap; + + protected X11OffscreenGLXDrawable(GLDrawableFactory factory, NativeWindow target) { + super(factory, target, true); + create(); + } + + protected void setRealizedImpl() { + if(realized) { + create(); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new X11OffscreenGLXContext(this, shareWith); + } + + private void create() { + NativeWindow nw = getNativeWindow(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + XVisualInfo vis = config.getXVisualInfo(); + int bitsPerPixel = vis.getDepth(); + AbstractGraphicsScreen aScreen = config.getScreen(); + AbstractGraphicsDevice aDevice = aScreen.getDevice(); + long dpy = aDevice.getHandle(); + int screen = aScreen.getIndex(); + + getFactoryImpl().lockToolkit(); + try { + X11Lib.XLockDisplay(dpy); + try{ + + pixmap = X11Lib.XCreatePixmap(dpy, X11Lib.RootWindow(dpy, screen), + component.getWidth(), component.getHeight(), bitsPerPixel); + if (pixmap == 0) { + throw new GLException("XCreatePixmap failed"); + } + long drawable = GLX.glXCreateGLXPixmap(dpy, vis, pixmap); + if (drawable == 0) { + X11Lib.XFreePixmap(dpy, pixmap); + pixmap = 0; + throw new GLException("glXCreateGLXPixmap failed"); + } + ((SurfaceChangeable)nw).setSurfaceHandle(drawable); + if (DEBUG) { + System.err.println("Created pixmap " + toHexString(pixmap) + + ", GLXPixmap " + toHexString(drawable) + + ", display " + toHexString(dpy)); + } + }finally{ + X11Lib.XUnlockDisplay(dpy); + } + } finally { + getFactoryImpl().unlockToolkit(); + } + } + + public void destroy() { + if (pixmap == 0) return; + + NativeWindow nw = getNativeWindow(); + long display = nw.getDisplayHandle(); + + getFactoryImpl().lockToolkit(); + try { + X11Lib.XLockDisplay(display); + try{ + long drawable = nw.getSurfaceHandle(); + if (DEBUG) { + System.err.println("Destroying pixmap " + toHexString(pixmap) + + ", GLXPixmap " + toHexString(drawable) + + ", display " + toHexString(display)); + } + + // Must destroy pixmap and GLXPixmap + + if (DEBUG) { + long cur = GLX.glXGetCurrentContext(); + if (cur != 0) { + System.err.println("WARNING: found context " + toHexString(cur) + " current during pixmap destruction"); + } + } + + // FIXME: workaround for crashes on NVidia hardware when + // destroying pixmap (no context is current at the point of the + // crash, at least from the point of view of + // glXGetCurrentContext) + GLX.glXMakeCurrent(display, 0, 0); + + GLX.glXDestroyGLXPixmap(display, drawable); + X11Lib.XFreePixmap(display, pixmap); + drawable = 0; + pixmap = 0; + ((SurfaceChangeable)nw).setSurfaceHandle(0); + + }finally{ + X11Lib.XUnlockDisplay(display); + } + } finally { + getFactoryImpl().unlockToolkit(); + display = 0; + } + } + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXContext.java new file mode 100644 index 000000000..c89a5efd5 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXContext.java @@ -0,0 +1,68 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.*; + +public class X11OnscreenGLXContext extends X11GLXContext { + // This indicates whether the context we have created is indirect + // and therefore requires the toolkit to be locked around all GL + // calls rather than just all GLX calls + protected boolean isIndirect; + + public X11OnscreenGLXContext(X11OnscreenGLXDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + } + + public boolean isOptimizable() { + return super.isOptimizable() && !isIndirect; + } + + protected void create() { + createContext(true); + isIndirect = !GLX.glXIsDirect(drawable.getNativeWindow().getDisplayHandle(), context); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXDrawable.java new file mode 100644 index 000000000..43468b858 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXDrawable.java @@ -0,0 +1,64 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.*; + +public class X11OnscreenGLXDrawable extends X11GLXDrawable { + protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, false); + } + + public GLContext createContext(GLContext shareWith) { + return new X11OnscreenGLXContext(this, shareWith); + } + + public int getWidth() { + return component.getWidth(); + } + + public int getHeight() { + return component.getHeight(); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXContext.java new file mode 100644 index 000000000..1b70adf6b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXContext.java @@ -0,0 +1,73 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.*; + +public class X11PbufferGLXContext extends X11GLXContext { + private X11PbufferGLXDrawable drawable; + + public X11PbufferGLXContext(X11PbufferGLXDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + public void bindPbufferToTexture() { + // FIXME: figure out how to implement this + throw new GLException("Not yet implemented"); + } + + public void releasePbufferFromTexture() { + // FIXME: figure out how to implement this + throw new GLException("Not yet implemented"); + } + + + public int getFloatingPointMode() { + return drawable.getFloatingPointMode(); + } + + protected void create() { + createContext(true); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java new file mode 100644 index 000000000..50b32b9ec --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java @@ -0,0 +1,157 @@ +/* + * 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. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.glx.*; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11PbufferGLXDrawable extends X11GLXDrawable { + protected X11PbufferGLXDrawable(GLDrawableFactory factory, NativeWindow target) { + /* GLCapabilities caps, + GLCapabilitiesChooser chooser, + int width, int height */ + super(factory, target, true); + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + createPbuffer(); + + if (DEBUG) { + System.err.println("Created pbuffer " + this); + } + } + + protected void setRealizedImpl() { + if(realized) { + createPbuffer(); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new X11PbufferGLXContext(this, shareWith); + } + + public void destroy() { + getFactoryImpl().lockToolkit(); + try { + NativeWindow nw = getNativeWindow(); + if (nw.getSurfaceHandle() != 0) { + GLX.glXDestroyPbuffer(nw.getDisplayHandle(), nw.getSurfaceHandle()); + } + ((SurfaceChangeable)nw).setSurfaceHandle(0); + } finally { + getFactoryImpl().unlockToolkit(); + } + } + + private void createPbuffer() { + getFactoryImpl().lockToolkit(); + try { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsScreen aScreen = config.getScreen(); + AbstractGraphicsDevice aDevice = aScreen.getDevice(); + long display = aDevice.getHandle(); + int screen = aScreen.getIndex(); + + if (display==0) { + throw new GLException("Null display"); + } + + NativeWindow nw = getNativeWindow(); + + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + + if (capabilities.getPbufferRenderToTexture()) { + throw new GLException("Render-to-texture pbuffers not supported yet on X11"); + } + + if (capabilities.getPbufferRenderToTextureRectangle()) { + throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11"); + } + + // Create the p-buffer. + int niattribs = 0; + int[] iattributes = new int[5]; + + iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH; + iattributes[niattribs++] = nw.getWidth(); + iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT; + iattributes[niattribs++] = nw.getHeight(); + iattributes[niattribs++] = 0; + + long pbuffer = GLX.glXCreatePbuffer(display, config.getFBConfig(), iattributes, 0); + if (pbuffer == 0) { + // FIXME: query X error code for detail error message + throw new GLException("pbuffer creation error: glXCreatePbuffer() failed"); + } + + // Set up instance variables + ((SurfaceChangeable)nw).setSurfaceHandle(pbuffer); + + // Determine the actual width and height we were able to create. + int[] tmp = new int[1]; + GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_WIDTH, tmp, 0); + int width = tmp[0]; + GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_HEIGHT, tmp, 0); + int height = tmp[0]; + ((SurfaceChangeable)nw).setSize(width, height); + } finally { + getFactoryImpl().unlockToolkit(); + } + } + + public int getFloatingPointMode() { + // Floating-point pbuffers currently require NVidia hardware on X11 + return GLPbuffer.NV_FLOAT; + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java new file mode 100644 index 000000000..dc6c60664 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2008 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. + */ + +package com.jogamp.opengl.impl.x11.glx.awt; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.nativewindow.awt.*; +import javax.media.opengl.*; +import javax.media.opengl.awt.*; + +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.x11.*; +import com.jogamp.nativewindow.impl.x11.*; +import com.jogamp.opengl.impl.x11.*; +import com.jogamp.opengl.impl.x11.glx.*; + +public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + + public X11AWTGLXGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GraphicsDevice device = null; + if (absScreen != null && + !(absScreen instanceof AWTGraphicsScreen)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); + } + + if(null==absScreen) { + absScreen = AWTGraphicsScreen.createScreenDevice(-1); + } + AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; + device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilitiesChooser objects"); + } + + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: got "+absScreen); + } + + GraphicsConfiguration gc; + X11GraphicsConfiguration x11Config; + + // Need the lock here, since it could be an AWT owned display connection + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + long displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(device); + if(0==displayHandle) { + displayHandle = X11Util.createThreadLocalDefaultDisplay(); + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: using a thread local X11 display"); + } + } else { + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: using AWT X11 display 0x"+Long.toHexString(displayHandle)); + } + } + ((AWTGraphicsDevice)awtScreen.getDevice()).setHandle(displayHandle); + X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle); + + X11GraphicsScreen x11Screen = new X11GraphicsScreen(x11Device, awtScreen.getIndex()); + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: made "+x11Screen); + } + + gc = device.getDefaultConfiguration(); + AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capabilities, gc); + if(DEBUG) { + System.err.println("AWT Colormodel compatible: "+capabilities); + } + + x11Config = (X11GraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(x11Device).chooseGraphicsConfiguration(capabilities, + chooser, + x11Screen); + if (x11Config == null) { + throw new GLException("Unable to choose a GraphicsConfiguration: "+capabilities+",\n\t"+chooser+"\n\t"+x11Screen); + } + + long visualID = x11Config.getVisualID(); + // Now figure out which GraphicsConfiguration corresponds to this + // visual by matching the visual ID + GraphicsConfiguration[] configs = device.getConfigurations(); + for (int i = 0; i < configs.length; i++) { + GraphicsConfiguration config = configs[i]; + if (config != null) { + if (X11SunJDKReflection.graphicsConfigurationGetVisualID(config) == visualID) { + return new AWTGraphicsConfiguration(awtScreen, x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), + config, x11Config); + } + } + } + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + // Either we weren't able to reflectively introspect on the + // X11GraphicsConfig or something went wrong in the steps above; + // Let's take the default configuration as used on Windows and MacOSX then .. + if(DEBUG) { + System.err.println("!!! Using default configuration"); + } + return new AWTGraphicsConfiguration(awtScreen, x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), gc, x11Config); + } +} |