diff options
author | Kevin Rushforth <[email protected]> | 2006-09-29 18:04:13 +0000 |
---|---|---|
committer | Kevin Rushforth <[email protected]> | 2006-09-29 18:04:13 +0000 |
commit | 908d0fbb2ea26226165cd42f12abf0d27e4a3f53 (patch) | |
tree | 0258d2293efab8f4eafba39a528a3d2eedd0c3cb /src/classes | |
parent | 0661a22dd9278b20856b13b08ff22d248119cf6b (diff) |
Merged dev-1_5 branch back to MAIN trunk
git-svn-id: https://svn.java.net/svn/j3d-core~svn/trunk@701 ba19aa83-45c5-6ac9-afd3-db810772062c
Diffstat (limited to 'src/classes')
172 files changed, 27235 insertions, 10124 deletions
diff --git a/src/classes/J3dVersion b/src/classes/J3dVersion index cc882bb..c6c433a 100644 --- a/src/classes/J3dVersion +++ b/src/classes/J3dVersion @@ -1,6 +1,6 @@ Manifest-Version: 1.0 Specification-Title: Java 3D API Specification -Specification-Version: 1.4 +Specification-Version: 1.5 Specification-Vendor: Sun Microsystems, Inc. Implementation-Title: Java 3D Core Runtime Environment Implementation-Version: @VERSION_BASE@ diff --git a/src/classes/build.xml b/src/classes/build.xml index 8a81c3c..df60201 100644 --- a/src/classes/build.xml +++ b/src/classes/build.xml @@ -15,7 +15,7 @@ --> <!-- Ant file for building java classes and jar files --> -<project name="Java 3D" default="jar-opt"> +<project name="Java 3D" default="jar-debug"> <path id="vecmath.debug.classpath"> <pathelement location="${vecmath_home}/build/debug/lib/ext/vecmath.jar"/> @@ -53,12 +53,13 @@ </copy> <!-- Compile the java code from ${src} into ${build}/${platform}/debug/classes --> - <javac srcdir="${src}/classes/share:${src}/classes/${ostype}:${core_utils_src}/classes/share:${build-debug-gen}/classes" + <javac srcdir="${src}/classes/share:${src}/classes/${wstype}:${jogl.pipeline.srcdir}:${core_utils_src}/classes/share:${build-debug-gen}/classes" destdir="${build}/${platform}/debug/classes" - source="1.4" - target="1.4" + source="1.5" + target="1.5" debug="true" - deprecation="off"> + deprecation="off" + excludes="${javac.excludes}"> <classpath refid="vecmath.debug.classpath"/> </javac> @@ -97,12 +98,13 @@ </copy> <!-- Compile the java code from ${src} into ${build}/${platform}/opt/classes --> - <javac srcdir="${src}/classes/share:${src}/classes/${ostype}:${core_utils_src}/classes/share:${build-opt-gen}/classes" destdir="${build}/${platform}/opt/classes" - source="1.4" - target="1.4" + <javac srcdir="${src}/classes/share:${src}/classes/${wstype}:${jogl.pipeline.srcdir}:${core_utils_src}/classes/share:${build-opt-gen}/classes" destdir="${build}/${platform}/opt/classes" + source="1.5" + target="1.5" debug="true" debuglevel="lines,source" - deprecation="off"> + deprecation="off" + excludes="${javac.excludes}"> <classpath refid="vecmath.opt.classpath"/> </javac> @@ -113,7 +115,10 @@ </copy> </target> - <target name="jar-debug"> + + <target name="jar-debug" depends="jar-debug-impl,copy-default-debug"/> + + <target name="jar-debug-impl"> <!-- Create the j3dcore and j3dutils jars directory --> <mkdir dir="${build}/${platform}/debug/lib/ext"/> @@ -153,7 +158,21 @@ </jar> </target> - <target name="jar-opt"> + <target name="copy-default-debug" unless="build.concurrent"> + <!-- Copy platform-specific jar and native files to "default" directory --> + <delete dir="${build}/default/debug" quiet="true"/> + <mkdir dir="${build}/default/debug/native"/> + <copy todir="${build}/default/debug" overwrite="true"> + <fileset dir="${build}/${platform}/debug" includes="lib/ext/**/*.jar"/> + </copy> + <copy todir="${build}/default/debug/native" overwrite="true" includeemptydirs="false" flatten="true"> + <fileset dir="${build}/${platform}/debug" includes="lib/** bin/**" excludes="**/*.jar"/> + </copy> + </target> + + <target name="jar-opt" depends="jar-opt-impl,copy-default-opt"/> + + <target name="jar-opt-impl"> <!-- Create the j3dcore and j3dutils jars directory --> <mkdir dir="${build}/${platform}/opt/lib/ext"/> @@ -188,11 +207,23 @@ <!-- Put everything in ${build}/${platform}/opt/classes/com into the j3dutils.jar file --> <jar jarfile="${build}/${platform}/opt/lib/ext/j3dutils.jar" manifest="${build-opt-gen}/ToolsVersion" update="no" - compress="false"> - <fileset dir="${build}/${platform}/opt/classes" includes="com/**/*"/> + compress="false"> + <fileset dir="${build}/${platform}/opt/classes" includes="com/**/*"/> </jar> </target> + <target name="copy-default-opt" unless="build.concurrent"> + <!-- Copy platform-specific jar and native files to "default" directory --> + <delete dir="${build}/default/opt" quiet="true"/> + <mkdir dir="${build}/default/opt/native"/> + <copy todir="${build}/default/opt" overwrite="true"> + <fileset dir="${build}/${platform}/opt" includes="lib/ext/**/*.jar"/> + </copy> + <copy todir="${build}/default/opt/native" overwrite="true" includeemptydirs="false" flatten="true"> + <fileset dir="${build}/${platform}/opt" includes="lib/** bin/**" excludes="**/*.jar"/> + </copy> + </target> + <target name="setup-docs"> <property name="javadoc.bottom" value="<font size="-1">Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. Use is subject to <a href="{@docRoot}/LICENSE-SPEC.html">license terms</a>."/> @@ -211,7 +242,7 @@ windowtitle="Java 3D ${version}"> <sourcepath> <pathelement location="${src}/classes/share"/> - <pathelement location="${src}/classes/${ostype}"/> + <pathelement location="${src}/classes/${wstype}"/> <pathelement location="${core_utils_src}/classes/share"/> <pathelement location="${vecmath_src}"/> </sourcepath> @@ -253,7 +284,7 @@ windowtitle="Java 3D ${version}"> <sourcepath> <pathelement location="${src}/classes/share"/> - <pathelement location="${src}/classes/${ostype}"/> + <pathelement location="${src}/classes/${wstype}"/> <pathelement location="${build}/${platform}/opt/gen/classes"/> <pathelement location="${core_utils_src}/classes/share"/> <pathelement location="${vecmath_src}"/> @@ -274,10 +305,12 @@ <!-- Compile the javadoc from ${src} into ${build}/javadocs --> <javadoc packagenames="javax.media.j3d.*, com.sun.j3d.audioengines.*, + com.sun.j3d.exp.*, com.sun.j3d.loaders.*, com.sun.j3d.utils.*, javax.vecmath.*" excludepackagenames="com.sun.j3d.utils.scenegraph.io.retained, + com.sun.j3d.exp.swing.impl, com.sun.j3d.utils.scenegraph.io.state.*" maxmemory="128m" destdir="${build}/${platform}/javadocs/docs-public" @@ -285,7 +318,7 @@ windowtitle="Java 3D ${version}"> <sourcepath> <pathelement location="${src}/classes/share"/> - <pathelement location="${src}/classes/${ostype}"/> + <pathelement location="${src}/classes/${wstype}"/> <pathelement location="${core_utils_src}/classes/share"/> <pathelement location="${vecmath_src}"/> </sourcepath> @@ -333,8 +366,8 @@ <fileset dir="${java.home}/lib/ext" includes="j3dcore.jar, j3dutils.jar, vecmath.jar"/> </delete> <delete> - <fileset dir="${java.home}/${install.bin}" includes="libj3dcore*.so, libj3dutils.so"/> - <fileset dir="${java.home}/${install.bin}" includes="j3dcore*.dll, j3dutils.dll"/> + <fileset dir="${java.home}/${install.bin}" includes="libj3dcore*.so"/> + <fileset dir="${java.home}/${install.bin}" includes="j3dcore*.dll"/> </delete> </target> diff --git a/src/classes/jogl/javax/media/j3d/JoglCgShaderInfo.java b/src/classes/jogl/javax/media/j3d/JoglCgShaderInfo.java new file mode 100755 index 0000000..c739027 --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglCgShaderInfo.java @@ -0,0 +1,32 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import com.sun.opengl.cg.*; + +class JoglCgShaderInfo extends JoglShaderObject { + private CGprogram cgShader; + private int j3dShaderType; + private int shaderProfile; + + JoglCgShaderInfo() { + super(0); + } + + public void setCgShader(CGprogram shader) { cgShader = shader; } + public CGprogram getCgShader() { return cgShader; } + public void setJ3DShaderType(int type) { j3dShaderType = type; } + public int getJ3DShaderType() { return j3dShaderType; } + public void setShaderProfile(int shaderProfile) { this.shaderProfile = shaderProfile; } + public int getShaderProfile() { return shaderProfile; } +} diff --git a/src/classes/jogl/javax/media/j3d/JoglCgShaderParameter.java b/src/classes/jogl/javax/media/j3d/JoglCgShaderParameter.java new file mode 100755 index 0000000..f744f1d --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglCgShaderParameter.java @@ -0,0 +1,29 @@ +/* + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import com.sun.opengl.cg.*; + +class JoglCgShaderParameter extends JoglShaderObject { + private CGparameter vParam; + private CGparameter fParam; + + JoglCgShaderParameter(CGparameter vParam, + CGparameter fParam) { + super(0); + this.vParam = vParam; + this.fParam = fParam; + } + + CGparameter vParam() { + return vParam; + } + + CGparameter fParam() { + return fParam; + } +} diff --git a/src/classes/jogl/javax/media/j3d/JoglCgShaderProgramInfo.java b/src/classes/jogl/javax/media/j3d/JoglCgShaderProgramInfo.java new file mode 100755 index 0000000..fe88cf1 --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglCgShaderProgramInfo.java @@ -0,0 +1,38 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import com.sun.opengl.cg.*; + +class JoglCgShaderProgramInfo extends JoglShaderObject { + private JoglCgShaderInfo vShader; // vertex shader + private JoglCgShaderInfo fShader; // fragment shader + // Array of parameters for (varying) vertex attributes + private CGparameter[] vtxAttrs; + + JoglCgShaderProgramInfo() { + super(0); + } + + public JoglCgShaderInfo getVertexShader() { return vShader; } + public void setVertexShader(JoglCgShaderInfo info) { vShader = info; } + public JoglCgShaderInfo getFragmentShader() { return fShader; } + public void setFragmentShader(JoglCgShaderInfo info) { fShader = info; } + public CGparameter[] getVertexAttributes() { return vtxAttrs; } + public void setVertexAttributes(CGparameter[] attrs) { vtxAttrs = attrs; } + public int getNumVertexAttributes() { + if (vtxAttrs == null) + return 0; + return vtxAttrs.length; + } +} diff --git a/src/classes/jogl/javax/media/j3d/JoglContext.java b/src/classes/jogl/javax/media/j3d/JoglContext.java new file mode 100644 index 0000000..075c304 --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglContext.java @@ -0,0 +1,231 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.nio.*; +import javax.media.opengl.*; +import com.sun.opengl.cg.*; + +/** + * Graphics context objects for Jogl rendering pipeline. + */ +class JoglContext implements Context { + private GLContext context; + + // Properties we need to keep track of for efficiency + private int maxTexCoordSets; + private float alphaClearValue; + private int currentTextureUnit; + private int currentCombinerUnit; + private boolean hasMultisample; + + // Needed for vertex attribute implementation + private JoglShaderObject shaderProgram; + + // Implementation of vertex attribute methods + static interface VertexAttributeImpl { + public void vertexAttrPointer(GL gl, + int index, int size, int type, int stride, Buffer pointer); + public void enableVertexAttrArray(GL gl, int index); + public void disableVertexAttrArray(GL gl, int index); + public void vertexAttr1fv(GL gl, int index, FloatBuffer buf); + public void vertexAttr2fv(GL gl, int index, FloatBuffer buf); + public void vertexAttr3fv(GL gl, int index, FloatBuffer buf); + public void vertexAttr4fv(GL gl, int index, FloatBuffer buf); + } + private VertexAttributeImpl vertexAttrImpl; + + class CgVertexAttributeImpl implements VertexAttributeImpl { + public void vertexAttrPointer(GL gl, + int index, int size, int type, int stride, Buffer pointer) { + JoglCgShaderProgramInfo shaderProgramInfo = (JoglCgShaderProgramInfo) shaderProgram; + if (shaderProgramInfo != null && index < shaderProgramInfo.getNumVertexAttributes()) { + CgGL.cgGLSetParameterPointer(shaderProgramInfo.getVertexAttributes()[index], + size, type, stride, pointer); + } else { + if (shaderProgramInfo == null) { + System.err.println(" shaderProgramInfo is null"); + } else { + System.err.println(" index (" + index + ") out of range: numVtxAttrs = " + + shaderProgramInfo.getNumVertexAttributes()); + } + } + } + + public void enableVertexAttrArray(GL gl, int index) { + JoglCgShaderProgramInfo shaderProgramInfo = (JoglCgShaderProgramInfo) shaderProgram; + if (shaderProgramInfo != null && index < shaderProgramInfo.getNumVertexAttributes()) { + CgGL.cgGLEnableClientState(shaderProgramInfo.getVertexAttributes()[index]); + } else { + if (shaderProgramInfo == null) { + System.err.println(" shaderProgramInfo is null"); + } else { + System.err.println(" index (" + index + ") out of range: numVtxAttrs = " + + shaderProgramInfo.getNumVertexAttributes()); + } + } + } + + public void disableVertexAttrArray(GL gl, int index) { + JoglCgShaderProgramInfo shaderProgramInfo = (JoglCgShaderProgramInfo) shaderProgram; + if (shaderProgramInfo != null && index < shaderProgramInfo.getNumVertexAttributes()) { + CgGL.cgGLDisableClientState(shaderProgramInfo.getVertexAttributes()[index]); + } else { + if (shaderProgramInfo == null) { + System.err.println(" shaderProgramInfo is null"); + } else { + System.err.println(" index (" + index + ") out of range: numVtxAttrs = " + + shaderProgramInfo.getNumVertexAttributes()); + } + } + } + + // NOTE: we should never get here. These functions are only called + // when building display lists for geometry arrays with vertex + // attributes, and such display lists are disabled in Cg mode. + public void vertexAttr1fv(GL gl, int index, FloatBuffer buf) { + throw new RuntimeException("Java 3D ERROR : Assertion failed: invalid call to cgVertexAttr1fv"); + } + + public void vertexAttr2fv(GL gl, int index, FloatBuffer buf) { + throw new RuntimeException("Java 3D ERROR : Assertion failed: invalid call to cgVertexAttr2fv"); + } + + public void vertexAttr3fv(GL gl, int index, FloatBuffer buf) { + throw new RuntimeException("Java 3D ERROR : Assertion failed: invalid call to cgVertexAttr3fv"); + } + + public void vertexAttr4fv(GL gl, int index, FloatBuffer buf) { + throw new RuntimeException("Java 3D ERROR : Assertion failed: invalid call to cgVertexAttr4fv"); + } + } + + class GLSLVertexAttributeImpl implements VertexAttributeImpl { + public void vertexAttrPointer(GL gl, + int index, int size, int type, int stride, Buffer pointer) { + gl.glVertexAttribPointerARB(index + glslVertexAttrOffset, + size, type, false, stride, pointer); + } + + public void enableVertexAttrArray(GL gl, int index) { + gl.glEnableVertexAttribArrayARB(index + glslVertexAttrOffset); + } + + public void disableVertexAttrArray(GL gl, int index) { + gl.glDisableVertexAttribArrayARB(index + glslVertexAttrOffset); + } + + public void vertexAttr1fv(GL gl, int index, FloatBuffer buf) { + gl.glVertexAttrib1fvARB(index + glslVertexAttrOffset, buf); + } + + public void vertexAttr2fv(GL gl, int index, FloatBuffer buf) { + gl.glVertexAttrib2fvARB(index + glslVertexAttrOffset, buf); + } + + public void vertexAttr3fv(GL gl, int index, FloatBuffer buf) { + gl.glVertexAttrib3fvARB(index + glslVertexAttrOffset, buf); + } + + public void vertexAttr4fv(GL gl, int index, FloatBuffer buf) { + gl.glVertexAttrib4fvARB(index + glslVertexAttrOffset, buf); + } + } + + // Only used when GLSL shader library is active + private int glslVertexAttrOffset; + + // Only used when Cg shader library is active + private CGcontext cgContext; + private int cgVertexProfile; + private int cgFragmentProfile; + + JoglContext(GLContext context) { + this.context = context; + } + + GLContext getGLContext() { + return context; + } + + int getMaxTexCoordSets() { return maxTexCoordSets; } + void setMaxTexCoordSets(int val) { maxTexCoordSets = val; } + float getAlphaClearValue() { return alphaClearValue; } + void setAlphaClearValue(float val) { alphaClearValue = val; } + int getCurrentTextureUnit() { return currentTextureUnit; } + void setCurrentTextureUnit(int val) { currentTextureUnit = val; } + int getCurrentCombinerUnit() { return currentCombinerUnit; } + void setCurrentCombinerUnit(int val) { currentCombinerUnit = val; } + boolean getHasMultisample() { return hasMultisample; } + void setHasMultisample(boolean val){ hasMultisample = val; } + + // Helpers for vertex attribute methods + void initCgVertexAttributeImpl() { + if (vertexAttrImpl != null) { + throw new RuntimeException("Should not initialize the vertex attribute implementation twice"); + } + vertexAttrImpl = new CgVertexAttributeImpl(); + } + + void initGLSLVertexAttributeImpl() { + if (vertexAttrImpl != null) { + throw new RuntimeException("Should not initialize the vertex attribute implementation twice"); + } + vertexAttrImpl = new GLSLVertexAttributeImpl(); + } + + void vertexAttrPointer(GL gl, + int index, int size, int type, int stride, Buffer pointer) { + vertexAttrImpl.vertexAttrPointer(gl, index, size, type, stride, pointer); + } + + void enableVertexAttrArray(GL gl, int index) { + vertexAttrImpl.enableVertexAttrArray(gl, index); + } + + void disableVertexAttrArray(GL gl, int index) { + vertexAttrImpl.disableVertexAttrArray(gl, index); + } + + void vertexAttr1fv(GL gl, int index, FloatBuffer buf) { + vertexAttrImpl.vertexAttr1fv(gl, index, buf); + } + + void vertexAttr2fv(GL gl, int index, FloatBuffer buf) { + vertexAttrImpl.vertexAttr2fv(gl, index, buf); + } + + void vertexAttr3fv(GL gl, int index, FloatBuffer buf) { + vertexAttrImpl.vertexAttr3fv(gl, index, buf); + } + + void vertexAttr4fv(GL gl, int index, FloatBuffer buf) { + vertexAttrImpl.vertexAttr4fv(gl, index, buf); + } + + // Used in vertex attribute implementation + JoglShaderObject getShaderProgram() { return shaderProgram; } + void setShaderProgram(JoglShaderObject object) { shaderProgram = object; } + + // Only used when GLSL shaders are in use + int getGLSLVertexAttrOffset() { return glslVertexAttrOffset; } + void setGLSLVertexAttrOffset(int offset) { glslVertexAttrOffset = offset; } + + // Only used when Cg shaders are in use + CGcontext getCgContext() { return cgContext; } + void setCgContext(CGcontext c) { cgContext = c; } + int getCgVertexProfile() { return cgVertexProfile; } + void setCgVertexProfile(int p) { cgVertexProfile = p; } + int getCgFragmentProfile() { return cgFragmentProfile; } + void setCgFragmentProfile(int p) { cgFragmentProfile = p; } +} diff --git a/src/classes/jogl/javax/media/j3d/JoglDrawable.java b/src/classes/jogl/javax/media/j3d/JoglDrawable.java new file mode 100755 index 0000000..3834a11 --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglDrawable.java @@ -0,0 +1,30 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.media.opengl.*; + +/** + * Drawable class for the Jogl rendering pipeline. + */ +class JoglDrawable implements Drawable { + private GLDrawable drawable; + + JoglDrawable(GLDrawable drawable) { + this.drawable = drawable; + } + + GLDrawable getGLDrawable() { + return drawable; + } +} diff --git a/src/classes/jogl/javax/media/j3d/JoglDrawingSurfaceObject.java b/src/classes/jogl/javax/media/j3d/JoglDrawingSurfaceObject.java new file mode 100644 index 0000000..d20a3d0 --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglDrawingSurfaceObject.java @@ -0,0 +1,60 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The DrawingSurfaceObject class is used to manage native drawing surface + */ +class JoglDrawingSurfaceObject extends DrawingSurfaceObject { + + JoglDrawingSurfaceObject(Canvas3D cv) { + super(cv); + + // System.err.println("JoglDrawingSurfaceObject constructed"); + } + + synchronized boolean renderLock() { + // System.err.println("JoglDrawingSurfaceObject.renderLock()"); + gotDsiLock = true; + return true; + } + + synchronized void unLock() { + // System.err.println("JoglDrawingSurfaceObject.unLock()"); + gotDsiLock = false; + } + + synchronized void getDrawingSurfaceObjectInfo() { + // FIXME: we don't have all of the information we need here to + // create a GLDrawable for the Canvas3D, so for now, do nothing + + // FIXME: this mechanism is much too complicated + + /* + System.err.println("JoglDrawingSurfaceObject.getDrawingSurfaceObjectInfo()"); + + if (canvas.drawable == null) { + System.err.println( + "JoglDrawingSurfaceObject.getDrawingSurfaceObjectInfo: window = " + + canvas.drawable); + + // TODO: replace with a real JoglDrawable + canvas.drawable = new JoglDrawable(); + } + */ + } + + synchronized void invalidate() { + System.err.println("JoglDrawingSurfaceObject.invalidate()"); + } +} diff --git a/src/classes/jogl/javax/media/j3d/JoglGraphicsConfiguration.java b/src/classes/jogl/javax/media/j3d/JoglGraphicsConfiguration.java new file mode 100755 index 0000000..d207069 --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglGraphicsConfiguration.java @@ -0,0 +1,103 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.awt.*; +import java.awt.geom.*; +import java.awt.image.*; +import javax.media.opengl.*; + +/** + * Class implementing the GraphicsConfiguration API, but not a "real" + * GraphicsConfiguration object. Wraps a GLCapabilities object and + * supports either immediate or deferred pixel format / visual + * selection depending on which platform we are running. + */ + +class JoglGraphicsConfiguration extends GraphicsConfiguration { + private GLCapabilities caps; + private int chosenIndex; + private GraphicsDevice device; + // Needed for Screen3D + private int width; + private int height; + + JoglGraphicsConfiguration(GLCapabilities caps, int chosenIndex, GraphicsDevice device) { + super(); + this.caps = caps; + this.chosenIndex = chosenIndex; + this.device = device; + DisplayMode m = device.getDisplayMode(); + width = m.getWidth(); + height = m.getHeight(); + } + + GLCapabilities getGLCapabilities() { + return caps; + } + + int getChosenIndex() { + return chosenIndex; + } + + public BufferedImage createCompatibleImage(int width, int height) { + throw new RuntimeException("Unimplemented"); + } + + public BufferedImage createCompatibleImage(int width, int height, + int transparency) { + throw new RuntimeException("Unimplemented"); + } + + public VolatileImage createCompatibleVolatileImage(int width, int height) { + throw new RuntimeException("Unimplemented"); + } + + public VolatileImage createCompatibleVolatileImage(int width, int height, int transparency) { + throw new RuntimeException("Unimplemented"); + } + + public VolatileImage createCompatibleVolatileImage(int width, int height, + ImageCapabilities caps) throws AWTException { + throw new RuntimeException("Unimplemented"); + } + + public VolatileImage createCompatibleVolatileImage(int width, int height, + ImageCapabilities caps, int transparency) throws AWTException { + throw new RuntimeException("Unimplemented"); + } + + public Rectangle getBounds() { + return new Rectangle(0, 0, width, height); + } + + public ColorModel getColorModel() { + throw new RuntimeException("Unimplemented"); + } + + public ColorModel getColorModel(int transparency) { + throw new RuntimeException("Unimplemented"); + } + + public AffineTransform getDefaultTransform() { + throw new RuntimeException("Unimplemented"); + } + + public GraphicsDevice getDevice() { + return device; + } + + public AffineTransform getNormalizingTransform() { + throw new RuntimeException("Unimplemented"); + } +} diff --git a/src/classes/jogl/javax/media/j3d/JoglPipeline.java b/src/classes/jogl/javax/media/j3d/JoglPipeline.java new file mode 100644 index 0000000..3557c32 --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglPipeline.java @@ -0,0 +1,9279 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.awt.*; +import java.io.*; +import java.lang.reflect.*; +import java.nio.*; +import java.security.*; +import java.util.*; +import java.util.regex.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import com.sun.opengl.cg.*; +import com.sun.opengl.util.*; + +/** + * Concrete implementation of Pipeline class for the JOGL rendering + * pipeline. + */ +class JoglPipeline extends Pipeline { + + // Flags indicating whether the Cg or GLSL libraries are available. + private boolean cgLibraryAvailable = false; + + // Currently prints for entry points not yet implemented + private static final boolean DEBUG = true; + // Currently prints for entry points already implemented + private static final boolean VERBOSE = false; + // Debugging output for graphics configuration selection + private static final boolean DEBUG_CONFIG = false; + // Prints extra debugging information + private static final boolean EXTRA_DEBUGGING = false; + // Number of milliseconds to wait for windows to pop up on screen + private static final int WAIT_TIME = 1000; + // Configurable constant just in case we want to change this later + private static final int MIN_FRAME_SIZE = 1; + + /** + * Constructor for singleton JoglPipeline instance + */ + protected JoglPipeline() { + } + + /** + * Initialize the pipeline + */ + void initialize(Pipeline.Type pipelineType) { + super.initialize(pipelineType); + + assert pipelineType == Pipeline.Type.JOGL; + + // Java3D maintains strict control over which threads perform OpenGL work + Threading.disableSingleThreading(); + + // TODO: finish this with any other needed initialization + } + + /** + * Load all of the required libraries + */ + void loadLibraries(int globalShadingLanguage) { + if (globalShadingLanguage == Shader.SHADING_LANGUAGE_CG) { + // Try to load the jogl_cg library and set the + // cgLibraryAvailable flag to true if loads successfully; note + // that successfully performing initialization of this class + // will cause the Cg native library to be loaded on our behalf + try { + Class.forName("com.sun.opengl.cg.CgGL"); + cgLibraryAvailable = true; + } catch (Exception ex) { + System.err.println(ex); + } catch (Error ex) { + System.err.println(ex); + } + } + } + + /** + * Returns true if the Cg library is loaded and available. Note that this + * does not necessarily mean that Cg is supported by the graphics card. + */ + boolean isCgLibraryAvailable() { + return cgLibraryAvailable; + } + + /** + * Returns true if the GLSL library is loaded and available. Note that this + * does not necessarily mean that GLSL is supported by the graphics card. + */ + boolean isGLSLLibraryAvailable() { + return true; + } + + + // --------------------------------------------------------------------- + + // + // GeometryArrayRetained methods + // + + // Used by D3D to free vertex buffer + void freeD3DArray(GeometryArrayRetained geo, boolean deleteVB) { + // Nothing to do + } + + // used for GeometryArrays by Copy or interleaved + void execute(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texUnitOffset, + int numActiveTexUnitState, + int vertexAttrCount, int[] vertexAttrSizes, + float[] varray, float[] carray, int cDirty) { + if (VERBOSE) System.err.println("JoglPipeline.execute()"); + + executeGeometryArray(ctx, geo, geo_type, isNonUniformScale, useAlpha, + ignoreVertexColors, startVIndex, vcount, vformat, + texCoordSetCount, texCoordSetMap, texCoordSetMapLen, + texUnitOffset, numActiveTexUnitState, + vertexAttrCount, vertexAttrSizes, + varray, null, carray, cDirty); + } + + // used by GeometryArray by Reference with java arrays + void executeVA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int initialCoordIndex, float[] vfcoords, double[] vdcoords, + int initialColorIndex, float[] cfdata, byte[] cbdata, + int initialNormalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndices, float[][] vertexAttrData, + int texCoordMapLength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty) { + if (VERBOSE) System.err.println("JoglPipeline.executeVA()"); + + boolean floatCoordDefined = ((vdefined & GeometryArrayRetained.COORD_FLOAT) != 0); + boolean doubleCoordDefined = ((vdefined & GeometryArrayRetained.COORD_DOUBLE) != 0); + boolean floatColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_FLOAT) != 0); + boolean byteColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_BYTE) != 0); + boolean normalsDefined = ((vdefined & GeometryArrayRetained.NORMAL_FLOAT) != 0); + boolean vattrDefined = ((vdefined & GeometryArrayRetained.VATTR_FLOAT) != 0); + boolean textureDefined = ((vdefined & GeometryArrayRetained.TEXCOORD_FLOAT) != 0); + + FloatBuffer fverts = null; + DoubleBuffer dverts = null; + FloatBuffer fclrs = null; + ByteBuffer bclrs = null; + FloatBuffer[] texCoordBufs = null; + FloatBuffer norms = null; + FloatBuffer[] vertexAttrBufs = null; + + // Get vertex attribute arrays + if (vattrDefined) { + vertexAttrBufs = getVertexAttrSetBuffer(vertexAttrData); + } + + // get texture arrays + if (textureDefined) { + texCoordBufs = getTexCoordSetBuffer(texCoords); + } + + // get coordinate array + if (floatCoordDefined) { + fverts = getVertexArrayBuffer(vfcoords); + } else if (doubleCoordDefined) { + dverts = getVertexArrayBuffer(vdcoords); + } + + // get color array + if (floatColorsDefined) { + fclrs = getColorArrayBuffer(cfdata); + } else if (byteColorsDefined) { + bclrs = getColorArrayBuffer(cbdata); + } + + // get normal array + if (normalsDefined) { + norms = getNormalArrayBuffer(ndata); + } + + int[] sarray = null; + int[] start_array = null; + int strip_len = 0; + if (geo_type == GeometryRetained.GEO_TYPE_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_LINE_STRIP_SET) { + sarray = ((GeometryStripArrayRetained) geo).stripVertexCounts; + strip_len = sarray.length; + start_array = ((GeometryStripArrayRetained) geo).stripStartOffsetIndices; + } + + executeGeometryArrayVA(ctx, geo, geo_type, + isNonUniformScale, ignoreVertexColors, + vcount, vformat, vdefined, + initialCoordIndex, fverts, dverts, + initialColorIndex, fclrs, bclrs, + initialNormalIndex, norms, + vertexAttrCount, vertexAttrSizes, + vertexAttrIndices, vertexAttrBufs, + texCoordMapLength, + texcoordoffset, numActiveTexUnitState, + texIndex, texstride, texCoordBufs, cdirty, + sarray, strip_len, start_array); + } + + // used by GeometryArray by Reference with NIO buffer + void executeVABuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int initialCoordIndex, + Object vcoords, + int initialColorIndex, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + int initialNormalIndex, Object ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndices, Object[] vertexAttrData, + int texCoordMapLength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty) { + if (VERBOSE) System.err.println("JoglPipeline.executeVABuffer()"); + + boolean floatCoordDefined = ((vdefined & GeometryArrayRetained.COORD_FLOAT) != 0); + boolean doubleCoordDefined = ((vdefined & GeometryArrayRetained.COORD_DOUBLE) != 0); + boolean floatColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_FLOAT) != 0); + boolean byteColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_BYTE) != 0); + boolean normalsDefined = ((vdefined & GeometryArrayRetained.NORMAL_FLOAT) != 0); + boolean vattrDefined = ((vdefined & GeometryArrayRetained.VATTR_FLOAT) != 0); + boolean textureDefined = ((vdefined & GeometryArrayRetained.TEXCOORD_FLOAT) != 0); + + FloatBuffer fverts = null; + DoubleBuffer dverts = null; + FloatBuffer fclrs = null; + ByteBuffer bclrs = null; + FloatBuffer[] texCoordBufs = null; + FloatBuffer norms = null; + FloatBuffer[] vertexAttrBufs = null; + + // Get vertex attribute arrays + if (vattrDefined) { + vertexAttrBufs = getVertexAttrSetBuffer(vertexAttrData); + } + + // get texture arrays + if (textureDefined) { + texCoordBufs = new FloatBuffer[texCoords.length]; + for (int i = 0; i < texCoords.length; i++) { + texCoordBufs[i] = (FloatBuffer) texCoords[i]; + } + } + + // get coordinate array + if (floatCoordDefined) { + fverts = (FloatBuffer) vcoords; + } else if (doubleCoordDefined) { + dverts = (DoubleBuffer) vcoords; + } + + if (fverts == null && dverts == null) { + return; + } + + // get color array + if (floatColorsDefined) { + if (cfdata != null) + fclrs = getColorArrayBuffer(cfdata); + else + fclrs = (FloatBuffer) cdataBuffer; + } else if (byteColorsDefined) { + if (cbdata != null) + bclrs = getColorArrayBuffer(cbdata); + else + bclrs = (ByteBuffer) cdataBuffer; + } + + // get normal array + if (normalsDefined) { + norms = (FloatBuffer) ndata; + } + + int[] sarray = null; + int[] start_array = null; + int strip_len = 0; + if (geo_type == GeometryRetained.GEO_TYPE_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_LINE_STRIP_SET) { + sarray = ((GeometryStripArrayRetained) geo).stripVertexCounts; + strip_len = sarray.length; + start_array = ((GeometryStripArrayRetained) geo).stripStartOffsetIndices; + } + + executeGeometryArrayVA(ctx, geo, geo_type, + isNonUniformScale, ignoreVertexColors, + vcount, vformat, vdefined, + initialCoordIndex, fverts, dverts, + initialColorIndex, fclrs, bclrs, + initialNormalIndex, norms, + vertexAttrCount, vertexAttrSizes, + vertexAttrIndices, vertexAttrBufs, + texCoordMapLength, + texcoordoffset, numActiveTexUnitState, + texIndex, texstride, texCoordBufs, cdirty, + sarray, strip_len, start_array); + } + + // used by GeometryArray by Reference in interleaved format with NIO buffer + void executeInterleavedBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texUnitOffset, + int numActiveTexUnit, + Object varray, float[] cdata, int cdirty) { + if (VERBOSE) System.err.println("JoglPipeline.executeInterleavedBuffer()"); + + executeGeometryArray(ctx, geo, geo_type, + isNonUniformScale, useAlpha, ignoreVertexColors, + startVIndex, vcount, vformat, + texCoordSetCount, texCoordSetMap, texCoordSetMapLen, + texUnitOffset, numActiveTexUnit, 0, null, + null, (Buffer) varray, cdata, cdirty); + } + + void setVertexFormat(Context ctx, GeometryArrayRetained geo, + int vformat, boolean useAlpha, boolean ignoreVertexColors) { + if (VERBOSE) System.err.println("JoglPipeline.setVertexFormat()"); + + GL gl = context(ctx).getGL(); + + // Enable and disable the appropriate pointers + if ((vformat & GeometryArray.NORMALS) != 0) { + gl.glEnableClientState(GL.GL_NORMAL_ARRAY); + } else { + gl.glDisableClientState(GL.GL_NORMAL_ARRAY); + } + if (!ignoreVertexColors && ((vformat & GeometryArray.COLOR) != 0)) { + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + } else { + gl.glDisableClientState(GL.GL_COLOR_ARRAY); + } + + if (gl.isExtensionAvailable("GL_SUN_global_alpha")) { + if (useAlpha) { + gl.glEnable(GL.GL_GLOBAL_ALPHA_SUN); + } else { + gl.glDisable(GL.GL_GLOBAL_ALPHA_SUN); + } + } + + if ((vformat & GeometryArray.COORDINATES) != 0) { + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + } else { + gl.glDisableClientState(GL.GL_VERTEX_ARRAY); + } + } + + void disableGlobalAlpha(Context ctx, GeometryArrayRetained geo, int vformat, + boolean useAlpha, boolean ignoreVertexColors) { + if (VERBOSE) System.err.println("JoglPipeline.disableGlobalAlpha()"); + + GL gl = context(ctx).getGL(); + + if (gl.isExtensionAvailable("GL_SUN_global_alpha")) { + if (!ignoreVertexColors && ((vformat & GeometryArray.COLOR) != 0)) { + if (useAlpha) { + gl.glDisable(GL.GL_GLOBAL_ALPHA_SUN); + } + } + } + } + + // used for GeometryArrays + void buildGA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int startVIndex, + int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, int[] texCoordSetMapOffset, + int vertexAttrCount, int[] vertexAttrSizes, + double[] xform, double[] nxform, + float[] varray) { + if (VERBOSE) System.err.println("JoglPipeline.buildGA()"); + JoglContext jctx = (JoglContext) ctx; + GL gl = context(ctx).getGL(); + FloatBuffer verts = null; + int stride = 0, coordoff = 0, normoff = 0, coloroff = 0, texCoordoff = 0; + int texStride = 0; + int vAttrOff = 0; + if ((vformat & GeometryArray.COORDINATES) != 0) { + stride += 3; + } + if ((vformat & GeometryArray.NORMALS) != 0) { + stride += 3; + coordoff += 3; + } + + if ((vformat & GeometryArray.COLOR) != 0) { + if ((vformat & GeometryArray.BY_REFERENCE) != 0) { + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + stride += 4; + normoff += 4; + coordoff += 4; + } else { + stride += 3; + normoff += 3; + coordoff += 3; + } + } else { + stride += 4; + normoff += 4; + coordoff += 4; + } + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { + texStride = 2 * texCoordSetCount; + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { + texStride = 3 * texCoordSetCount; + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_4) != 0) { + texStride = 4 * texCoordSetCount; + } + stride += texStride; + normoff += texStride; + coloroff += texStride; + coordoff += texStride; + } + + int vAttrStride = 0; + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + vAttrStride += vertexAttrSizes[i]; + } + stride += vAttrStride; + normoff += vAttrStride; + coloroff += vAttrStride; + coordoff += vAttrStride; + texCoordoff += vAttrStride; + } + + int bstride = stride * BufferUtil.SIZEOF_FLOAT; + // Start sending down from the startVIndex + int initialOffset = startVIndex * stride; + normoff += initialOffset; + coloroff += initialOffset; + coordoff += initialOffset; + texCoordoff += initialOffset; + vAttrOff += initialOffset; + + // process alpha for geometryArray without alpha + boolean useAlpha = false; + if (updateAlpha && !ignoreVertexColors) { + useAlpha = true; + } + + if (geo_type == GeometryRetained.GEO_TYPE_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_LINE_STRIP_SET) { + int[] sarray = ((GeometryStripArrayRetained) geo).stripVertexCounts; + + int primType = 0; + switch (geo_type) { + case GeometryRetained.GEO_TYPE_TRI_STRIP_SET : + primType = GL.GL_TRIANGLE_STRIP; + break; + case GeometryRetained.GEO_TYPE_TRI_FAN_SET : + primType = GL.GL_TRIANGLE_FAN; + break; + case GeometryRetained.GEO_TYPE_LINE_STRIP_SET : + primType = GL.GL_LINE_STRIP; + break; + } + + if (ignoreVertexColors) { + vformat &= ~GeometryArray.COLOR; + } + + for (int i = 0; i < sarray.length; i++) { + gl.glBegin(primType); + for (int j = 0; j < sarray[i]; j++) { + if ((vformat & GeometryArray.NORMALS) != 0) { + if (nxform != null) { + float nx = (float) (nxform[0] * varray[normoff] + + nxform[1] * varray[normoff+1] + + nxform[2] * varray[normoff+2]); + float ny = (float) (nxform[4] * varray[normoff] + + nxform[5] * varray[normoff+1] + + nxform[6] * varray[normoff+2]); + float nz = (float) (nxform[8] * varray[normoff] + + nxform[9] * varray[normoff+1] + + nxform[10] * varray[normoff+2]); + gl.glNormal3f(nx, ny, nz); + } else { + gl.glNormal3f(varray[normoff], varray[normoff+1], varray[normoff+2]); + } + } + if ((vformat & GeometryArray.COLOR) != 0) { + if (useAlpha) { + gl.glColor4f(varray[coloroff], + varray[coloroff+1], + varray[coloroff+2], + varray[coloroff+3] * alpha); + } else { + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { // alpha is present + gl.glColor4f(varray[coloroff], + varray[coloroff+1], + varray[coloroff+2], + varray[coloroff+3]); + } else { + gl.glColor3f(varray[coloroff], + varray[coloroff+1], + varray[coloroff+2]); + } + } + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + int vaOff = vAttrOff; + if (verts == null) { + verts = FloatBuffer.wrap(varray); + } + for (int vaIdx = 0; vaIdx < vertexAttrCount; vaIdx++) { + switch (vertexAttrSizes[vaIdx]) { + case 1: + verts.position(vaOff); + jctx.vertexAttr1fv(gl, vaIdx, verts); + break; + case 2: + verts.position(vaOff); + jctx.vertexAttr2fv(gl, vaIdx, verts); + break; + case 3: + verts.position(vaOff); + jctx.vertexAttr3fv(gl, vaIdx, verts); + break; + case 4: + verts.position(vaOff); + jctx.vertexAttr4fv(gl, vaIdx, verts); + break; + } + + vaOff += vertexAttrSizes[vaIdx]; + } + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + if (texCoordSetMapLen > 0) { + if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { + for (int k = 0; k < texCoordSetMapLen; k++) { + if (texCoordSetMapOffset[k] != -1) { + int off = texCoordoff + texCoordSetMapOffset[k]; + gl.glMultiTexCoord2f(GL.GL_TEXTURE0 + k, + varray[off], + varray[off + 1]); + } + } + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { + for (int k = 0; k < texCoordSetMapLen; k++) { + if (texCoordSetMapOffset[k] != -1) { + int off = texCoordoff + texCoordSetMapOffset[k]; + gl.glMultiTexCoord3f(GL.GL_TEXTURE0 + k, + varray[off], + varray[off + 1], + varray[off + 2]); + } + } + } else { + for (int k = 0; k < texCoordSetMapLen; k++) { + if (texCoordSetMapOffset[k] != -1) { + int off = texCoordoff + texCoordSetMapOffset[k]; + gl.glMultiTexCoord4f(GL.GL_TEXTURE0 + k, + varray[off], + varray[off + 1], + varray[off + 2], + varray[off + 3]); + } + } + } + } else { // no multitexture + if (texCoordSetMapOffset[0] != -1) { + int off = texCoordoff + texCoordSetMapOffset[0]; + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { + gl.glTexCoord2f(varray[off], varray[off + 1]); + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { + gl.glTexCoord3f(varray[off], varray[off + 1], varray[off + 2]); + } else { + gl.glTexCoord4f(varray[off], varray[off + 1], varray[off + 2], varray[off + 3]); + } + } + } // no multitexture + } + // texCoordSetMapLen can't be 0 if texture coordinates + // is to be specified + } + + if ((vformat & GeometryArray.COORDINATES) != 0) { + if (xform != null) { + // transform the vertex data with the static transform + float w = (float) (xform[12] * varray[coordoff] + + xform[13] * varray[coordoff+1] + + xform[14] * varray[coordoff+2] + + xform[15]); + float winv = 1.0f/w; + float vx = (float) (xform[0] * varray[coordoff] + + xform[1] * varray[coordoff+1] + + xform[2] * varray[coordoff+2] + + xform[3]) * winv; + float vy = (float) (xform[4] * varray[coordoff] + + xform[5] * varray[coordoff+1] + + xform[6] * varray[coordoff+2] + + xform[7]) * winv; + float vz = (float) (xform[8] * varray[coordoff] + + xform[9] * varray[coordoff+1] + + xform[10] * varray[coordoff+2] + + xform[11]) * winv; + gl.glVertex3f(vx, vy, vz); + } else { + gl.glVertex3f(varray[coordoff], varray[coordoff + 1], varray[coordoff + 2]); + } + } + normoff += stride; + coloroff += stride; + coordoff += stride; + texCoordoff += stride; + vAttrOff += stride; + } + gl.glEnd(); + } + } else if ((geo_type == GeometryRetained.GEO_TYPE_QUAD_SET) || + (geo_type == GeometryRetained.GEO_TYPE_TRI_SET) || + (geo_type == GeometryRetained.GEO_TYPE_POINT_SET) || + (geo_type == GeometryRetained.GEO_TYPE_LINE_SET)) { + int primType = 0; + switch (geo_type) { + case GeometryRetained.GEO_TYPE_QUAD_SET : + primType = GL.GL_QUADS; + break; + case GeometryRetained.GEO_TYPE_TRI_SET : + primType = GL.GL_TRIANGLES; + break; + case GeometryRetained.GEO_TYPE_POINT_SET : + primType = GL.GL_POINTS; + break; + case GeometryRetained.GEO_TYPE_LINE_SET : + primType = GL.GL_LINES; + break; + } + + if (ignoreVertexColors) { + vformat &= ~GeometryArray.COLOR; + } + + gl.glBegin(primType); + for (int j = 0; j < vcount; j++) { + if ((vformat & GeometryArray.NORMALS) != 0) { + if (nxform != null) { + float nx = (float) (nxform[0] * varray[normoff] + + nxform[1] * varray[normoff+1] + + nxform[2] * varray[normoff+2]); + float ny = (float) (nxform[4] * varray[normoff] + + nxform[5] * varray[normoff+1] + + nxform[6] * varray[normoff+2]); + float nz = (float) (nxform[8] * varray[normoff] + + nxform[9] * varray[normoff+1] + + nxform[10] * varray[normoff+2]); + gl.glNormal3f(nx, ny, nz); + } else { + gl.glNormal3f(varray[normoff], varray[normoff + 1], varray[normoff + 2]); + } + } + if ((vformat & GeometryArray.COLOR) != 0) { + if (useAlpha) { + float cr, cg, cb, ca; + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + cr = varray[coloroff]; + cg = varray[coloroff + 1]; + cb = varray[coloroff + 2]; + ca = varray[coloroff + 3] * alpha; + } else { + cr = varray[coloroff]; + cg = varray[coloroff + 1]; + cb = varray[coloroff + 2]; + ca = alpha; + } + gl.glColor4f(cr, cg, cb, ca); + } else { + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { // alpha is present + gl.glColor4f(varray[coloroff], + varray[coloroff + 1], + varray[coloroff + 2], + varray[coloroff + 3]); + } else { + gl.glColor3f(varray[coloroff], + varray[coloroff + 1], + varray[coloroff + 2]); + } + } + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + int vaOff = vAttrOff; + if (verts == null) { + verts = FloatBuffer.wrap(varray); + } + for (int vaIdx = 0; vaIdx < vertexAttrCount; vaIdx++) { + switch (vertexAttrSizes[vaIdx]) { + case 1: + verts.position(vaOff); + jctx.vertexAttr1fv(gl, vaIdx, verts); + break; + case 2: + verts.position(vaOff); + jctx.vertexAttr2fv(gl, vaIdx, verts); + break; + case 3: + verts.position(vaOff); + jctx.vertexAttr3fv(gl, vaIdx, verts); + break; + case 4: + verts.position(vaOff); + jctx.vertexAttr4fv(gl, vaIdx, verts); + break; + } + + vaOff += vertexAttrSizes[vaIdx]; + } + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + if (texCoordSetMapLen > 0) { + if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { + for (int k = 0; k < texCoordSetMapLen; k++) { + if (texCoordSetMapOffset[k] != -1) { + int off = texCoordoff + texCoordSetMapOffset[k]; + gl.glMultiTexCoord2f(GL.GL_TEXTURE0 + k, + varray[off], + varray[off + 1]); + } + } + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { + for (int k = 0; k < texCoordSetMapLen; k++) { + if (texCoordSetMapOffset[k] != -1) { + int off = texCoordoff + texCoordSetMapOffset[k]; + gl.glMultiTexCoord3f(GL.GL_TEXTURE0 + k, + varray[off], + varray[off + 1], + varray[off + 2]); + } + } + } else { + for (int k = 0; k < texCoordSetMapLen; k++) { + if (texCoordSetMapOffset[k] != -1) { + int off = texCoordoff + texCoordSetMapOffset[k]; + gl.glMultiTexCoord4f(GL.GL_TEXTURE0 + k, + varray[off], + varray[off + 1], + varray[off + 2], + varray[off + 3]); + } + } + } + } else { // no multitexture + if (texCoordSetMapOffset[0] != -1) { + int off = texCoordoff + texCoordSetMapOffset[0]; + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { + gl.glTexCoord2f(varray[off], varray[off + 1]); + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { + gl.glTexCoord3f(varray[off], varray[off + 1], varray[off + 2]); + } else { + gl.glTexCoord4f(varray[off], varray[off + 1], varray[off + 2], varray[off + 3]); + } + } + } // no multitexture + } + // texCoordSetMapLen can't be 0 if texture coordinates is + // to be specified + } + + if ((vformat & GeometryArray.COORDINATES) != 0) { + if (xform != null) { + // transform the vertex data with the static transform + float w = (float) (xform[12] * varray[coordoff] + + xform[13] * varray[coordoff+1] + + xform[14] * varray[coordoff+2] + + xform[15]); + float winv = 1.0f/w; + float vx = (float) (xform[0] * varray[coordoff] + + xform[1] * varray[coordoff+1] + + xform[2] * varray[coordoff+2] + + xform[3]) * winv; + float vy = (float) (xform[4] * varray[coordoff] + + xform[5] * varray[coordoff+1] + + xform[6] * varray[coordoff+2] + + xform[7]) * winv; + float vz = (float) (xform[8] * varray[coordoff] + + xform[9] * varray[coordoff+1] + + xform[10] * varray[coordoff+2] + + xform[11]) * winv; + gl.glVertex3f(vx, vy, vz); + } else { + gl.glVertex3f(varray[coordoff], varray[coordoff + 1], varray[coordoff + 2]); + } + } + normoff += stride; + coloroff += stride; + coordoff += stride; + texCoordoff += stride; + vAttrOff += stride; + } + gl.glEnd(); + } + } + + // used to Build Dlist GeometryArray by Reference with java arrays + void buildGAForByRef(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int initialCoordIndex, float[] vfcoords, double[] vdcoords, + int initialColorIndex, float[] cfdata, byte[] cbdata, + int initialNormalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndices, float[][] vertexAttrData, + int texCoordMapLength, + int[] tcoordsetmap, + int[] texIndices, int texStride, Object[] texCoords, + double[] xform, double[] nxform) { + if (VERBOSE) System.err.println("JoglPipeline.buildGAForByRef()"); + + GL gl = context(ctx).getGL(); + + boolean floatCoordDefined = ((vdefined & GeometryArrayRetained.COORD_FLOAT) != 0); + boolean doubleCoordDefined = ((vdefined & GeometryArrayRetained.COORD_DOUBLE) != 0); + boolean floatColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_FLOAT) != 0); + boolean byteColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_BYTE) != 0); + boolean normalsDefined = ((vdefined & GeometryArrayRetained.NORMAL_FLOAT) != 0); + boolean vattrDefined = ((vdefined & GeometryArrayRetained.VATTR_FLOAT) != 0); + boolean textureDefined = ((vdefined & GeometryArrayRetained.TEXCOORD_FLOAT) != 0); + + FloatBuffer fverts = null; + DoubleBuffer dverts = null; + FloatBuffer fclrs = null; + ByteBuffer bclrs = null; + FloatBuffer[] texCoordBufs = null; + FloatBuffer norms = null; + FloatBuffer[] vertexAttrBufs = null; + + // Get vertex attribute arrays + if (vattrDefined) { + vertexAttrBufs = getVertexAttrSetBuffer(vertexAttrData); + } + + // get texture arrays + if (textureDefined) { + texCoordBufs = getTexCoordSetBuffer(texCoords); + } + + // process alpha for geometryArray without alpha + boolean useAlpha = false; + if (updateAlpha && !ignoreVertexColors) { + useAlpha = true; + } + + int[] sarray = null; + int[] start_array = null; + int strip_len = 0; + if (geo_type == GeometryRetained.GEO_TYPE_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_LINE_STRIP_SET) { + sarray = ((GeometryStripArrayRetained) geo).stripVertexCounts; + strip_len = sarray.length; + start_array = ((GeometryStripArrayRetained) geo).stripStartOffsetIndices; + } + + if (ignoreVertexColors) { + vformat &= ~GeometryArray.COLOR; + floatColorsDefined = false; + byteColorsDefined = false; + } + + // get coordinate array + if (floatCoordDefined) { + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + fverts = getVertexArrayBuffer(vfcoords, (xform == null)); + if (xform != null) { + // Must copy in and transform data + for (int i = initialCoordIndex; i < vcount * 3; i += 3) { + fverts.put(i , (float) (xform[0] * vfcoords[i] + + xform[1] * vfcoords[i+1] + + xform[2] * vfcoords[i+2])); + fverts.put(i+1, (float) (xform[4] * vfcoords[i] + + xform[5] * vfcoords[i+1] + + xform[6] * vfcoords[i+2])); + fverts.put(i+2, (float) (xform[8] * vfcoords[i] + + xform[9] * vfcoords[i+1] + + xform[10] * vfcoords[i+2])); + } + } + } else if (doubleCoordDefined) { + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + dverts = getVertexArrayBuffer(vdcoords, (xform == null)); + if (xform != null) { + // Must copy in and transform data + for (int i = initialCoordIndex; i < vcount * 3; i += 3) { + dverts.put(i , (xform[0] * vdcoords[i] + + xform[1] * vdcoords[i+1] + + xform[2] * vdcoords[i+2])); + dverts.put(i+1, (xform[4] * vdcoords[i] + + xform[5] * vdcoords[i+1] + + xform[6] * vdcoords[i+2])); + dverts.put(i+2, (xform[8] * vdcoords[i] + + xform[9] * vdcoords[i+1] + + xform[10] * vdcoords[i+2])); + } + } + } else { + gl.glDisableClientState(GL.GL_VERTEX_ARRAY); + } + + // get color array + if (floatColorsDefined) { + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + fclrs = getColorArrayBuffer(cfdata, !useAlpha); + if (useAlpha) { + // Must copy in and modify color data + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + for (int i = initialColorIndex; i < vcount * 4; i += 4) { + fclrs.put(i , cfdata[i]); + fclrs.put(i+1, cfdata[i+1]); + fclrs.put(i+2, cfdata[i+2]); + fclrs.put(i+3, alpha * cfdata[i+3]); + } + } else { + int k = 0; + for (int i = initialColorIndex; i < vcount * 4; i += 4) { + fclrs.put(i , cfdata[k++]); + fclrs.put(i+1, cfdata[k++]); + fclrs.put(i+2, cfdata[k++]); + fclrs.put(i+3, alpha); + } + } + vformat |= GeometryArray.WITH_ALPHA; + } + } else if (byteColorsDefined) { + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + bclrs = getColorArrayBuffer(cbdata, !useAlpha); + if (useAlpha) { + // Must copy in and modify color data + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + for (int i = initialColorIndex; i < vcount * 4; i += 4) { + bclrs.put(i , cbdata[i]); + bclrs.put(i+1, cbdata[i+1]); + bclrs.put(i+2, cbdata[i+2]); + bclrs.put(i+3, (byte) (alpha * (int) (cbdata[i+3] & 0xFF))); + } + } else { + int k = 0; + for (int i = initialColorIndex; i < vcount * 4; i += 4) { + bclrs.put(i , cbdata[k++]); + bclrs.put(i+1, cbdata[k++]); + bclrs.put(i+2, cbdata[k++]); + bclrs.put(i+3, (byte) (alpha * 255.0f)); + } + } + vformat |= GeometryArray.WITH_ALPHA; + } + } else { + gl.glDisableClientState(GL.GL_COLOR_ARRAY); + } + + // get normal array + if (normalsDefined) { + gl.glEnableClientState(GL.GL_NORMAL_ARRAY); + norms = getNormalArrayBuffer(ndata, (nxform == null)); + if (nxform != null) { + // Must copy in and transform data + for (int i = initialNormalIndex; i < vcount * 3; i += 3) { + norms.put(i , (float) (nxform[0] * ndata[i] + + nxform[1] * ndata[i+1] + + nxform[2] * ndata[i+2])); + norms.put(i+1, (float) (nxform[4] * ndata[i] + + nxform[5] * ndata[i+1] + + nxform[6] * ndata[i+2])); + norms.put(i+2, (float) (nxform[8] * ndata[i] + + nxform[9] * ndata[i+1] + + nxform[10] * ndata[i+2])); + } + } + } else { + gl.glDisableClientState(GL.GL_NORMAL_ARRAY); + } + + executeGeometryArrayVA(ctx, geo, geo_type, + isNonUniformScale, ignoreVertexColors, + vcount, vformat, vdefined, + initialCoordIndex, fverts, dverts, + initialColorIndex, fclrs, bclrs, + initialNormalIndex, norms, + vertexAttrCount, vertexAttrSizes, + vertexAttrIndices, vertexAttrBufs, + texCoordMapLength, + tcoordsetmap, texCoordMapLength, + texIndices, texStride, texCoordBufs, 0, + sarray, strip_len, start_array); + } + + //---------------------------------------------------------------------- + // Private helper methods for GeometryArrayRetained + // + + private void + testForInterleavedArrays(int vformat, + boolean[] useInterleavedArrays, + int[] iaFormat) { + if (VERBOSE) System.err.println("JoglPipeline.testForInterleavedArrays()"); + useInterleavedArrays[0] = true; + switch (vformat) { + case GeometryArray.COORDINATES : + iaFormat[0] = GL.GL_V3F; break; + case (GeometryArray.COORDINATES | GeometryArray.NORMALS) : + iaFormat[0] = GL.GL_N3F_V3F; break; + case (GeometryArray.COORDINATES | GeometryArray.TEXTURE_COORDINATE_2) : + iaFormat[0] = GL.GL_T2F_V3F; break; + case (GeometryArray.COORDINATES | GeometryArray.NORMALS | GeometryArray.COLOR) : + case (GeometryArray.COORDINATES | GeometryArray.NORMALS | GeometryArray.COLOR | GeometryArray.WITH_ALPHA) : + iaFormat[0] = GL.GL_C4F_N3F_V3F; break; + case (GeometryArray.COORDINATES | GeometryArray.NORMALS | GeometryArray.TEXTURE_COORDINATE_2) : + iaFormat[0] = GL.GL_T2F_N3F_V3F; break; + case (GeometryArray.COORDINATES | GeometryArray.NORMALS | GeometryArray.COLOR | GeometryArray.TEXTURE_COORDINATE_2): + case (GeometryArray.COORDINATES | GeometryArray.NORMALS | GeometryArray.COLOR | GeometryArray.WITH_ALPHA | GeometryArray.TEXTURE_COORDINATE_2): + iaFormat[0] = GL.GL_T2F_C4F_N3F_V3F; break; + default: + useInterleavedArrays[0] = false; break; + } + } + + private void + enableTexCoordPointer(GL gl, + int texUnit, + int texSize, + int texDataType, + int stride, + Buffer pointer) { + if (VERBOSE) System.err.println("JoglPipeline.enableTexCoordPointer()"); + clientActiveTextureUnit(gl, texUnit); + gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + gl.glTexCoordPointer(texSize, texDataType, stride, pointer); + } + + private void + disableTexCoordPointer(GL gl, + int texUnit) { + if (VERBOSE) System.err.println("JoglPipeline.disableTexCoordPointer()"); + clientActiveTextureUnit(gl, texUnit); + gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY); + } + + private void + clientActiveTextureUnit(GL gl, + int texUnit) { + if (VERBOSE) System.err.println("JoglPipeline.clientActiveTextureUnit()"); + if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + gl.glClientActiveTexture(texUnit + GL.GL_TEXTURE0); + } + } + + + private void + executeTexture(int texCoordSetMapLen, + int texSize, int bstride, int texCoordoff, + int[] texCoordSetMapOffset, + int numActiveTexUnit, + FloatBuffer verts, GL gl) { + if (VERBOSE) System.err.println("JoglPipeline.executeTexture()"); + int tus = 0; /* texture unit state index */ + + for (int i = 0; i < numActiveTexUnit; i++) { + + tus = i; + + /* + * it's possible thattexture unit state index (tus) + * is greater than the texCoordSetMapOffsetLen, in this + * case, just disable TexCoordPointer. + */ + if ((tus < texCoordSetMapLen) && + (texCoordSetMapOffset[tus] != -1)) { + if (EXTRA_DEBUGGING) { + System.err.println(" texCoord position " + i + ": " + (texCoordoff + texCoordSetMapOffset[tus])); + } + verts.position(texCoordoff + texCoordSetMapOffset[tus]); + enableTexCoordPointer(gl, i, + texSize, GL.GL_FLOAT, bstride, + verts); + } else { + disableTexCoordPointer(gl, i); + } + } + } + + private void + resetTexture(GL gl, JoglContext ctx) { + if (VERBOSE) System.err.println("JoglPipeline.resetTexture()"); + /* Disable texture coordinate arrays for all texture units */ + for (int i = 0; i < ctx.getMaxTexCoordSets(); i++) { + disableTexCoordPointer(gl, i); + } + /* Reset client active texture unit to 0 */ + clientActiveTextureUnit(gl, 0); + } + + private void + executeGeometryArray(Context absCtx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetMapOffset, + int numActiveTexUnitState, + int vertexAttrCount, int[] vertexAttrSizes, + float[] varray, Buffer varrayBuffer, + float[] carray, int cDirty) { + if (VERBOSE) System.err.println("JoglPipeline.executeGeometryArray()"); + JoglContext ctx = (JoglContext) absCtx; + GLContext context = context(ctx); + GL gl = context.getGL(); + + boolean useInterleavedArrays; + int iaFormat = 0; + int primType = 0; + int stride = 0, coordoff = 0, normoff = 0, coloroff = 0, texCoordoff = 0; + int texSize = 0, texStride = 0; + int vAttrOff = 0; + int vAttrStride = 0; + int bstride = 0, cbstride = 0; + FloatBuffer verts = null; + FloatBuffer clrs = null; + int[] sarray = null; + int[] start_array = null; + + if (EXTRA_DEBUGGING) { + System.err.println("Vertex format: " + getVertexDescription(vformat)); + System.err.println("Geometry type: " + getGeometryDescription(geo_type)); + if (carray != null) { + System.err.println(" Separate color array"); + } else { + System.err.println(" Colors (if any) interleaved"); + } + } + + if ((vformat & GeometryArray.COORDINATES) != 0) { + stride += 3; + } + if ((vformat & GeometryArray.NORMALS) != 0) { + stride += 3; + coordoff += 3; + } + if ((vformat & GeometryArray.COLOR) != 0) { + if ((vformat & GeometryArray.WITH_ALPHA) != 0 ) { + stride += 4; + normoff += 4; + coordoff += 4; + } else { /* Handle the case of executeInterleaved 3f */ + stride += 3; + normoff += 3; + coordoff += 3; + } + } + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + if (EXTRA_DEBUGGING) { + System.err.println(" Number of tex coord sets: " + texCoordSetCount); + } + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { + texSize = 2; + texStride = 2 * texCoordSetCount; + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { + texSize = 3; + texStride = 3 * texCoordSetCount; + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_4) != 0) { + texSize = 4; + texStride = 4 * texCoordSetCount; + } + stride += texStride; + normoff += texStride; + coloroff += texStride; + coordoff += texStride; + } + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + vAttrStride += vertexAttrSizes[i]; + } + stride += vAttrStride; + normoff += vAttrStride; + coloroff += vAttrStride; + coordoff += vAttrStride; + texCoordoff += vAttrStride; + } + + bstride = stride * BufferUtil.SIZEOF_FLOAT; + + if (geo_type == GeometryRetained.GEO_TYPE_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_LINE_STRIP_SET) { + sarray = ((GeometryStripArrayRetained) geo).stripVertexCounts; + start_array = ((GeometryStripArrayRetained) geo).stripStartOffsetIndices; + } + + // We have to copy if the data isn't specified using NIO + if (varray != null) { + verts = getVertexArrayBuffer(varray); + } else if (varrayBuffer != null) { + verts = (FloatBuffer) varrayBuffer; + } else { + // This should never happen + throw new AssertionError("Unable to get vertex pointer"); + } + + // using byRef interleaved array and has a separate pointer, then .. + int cstride = stride; + if (carray != null) { + clrs = getColorArrayBuffer(carray); + cstride = 4; + } else { + // FIXME: need to "auto-slice" this buffer later + clrs = verts; + } + + cbstride = cstride * BufferUtil.SIZEOF_FLOAT; + + // Enable normalize for non-uniform scale (which rescale can't handle) + if (isNonUniformScale) { + gl.glEnable(GL.GL_NORMALIZE); + } + + int startVertex = stride * startVIndex; + int startClrs = cstride * startVIndex; + if (clrs == verts) { + startClrs += coloroff; + } + + /*** Handle non-indexed strip GeometryArray first *******/ + if (geo_type == GeometryRetained.GEO_TYPE_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_LINE_STRIP_SET) { + if (ignoreVertexColors || (carray != null) || + ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0 && ((texCoordSetMapLen > 1) || + (texCoordSetCount > 1)))) { + useInterleavedArrays = false; + } else { + boolean[] tmp = new boolean[1]; + int[] tmp2 = new int[1]; + testForInterleavedArrays(vformat, tmp, tmp2); + useInterleavedArrays = tmp[0]; + iaFormat = tmp2[0]; + } + if (useInterleavedArrays) { + verts.position(startVertex); + gl.glInterleavedArrays(iaFormat, bstride, verts); + } else { + if ((vformat & GeometryArray.NORMALS) != 0) { + verts.position(startVertex + normoff); + gl.glNormalPointer(GL.GL_FLOAT, bstride, verts); + } + if (!ignoreVertexColors && (vformat & GeometryArray.COLOR) != 0) { + if (EXTRA_DEBUGGING) { + System.err.println(" Doing colors"); + } + clrs.position(startClrs); + if ((vformat & GeometryArray.WITH_ALPHA) != 0 || useAlpha) { + gl.glColorPointer(4, GL.GL_FLOAT, cbstride, clrs); + } else { + gl.glColorPointer(3, GL.GL_FLOAT, cbstride, clrs); + } + } + if ((vformat & GeometryArray.COORDINATES) != 0) { + verts.position(startVertex + coordoff); + gl.glVertexPointer(3, GL.GL_FLOAT, bstride, verts); + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + executeTexture(texCoordSetMapLen, + texSize, bstride, texCoordoff, + texCoordSetMapOffset, + numActiveTexUnitState, + verts, gl); + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + int vAttrOffset = startVertex + vAttrOff; + for (int i = 0; i < vertexAttrCount; i++) { + ctx.enableVertexAttrArray(gl, i); + verts.position(vAttrOffset); + ctx.vertexAttrPointer(gl, i, vertexAttrSizes[i], + GL.GL_FLOAT, bstride, verts); + vAttrOffset += vertexAttrSizes[i]; + } + } + } + + switch (geo_type) { + case GeometryRetained.GEO_TYPE_TRI_STRIP_SET: + primType = GL.GL_TRIANGLE_STRIP; + break; + case GeometryRetained.GEO_TYPE_TRI_FAN_SET: + primType = GL.GL_TRIANGLE_FAN; + break; + case GeometryRetained.GEO_TYPE_LINE_STRIP_SET: + primType = GL.GL_LINE_STRIP; + break; + } + + if (gl.isExtensionAvailable("GL_EXT_multi_draw_arrays")) { + gl.glMultiDrawArraysEXT(primType, start_array, 0, sarray, 0, sarray.length); + } else { + for (int i = 0; i < sarray.length; i++) { + gl.glDrawArrays(primType, start_array[i], sarray[i]); + } + } + } else if ((geo_type == GeometryRetained.GEO_TYPE_QUAD_SET) || + (geo_type == GeometryRetained.GEO_TYPE_TRI_SET) || + (geo_type == GeometryRetained.GEO_TYPE_POINT_SET) || + (geo_type == GeometryRetained.GEO_TYPE_LINE_SET)) { + /******* Handle non-indexed non-striped GeometryArray now *****/ + if (ignoreVertexColors || (carray != null) || + ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0 && ((texCoordSetMapLen > 1) || + (texCoordSetCount > 1)))) { + useInterleavedArrays = false; + } else { + boolean[] tmp = new boolean[1]; + int[] tmp2 = new int[1]; + testForInterleavedArrays(vformat, tmp, tmp2); + useInterleavedArrays = tmp[0]; + iaFormat = tmp2[0]; + } + + if (useInterleavedArrays) { + verts.position(startVertex); + gl.glInterleavedArrays(iaFormat, bstride, verts); + } else { + if (EXTRA_DEBUGGING) { + System.err.println(" startVertex: " + startVertex); + System.err.println(" stride: " + stride); + System.err.println(" bstride: " + bstride); + System.err.println(" normoff: " + normoff); + System.err.println(" coloroff: " + coloroff); + System.err.println(" coordoff: " + coordoff); + System.err.println(" texCoordoff: " + texCoordoff); + } + if ((vformat & GeometryArray.NORMALS) != 0) { + verts.position(startVertex + normoff); + gl.glNormalPointer(GL.GL_FLOAT, bstride, verts); + } + if (!ignoreVertexColors && (vformat & GeometryArray.COLOR) != 0) { + clrs.position(startClrs); + if ((vformat & GeometryArray.WITH_ALPHA) != 0 || useAlpha) { + gl.glColorPointer(4, GL.GL_FLOAT, cbstride, clrs); + } else { + gl.glColorPointer(3, GL.GL_FLOAT, cbstride, clrs); + } + } + if ((vformat & GeometryArray.COORDINATES) != 0) { + verts.position(startVertex + coordoff); + gl.glVertexPointer(3, GL.GL_FLOAT, bstride, verts); + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + executeTexture(texCoordSetMapLen, + texSize, bstride, texCoordoff, + texCoordSetMapOffset, + numActiveTexUnitState, + verts, gl); + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + int vAttrOffset = startVertex + vAttrOff; + for (int i = 0; i < vertexAttrCount; i++) { + ctx.enableVertexAttrArray(gl, i); + verts.position(vAttrOffset); + ctx.vertexAttrPointer(gl, i, vertexAttrSizes[i], + GL.GL_FLOAT, bstride, verts); + vAttrOffset += vertexAttrSizes[i]; + } + } + } + switch (geo_type){ + case GeometryRetained.GEO_TYPE_QUAD_SET : gl.glDrawArrays(GL.GL_QUADS, 0, vcount); break; + case GeometryRetained.GEO_TYPE_TRI_SET : gl.glDrawArrays(GL.GL_TRIANGLES, 0, vcount); break; + case GeometryRetained.GEO_TYPE_POINT_SET: gl.glDrawArrays(GL.GL_POINTS, 0, vcount); break; + case GeometryRetained.GEO_TYPE_LINE_SET : gl.glDrawArrays(GL.GL_LINES, 0, vcount); break; + } + } + + /* clean up if we turned on normalize */ + if (isNonUniformScale) { + gl.glDisable(GL.GL_NORMALIZE); + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + resetVertexAttrs(gl, ctx, vertexAttrCount); + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + resetTexture(gl, ctx); + } + } + + + // glLockArrays() is invoked only for indexed geometry, and the + // vertexCount is guarenteed to be >= 0. + private void lockArray(GL gl, int vertexCount) { + if (gl.isExtensionAvailable("GL_EXT_compiled_vertex_array")) { + gl.glLockArraysEXT(0, vertexCount); + } + } + + private void unlockArray(GL gl) { + if (gl.isExtensionAvailable("GL_EXT_compiled_vertex_array")) { + gl.glUnlockArraysEXT(); + } + } + + private void + executeGeometryArrayVA(Context absCtx, + GeometryArrayRetained geo, + int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int initialCoordIndex, FloatBuffer fverts, DoubleBuffer dverts, + int initialColorIndex, FloatBuffer fclrs, ByteBuffer bclrs, + int initialNormalIndex, FloatBuffer norms, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndices, FloatBuffer[] vertexAttrData, + int texCoordMapLength, + int[] texCoordSetMap, + int numActiveTexUnit, + int[] texindices, int texStride, FloatBuffer[] texCoords, + int cdirty, + int[] sarray, + int strip_len, + int[] start_array) { + JoglContext ctx = (JoglContext) absCtx; + GLContext context = context(ctx); + GL gl = context.getGL(); + + boolean floatCoordDefined = ((vdefined & GeometryArrayRetained.COORD_FLOAT) != 0); + boolean doubleCoordDefined = ((vdefined & GeometryArrayRetained.COORD_DOUBLE) != 0); + boolean floatColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_FLOAT) != 0); + boolean byteColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_BYTE) != 0); + boolean normalsDefined = ((vdefined & GeometryArrayRetained.NORMAL_FLOAT) != 0); + boolean vattrDefined = ((vdefined & GeometryArrayRetained.VATTR_FLOAT) != 0); + boolean textureDefined = ((vdefined & GeometryArrayRetained.TEXCOORD_FLOAT) != 0); + + // Enable normalize for non-uniform scale (which rescale can't handle) + if (isNonUniformScale) { + gl.glEnable(GL.GL_NORMALIZE); + } + + int coordoff = 3 * initialCoordIndex; + // Define the data pointers + if (floatCoordDefined) { + fverts.position(coordoff); + gl.glVertexPointer(3, GL.GL_FLOAT, 0, fverts); + } else if (doubleCoordDefined){ + dverts.position(coordoff); + gl.glVertexPointer(3, GL.GL_DOUBLE, 0, dverts); + } + + if (floatColorsDefined) { + int coloroff; + int sz; + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + coloroff = 4 * initialColorIndex; + sz = 4; + } else { + coloroff = 3 * initialColorIndex; + sz = 3; + } + fclrs.position(coloroff); + gl.glColorPointer(sz, GL.GL_FLOAT, 0, fclrs); + } else if (byteColorsDefined) { + int coloroff; + int sz; + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + coloroff = 4 * initialColorIndex; + sz = 4; + } else { + coloroff = 3 * initialColorIndex; + sz = 3; + } + bclrs.position(coloroff); + gl.glColorPointer(sz, GL.GL_UNSIGNED_BYTE, 0, bclrs); + } + if (normalsDefined) { + int normoff = 3 * initialNormalIndex; + norms.position(normoff); + gl.glNormalPointer(GL.GL_FLOAT, 0, norms); + } + + if (vattrDefined) { + for (int i = 0; i < vertexAttrCount; i++) { + FloatBuffer vertexAttrs = vertexAttrData[i]; + int sz = vertexAttrSizes[i]; + int initIdx = vertexAttrIndices[i]; + ctx.enableVertexAttrArray(gl, i); + vertexAttrs.position(initIdx * sz); + ctx.vertexAttrPointer(gl, i, sz, GL.GL_FLOAT, 0, vertexAttrs); + } + } + + if (textureDefined) { + int texSet = 0; + for (int i = 0; i < numActiveTexUnit; i++) { + if (( i < texCoordMapLength) && + ((texSet = texCoordSetMap[i]) != -1)) { + FloatBuffer buf = texCoords[texSet]; + buf.position(texStride * texindices[texSet]); + enableTexCoordPointer(gl, i, texStride, + GL.GL_FLOAT, 0, buf); + } else { + disableTexCoordPointer(gl, i); + } + } + + // Reset client active texture unit to 0 + clientActiveTextureUnit(gl, 0); + } + + if (geo_type == GeometryRetained.GEO_TYPE_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_LINE_STRIP_SET) { + int primType = 0; + switch (geo_type) { + case GeometryRetained.GEO_TYPE_TRI_STRIP_SET: + primType = GL.GL_TRIANGLE_STRIP; + break; + case GeometryRetained.GEO_TYPE_TRI_FAN_SET: + primType = GL.GL_TRIANGLE_FAN; + break; + case GeometryRetained.GEO_TYPE_LINE_STRIP_SET: + primType = GL.GL_LINE_STRIP; + break; + } + if (gl.isExtensionAvailable("GL_EXT_multi_draw_arrays")) { + gl.glMultiDrawArraysEXT(primType, start_array, 0, sarray, 0, strip_len); + } else if (gl.isExtensionAvailable("GL_VERSION_1_4")) { + gl.glMultiDrawArrays(primType, start_array, 0, sarray, 0, strip_len); + } else { + for (int i = 0; i < strip_len; i++) { + gl.glDrawArrays(primType, start_array[i], sarray[i]); + } + } + } else { + switch (geo_type){ + case GeometryRetained.GEO_TYPE_QUAD_SET : gl.glDrawArrays(GL.GL_QUADS, 0, vcount); break; + case GeometryRetained.GEO_TYPE_TRI_SET : gl.glDrawArrays(GL.GL_TRIANGLES, 0, vcount); break; + case GeometryRetained.GEO_TYPE_POINT_SET : gl.glDrawArrays(GL.GL_POINTS, 0, vcount); break; + case GeometryRetained.GEO_TYPE_LINE_SET : gl.glDrawArrays(GL.GL_LINES, 0, vcount); break; + } + } + + // clean up if we turned on normalize + if (isNonUniformScale) { + gl.glDisable(GL.GL_NORMALIZE); + } + + if (vattrDefined) { + resetVertexAttrs(gl, ctx, vertexAttrCount); + } + + if (textureDefined) { + resetTexture(gl, ctx); + } + } + + private String getVertexDescription(int vformat) { + String res = ""; + if ((vformat & GeometryArray.COORDINATES) != 0) res += "COORDINATES "; + if ((vformat & GeometryArray.NORMALS) != 0) res += "NORMALS "; + if ((vformat & GeometryArray.COLOR) != 0) res += "COLOR "; + if ((vformat & GeometryArray.WITH_ALPHA) != 0) res += "(WITH_ALPHA) "; + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) res += "TEXTURE_COORDINATE "; + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) res += "(2) "; + if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) res += "(3) "; + if ((vformat & GeometryArray.TEXTURE_COORDINATE_4) != 0) res += "(4) "; + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) res += "VERTEX_ATTRIBUTES "; + return res; + } + + private String getGeometryDescription(int geo_type) { + switch (geo_type) { + case GeometryRetained.GEO_TYPE_TRI_STRIP_SET : return "GEO_TYPE_TRI_STRIP_SET"; + case GeometryRetained.GEO_TYPE_TRI_FAN_SET : return "GEO_TYPE_TRI_FAN_SET"; + case GeometryRetained.GEO_TYPE_LINE_STRIP_SET: return "GEO_TYPE_LINE_STRIP_SET"; + case GeometryRetained.GEO_TYPE_QUAD_SET : return "GEO_TYPE_QUAD_SET"; + case GeometryRetained.GEO_TYPE_TRI_SET : return "GEO_TYPE_TRI_SET"; + case GeometryRetained.GEO_TYPE_POINT_SET : return "GEO_TYPE_POINT_SET"; + case GeometryRetained.GEO_TYPE_LINE_SET : return "GEO_TYPE_LINE_SET"; + default: return "(unknown " + geo_type + ")"; + } + } + + private void resetVertexAttrs(GL gl, JoglContext ctx, int vertexAttrCount) { + // Disable specified vertex attr arrays + for (int i = 0; i < vertexAttrCount; i++) { + ctx.disableVertexAttrArray(gl, i); + } + } + + + // --------------------------------------------------------------------- + + // + // IndexedGeometryArrayRetained methods + // + + // by-copy or interleaved, by reference, Java arrays + void executeIndexedGeometry(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + float[] varray, float[] carray, + int cdirty, + int[] indexCoord) { + if (VERBOSE) System.err.println("JoglPipeline.executeIndexedGeometry()"); + + executeIndexedGeometryArray(ctx, geo, geo_type, + isNonUniformScale, useAlpha, ignoreVertexColors, + initialIndexIndex, indexCount, + vertexCount, vformat, + vertexAttrCount, vertexAttrSizes, + texCoordSetCount, texCoordSetMap, texCoordSetMapLen, + texCoordSetOffset, + numActiveTexUnitState, + varray, null, carray, + cdirty, indexCoord); + } + + // interleaved, by reference, nio buffer + void executeIndexedGeometryBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object vdata, float[] carray, + int cDirty, + int[] indexCoord) { + if (VERBOSE) System.err.println("JoglPipeline.executeIndexedGeometryBuffer()"); + + executeIndexedGeometryArray(ctx, geo, geo_type, + isNonUniformScale, useAlpha, ignoreVertexColors, + initialIndexIndex, indexCount, vertexCount, vformat, + 0, null, + texCoordSetCount, texCoordSetMap, texCoordSetMapLen, texCoordSetOffset, + numActiveTexUnitState, + null, (FloatBuffer) vdata, carray, + cDirty, indexCoord); + } + + // non interleaved, by reference, Java arrays + void executeIndexedGeometryVA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + float[] vfcoords, double[] vdcoords, + float[] cfdata, byte[] cbdata, + float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + float[][] vertexAttrData, + int texCoordMapLength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texStride, Object[] texCoords, + int cdirty, + int[] indexCoord) { + if (VERBOSE) System.err.println("JoglPipeline.executeIndexedGeometryVA()"); + + boolean floatCoordDefined = ((vdefined & GeometryArrayRetained.COORD_FLOAT) != 0); + boolean doubleCoordDefined = ((vdefined & GeometryArrayRetained.COORD_DOUBLE) != 0); + boolean floatColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_FLOAT) != 0); + boolean byteColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_BYTE) != 0); + boolean normalsDefined = ((vdefined & GeometryArrayRetained.NORMAL_FLOAT) != 0); + boolean vattrDefined = ((vdefined & GeometryArrayRetained.VATTR_FLOAT) != 0); + boolean textureDefined = ((vdefined & GeometryArrayRetained.TEXCOORD_FLOAT) != 0); + + FloatBuffer fverts = null; + DoubleBuffer dverts = null; + FloatBuffer fclrs = null; + ByteBuffer bclrs = null; + FloatBuffer[] texCoordBufs = null; + FloatBuffer norms = null; + FloatBuffer[] vertexAttrBufs = null; + + // Get vertex attribute arrays + if (vattrDefined) { + vertexAttrBufs = getVertexAttrSetBuffer(vertexAttrData); + } + + // get texture arrays + if (textureDefined) { + texCoordBufs = getTexCoordSetBuffer(texCoords); + } + + int[] sarray = null; + int strip_len = 0; + if (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET) { + sarray = ((IndexedGeometryStripArrayRetained) geo).stripIndexCounts; + strip_len = sarray.length; + } + + // get coordinate array + if (floatCoordDefined) { + fverts = getVertexArrayBuffer(vfcoords); + } else if (doubleCoordDefined) { + dverts = getVertexArrayBuffer(vdcoords); + } + + // get color array + if (floatColorsDefined) { + fclrs = getColorArrayBuffer(cfdata); + } else if (byteColorsDefined) { + bclrs = getColorArrayBuffer(cbdata); + } + + // get normal array + if (normalsDefined) { + norms = getNormalArrayBuffer(ndata); + } + + executeIndexedGeometryArrayVA(ctx, geo, geo_type, + isNonUniformScale, ignoreVertexColors, + initialIndexIndex, validIndexCount, vertexCount, + vformat, vdefined, + fverts, dverts, + fclrs, bclrs, + norms, + vertexAttrCount, vertexAttrSizes, vertexAttrBufs, + texCoordMapLength, texcoordoffset, + numActiveTexUnitState, + texStride, texCoordBufs, + cdirty, indexCoord, + sarray, strip_len); + } + + // non interleaved, by reference, nio buffer + void executeIndexedGeometryVABuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + Object vcoords, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + Object ndata, + int vertexAttrCount, int[] vertexAttrSizes, + Object[] vertexAttrData, + int texCoordMapLength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texStride, Object[] texCoords, + int cdirty, + int[] indexCoord) { + if (VERBOSE) System.err.println("JoglPipeline.executeIndexedGeometryVABuffer()"); + + boolean floatCoordDefined = ((vdefined & GeometryArrayRetained.COORD_FLOAT) != 0); + boolean doubleCoordDefined = ((vdefined & GeometryArrayRetained.COORD_DOUBLE) != 0); + boolean floatColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_FLOAT) != 0); + boolean byteColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_BYTE) != 0); + boolean normalsDefined = ((vdefined & GeometryArrayRetained.NORMAL_FLOAT) != 0); + boolean vattrDefined = ((vdefined & GeometryArrayRetained.VATTR_FLOAT) != 0); + boolean textureDefined = ((vdefined & GeometryArrayRetained.TEXCOORD_FLOAT) != 0); + + FloatBuffer fverts = null; + DoubleBuffer dverts = null; + FloatBuffer fclrs = null; + ByteBuffer bclrs = null; + FloatBuffer[] texCoordBufs = null; + FloatBuffer norms = null; + FloatBuffer[] vertexAttrBufs = null; + + // Get vertex attribute arrays + if (vattrDefined) { + vertexAttrBufs = getVertexAttrSetBuffer(vertexAttrData); + } + + // get texture arrays + if (textureDefined) { + texCoordBufs = new FloatBuffer[texCoords.length]; + for (int i = 0; i < texCoords.length; i++) { + texCoordBufs[i] = (FloatBuffer) texCoords[i]; + } + } + + // get coordinate array + if (floatCoordDefined) { + fverts = (FloatBuffer) vcoords; + } else if (doubleCoordDefined) { + dverts = (DoubleBuffer) vcoords; + } + + if (fverts == null && dverts == null) { + return; + } + + int[] sarray = null; + int strip_len = 0; + if (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET) { + sarray = ((IndexedGeometryStripArrayRetained) geo).stripIndexCounts; + strip_len = sarray.length; + } + + // get color array + if (floatColorsDefined) { + if (cfdata != null) + fclrs = getColorArrayBuffer(cfdata); + else + fclrs = (FloatBuffer) cdataBuffer; + } else if (byteColorsDefined) { + if (cbdata != null) + bclrs = getColorArrayBuffer(cbdata); + else + bclrs = (ByteBuffer) cdataBuffer; + } + + // get normal array + if (normalsDefined) { + norms = (FloatBuffer) ndata; + } + + executeIndexedGeometryArrayVA(ctx, geo, geo_type, + isNonUniformScale, ignoreVertexColors, + initialIndexIndex, validIndexCount, vertexCount, + vformat, vdefined, + fverts, dverts, + fclrs, bclrs, + norms, + vertexAttrCount, vertexAttrSizes, vertexAttrBufs, + texCoordMapLength, texcoordoffset, + numActiveTexUnitState, + texStride, texCoordBufs, + cdirty, indexCoord, + sarray, strip_len); + } + + // by-copy geometry + void buildIndexedGeometry(Context absCtx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetMapOffset, + double[] xform, double[] nxform, + float[] varray, int[] indexCoord) { + if (VERBOSE) System.err.println("JoglPipeline.buildIndexedGeometry()"); + + JoglContext ctx = (JoglContext) absCtx; + GL gl = context(ctx).getGL(); + + boolean useInterleavedArrays; + int iaFormat = 0; + int primType = 0; + int stride = 0, coordoff = 0, normoff = 0, coloroff = 0, texCoordoff = 0; + int texSize = 0, texStride = 0; + int vAttrOff = 0; + int vAttrStride = 0; + int bstride = 0, cbstride = 0; + FloatBuffer verts = null; + FloatBuffer clrs = null; + int[] sarray = null; + int strip_len = 0; + boolean useAlpha = false; + + if ((vformat & GeometryArray.COORDINATES) != 0) { + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + stride += 3; + } else { + gl.glDisableClientState(GL.GL_VERTEX_ARRAY); + } + + if ((vformat & GeometryArray.NORMALS) != 0) { + gl.glEnableClientState(GL.GL_NORMAL_ARRAY); + stride += 3; + coordoff += 3; + } else { + gl.glDisableClientState(GL.GL_NORMAL_ARRAY); + } + + if ((vformat & GeometryArray.COLOR) != 0) { + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + stride += 4; + normoff += 4; + coordoff += 4; + } else { + gl.glDisableClientState(GL.GL_COLOR_ARRAY); + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { + texSize = 2; + texStride = 2 * texCoordSetCount; + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { + texSize = 3; + texStride = 3 * texCoordSetCount; + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_4) != 0) { + texSize = 4; + texStride = 4 * texCoordSetCount; + } + stride += texStride; + normoff += texStride; + coloroff += texStride; + coordoff += texStride; + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + vAttrStride += vertexAttrSizes[i]; + } + stride += vAttrStride; + normoff += vAttrStride; + coloroff += vAttrStride; + coordoff += vAttrStride; + texCoordoff += vAttrStride; + } + + bstride = stride * BufferUtil.SIZEOF_FLOAT; + + // process alpha for geometryArray without alpha + if (updateAlpha && !ignoreVertexColors) { + useAlpha = true; + } + + if (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET) { + sarray = ((IndexedGeometryStripArrayRetained) geo).stripIndexCounts; + strip_len = sarray.length; + } + + // Copy data into NIO array + verts = getVertexArrayBuffer(varray); + + // Apply normal transform if necessary + if ((vformat & GeometryArray.NORMALS) != 0 && nxform != null) { + int off = normoff; + for (int i = 0; i < vertexCount * 3; i+=3) { + verts.put(off , (float) (nxform[0] * varray[off] + + nxform[1] * varray[off+1] + + nxform[2] * varray[off+2])); + verts.put(off+1, (float) (nxform[4] * varray[off] + + nxform[5] * varray[off+1] + + nxform[6] * varray[off+2])); + verts.put(off+2, (float) (nxform[8] * varray[off] + + nxform[9] * varray[off+1] + + nxform[10] * varray[off+2])); + off += stride; + } + } + + // Apply coordinate transform if necessary + if ((vformat & GeometryArray.COORDINATES) != 0 && xform != null) { + int off = coordoff; + for (int i = 0; i < vertexCount * 3; i+=3) { + verts.put(off , (float) (xform[0] * varray[off] + + xform[1] * varray[off+1] + + xform[2] * varray[off+2])); + verts.put(off+1, (float) (xform[4] * varray[off] + + xform[5] * varray[off+1] + + xform[6] * varray[off+2])); + verts.put(off+2, (float) (xform[8] * varray[off] + + xform[9] * varray[off+1] + + xform[10] * varray[off+2])); + off += stride; + } + } + + if (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET) { + // Note we can use interleaved arrays even if we have a + // non-null xform since we use the same data layout unlike the + // C code + if (ignoreVertexColors || + (((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) && ((texCoordSetMapLen > 1) || + (texCoordSetCount > 1)))) { + useInterleavedArrays = false; + } else { + boolean[] tmp = new boolean[1]; + int[] tmp2 = new int[1]; + testForInterleavedArrays(vformat, tmp, tmp2); + useInterleavedArrays = tmp[0]; + iaFormat = tmp2[0]; + } + + if (useInterleavedArrays) { + verts.position(0); + gl.glInterleavedArrays(iaFormat, bstride, verts); + } else { + if ((vformat & GeometryArray.NORMALS) != 0) { + verts.position(normoff); + gl.glNormalPointer(GL.GL_FLOAT, bstride, verts); + } + if (!ignoreVertexColors && ((vformat & GeometryArray.COLOR) != 0)) { + verts.position(coloroff); + if (((vformat & GeometryArray.WITH_ALPHA) != 0) || useAlpha) { + gl.glColorPointer(4, GL.GL_FLOAT, bstride, verts); + } else { + gl.glColorPointer(3, GL.GL_FLOAT, bstride, verts); + } + } + if ((vformat & GeometryArray.COORDINATES) != 0) { + verts.position(coordoff); + gl.glVertexPointer(3, GL.GL_FLOAT, bstride, verts); + } + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + executeTexture(texCoordSetMapLen, + texSize, bstride, texCoordoff, + texCoordSetMapOffset, + texCoordSetMapLen, + verts, gl); + } + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + int vAttrOffset = vAttrOff; + for (int i = 0; i < vertexAttrCount; i++) { + ctx.enableVertexAttrArray(gl, i); + verts.position(vAttrOffset); + ctx.vertexAttrPointer(gl, i, vertexAttrSizes[i], + GL.GL_FLOAT, bstride, verts); + vAttrOffset += vertexAttrSizes[i]; + } + } + } + + switch (geo_type) { + case GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET: + primType = GL.GL_TRIANGLE_STRIP; + break; + case GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET: + primType = GL.GL_TRIANGLE_FAN; + break; + case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET: + primType = GL.GL_LINE_STRIP; + break; + } + + lockArray(gl, vertexCount); + + // Note: using MultiDrawElements is probably more expensive than + // not in this case due to the need to allocate more temporary + // direct buffers and slice up the incoming indices array + int offset = initialIndexIndex; + IntBuffer indicesBuffer = IntBuffer.wrap(indexCoord); + for (int i = 0; i < strip_len; i++) { + indicesBuffer.position(offset); + int count = sarray[i]; + gl.glDrawElements(primType, count, GL.GL_UNSIGNED_INT, indicesBuffer); + offset += count; + } + } else if ((geo_type == GeometryRetained.GEO_TYPE_INDEXED_QUAD_SET) || + (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_SET) || + (geo_type == GeometryRetained.GEO_TYPE_INDEXED_POINT_SET) || + (geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_SET)) { + // Note we can use interleaved arrays even if we have a + // non-null xform since we use the same data layout unlike the + // C code + if (ignoreVertexColors || + (((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) && ((texCoordSetMapLen > 1) || + (texCoordSetCount > 1)))) { + useInterleavedArrays = false; + } else { + boolean[] tmp = new boolean[1]; + int[] tmp2 = new int[1]; + testForInterleavedArrays(vformat, tmp, tmp2); + useInterleavedArrays = tmp[0]; + iaFormat = tmp2[0]; + } + + if (useInterleavedArrays) { + verts.position(0); + gl.glInterleavedArrays(iaFormat, bstride, verts); + } else { + if ((vformat & GeometryArray.NORMALS) != 0) { + verts.position(normoff); + gl.glNormalPointer(GL.GL_FLOAT, bstride, verts); + } + + if (!ignoreVertexColors && ((vformat & GeometryArray.COLOR) != 0)) { + verts.position(coloroff); + if (((vformat & GeometryArray.WITH_ALPHA) != 0) || useAlpha) { + gl.glColorPointer(4, GL.GL_FLOAT, bstride, verts); + } else { + gl.glColorPointer(3, GL.GL_FLOAT, bstride, verts); + } + } + if ((vformat & GeometryArray.COORDINATES) != 0) { + verts.position(coordoff); + gl.glVertexPointer(3, GL.GL_FLOAT, bstride, verts); + } + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + executeTexture(texCoordSetMapLen, + texSize, bstride, texCoordoff, + texCoordSetMapOffset, + texCoordSetMapLen, + verts, gl); + } + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + int vAttrOffset = vAttrOff; + for (int i = 0; i < vertexAttrCount; i++) { + ctx.enableVertexAttrArray(gl, i); + verts.position(vAttrOffset); + ctx.vertexAttrPointer(gl, i, vertexAttrSizes[i], + GL.GL_FLOAT, bstride, verts); + vAttrOffset += vertexAttrSizes[i]; + } + } + + switch (geo_type) { + case GeometryRetained.GEO_TYPE_INDEXED_QUAD_SET : + primType = GL.GL_QUADS; + break; + case GeometryRetained.GEO_TYPE_INDEXED_TRI_SET : + primType = GL.GL_TRIANGLES; + break; + case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET : + primType = GL.GL_POINTS; + break; + case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET : + primType = GL.GL_LINES; + break; + } + + lockArray(gl, vertexCount); + + IntBuffer indicesBuffer = IntBuffer.wrap(indexCoord); + indicesBuffer.position(initialIndexIndex); + gl.glDrawElements(primType, validIndexCount, GL.GL_UNSIGNED_INT, indicesBuffer); + } + } + + unlockArray(gl); + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + resetVertexAttrs(gl, ctx, vertexAttrCount); + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + resetTexture(gl, ctx); + } + } + + + //---------------------------------------------------------------------- + // + // Helper routines for IndexedGeometryArrayRetained + // + + private void executeIndexedGeometryArray(Context absCtx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + float[] varray, FloatBuffer vdata, float[] carray, + int cDirty, + int[] indexCoord) { + JoglContext ctx = (JoglContext) absCtx; + GL gl = context(ctx).getGL(); + + boolean useInterleavedArrays; + int iaFormat = 0; + int primType = 0; + int stride = 0, coordoff = 0, normoff = 0, coloroff = 0, texCoordoff = 0; + int texSize = 0, texStride = 0; + int vAttrOff = 0; + int vAttrStride = 0; + int bstride = 0, cbstride = 0; + FloatBuffer verts = null; + FloatBuffer clrs = null; + int[] sarray = null; + int strip_len = 0; + + if ((vformat & GeometryArray.COORDINATES) != 0) { + stride += 3; + } + if ((vformat & GeometryArray.NORMALS) != 0) { + stride += 3; + coordoff += 3; + } + + if ((vformat & GeometryArray.COLOR) != 0) { + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + stride += 4; + normoff += 4; + coordoff += 4; + } else { // Handle the case of executeInterleaved 3f + stride += 3; + normoff += 3; + coordoff += 3; + } + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + if ((vformat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { + texSize = 2; + texStride = 2 * texCoordSetCount; + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { + texSize = 3; + texStride = 3 * texCoordSetCount; + } else if ((vformat & GeometryArray.TEXTURE_COORDINATE_4) != 0) { + texSize = 4; + texStride = 4 * texCoordSetCount; + } + stride += texStride; + normoff += texStride; + coloroff += texStride; + coordoff += texStride; + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + vAttrStride += vertexAttrSizes[i]; + } + stride += vAttrStride; + normoff += vAttrStride; + coloroff += vAttrStride; + coordoff += vAttrStride; + texCoordoff += vAttrStride; + } + + bstride = stride * BufferUtil.SIZEOF_FLOAT; + + if (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET) { + sarray = ((IndexedGeometryStripArrayRetained) geo).stripIndexCounts; + strip_len = sarray.length; + } + + // We have to copy if the data isn't specified using NIO + if (varray != null) { + verts = getVertexArrayBuffer(varray); + } else if (vdata != null) { + verts = vdata; + } else { + // This should never happen + throw new AssertionError("Unable to get vertex pointer"); + } + + // using byRef interleaved array and has a separate pointer, then .. + int cstride = stride; + if (carray != null) { + clrs = getColorArrayBuffer(carray); + cstride = 4; + } else { + // FIXME: need to "auto-slice" this buffer later + clrs = verts; + } + + cbstride = cstride * BufferUtil.SIZEOF_FLOAT; + + // Enable normalize for non-uniform scale (which rescale can't handle) + if (isNonUniformScale) { + gl.glEnable(GL.GL_NORMALIZE); + } + + /*** Handle non-indexed strip GeometryArray first *******/ + if (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET) { + if (ignoreVertexColors || (carray != null) || + ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0 && ((texCoordSetMapLen > 1) || + (texCoordSetCount > 1)))) { + useInterleavedArrays = false; + } else { + boolean[] tmp = new boolean[1]; + int[] tmp2 = new int[1]; + testForInterleavedArrays(vformat, tmp, tmp2); + useInterleavedArrays = tmp[0]; + iaFormat = tmp2[0]; + } + if (useInterleavedArrays) { + verts.position(0); + gl.glInterleavedArrays(iaFormat, bstride, verts); + } else { + if ((vformat & GeometryArray.NORMALS) != 0) { + verts.position(normoff); + gl.glNormalPointer(GL.GL_FLOAT, bstride, verts); + } + if (!ignoreVertexColors && (vformat & GeometryArray.COLOR) != 0) { + if (clrs == verts) { + clrs.position(coloroff); + } + if ((vformat & GeometryArray.WITH_ALPHA) != 0 || useAlpha) { + gl.glColorPointer(4, GL.GL_FLOAT, cbstride, clrs); + } else { + gl.glColorPointer(3, GL.GL_FLOAT, cbstride, clrs); + } + } + if ((vformat & GeometryArray.COORDINATES) != 0) { + verts.position(coordoff); + gl.glVertexPointer(3, GL.GL_FLOAT, bstride, verts); + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + /* XXXX: texCoordoff == 0 ???*/ + executeTexture(texCoordSetMapLen, + texSize, bstride, texCoordoff, + texCoordSetOffset, + numActiveTexUnitState, + verts, gl); + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + int vAttrOffset = vAttrOff; + for (int i = 0; i < vertexAttrCount; i++) { + ctx.enableVertexAttrArray(gl, i); + verts.position(vAttrOffset); + ctx.vertexAttrPointer(gl, i, vertexAttrSizes[i], + GL.GL_FLOAT, bstride, verts); + vAttrOffset += vertexAttrSizes[i]; + } + } + } + + switch (geo_type) { + case GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET: + primType = GL.GL_TRIANGLE_STRIP; + break; + case GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET: + primType = GL.GL_TRIANGLE_FAN; + break; + case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET: + primType = GL.GL_LINE_STRIP; + break; + } + + lockArray(gl, vertexCount); + + // Note: using MultiDrawElements is probably more expensive than + // not in this case due to the need to allocate more temporary + // direct buffers and slice up the incoming indices array + int offset = initialIndexIndex; + IntBuffer indicesBuffer = IntBuffer.wrap(indexCoord); + for (int i = 0; i < strip_len; i++) { + indicesBuffer.position(offset); + int count = sarray[i]; + gl.glDrawElements(primType, count, GL.GL_UNSIGNED_INT, indicesBuffer); + offset += count; + } + } else if ((geo_type == GeometryRetained.GEO_TYPE_INDEXED_QUAD_SET) || + (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_SET) || + (geo_type == GeometryRetained.GEO_TYPE_INDEXED_POINT_SET) || + (geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_SET)) { + /******* Handle non-indexed non-striped GeometryArray now *****/ + if (ignoreVertexColors || (carray != null) || + ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0 && ((texCoordSetMapLen > 1) || + (texCoordSetCount > 1)))) { + useInterleavedArrays = false; + } else { + boolean[] tmp = new boolean[1]; + int[] tmp2 = new int[1]; + testForInterleavedArrays(vformat, tmp, tmp2); + useInterleavedArrays = tmp[0]; + iaFormat = tmp2[0]; + } + + if (useInterleavedArrays) { + verts.position(0); + gl.glInterleavedArrays(iaFormat, bstride, verts); + } else { + if ((vformat & GeometryArray.NORMALS) != 0) { + verts.position(normoff); + gl.glNormalPointer(GL.GL_FLOAT, bstride, verts); + } + + if (!ignoreVertexColors && (vformat & GeometryArray.COLOR) != 0) { + if (clrs == verts) { + clrs.position(coloroff); + } + if ((vformat & GeometryArray.WITH_ALPHA) != 0 || useAlpha) { + gl.glColorPointer(4, GL.GL_FLOAT, cbstride, clrs); + } else { + gl.glColorPointer(3, GL.GL_FLOAT, cbstride, clrs); + } + } + if ((vformat & GeometryArray.COORDINATES) != 0) { + verts.position(coordoff); + gl.glVertexPointer(3, GL.GL_FLOAT, bstride, verts); + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + /* XXXX: texCoordoff == 0 ???*/ + executeTexture(texCoordSetMapLen, + texSize, bstride, texCoordoff, + texCoordSetOffset, + numActiveTexUnitState, + verts, gl); + } + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + int vAttrOffset = vAttrOff; + for (int i = 0; i < vertexAttrCount; i++) { + ctx.enableVertexAttrArray(gl, i); + verts.position(vAttrOffset); + ctx.vertexAttrPointer(gl, i, vertexAttrSizes[i], + GL.GL_FLOAT, bstride, verts); + vAttrOffset += vertexAttrSizes[i]; + } + } + } + + lockArray(gl, vertexCount); + IntBuffer buf = IntBuffer.wrap(indexCoord); + buf.position(initialIndexIndex); + switch (geo_type){ + case GeometryRetained.GEO_TYPE_INDEXED_QUAD_SET : gl.glDrawElements(GL.GL_QUADS, indexCount, GL.GL_UNSIGNED_INT, buf); break; + case GeometryRetained.GEO_TYPE_INDEXED_TRI_SET : gl.glDrawElements(GL.GL_TRIANGLES, indexCount, GL.GL_UNSIGNED_INT, buf); break; + case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET: gl.glDrawElements(GL.GL_POINTS, indexCount, GL.GL_UNSIGNED_INT, buf); break; + case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET : gl.glDrawElements(GL.GL_LINES, indexCount, GL.GL_UNSIGNED_INT, buf); break; + } + } + + unlockArray(gl); + + if ((vformat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + resetVertexAttrs(gl, ctx, vertexAttrCount); + } + + if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { + resetTexture(gl, ctx); + } + + // clean up if we turned on normalize + if (isNonUniformScale) { + gl.glDisable(GL.GL_NORMALIZE); + } + } + + + private void executeIndexedGeometryArrayVA(Context absCtx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, int vformat, int vdefined, + FloatBuffer fverts, DoubleBuffer dverts, + FloatBuffer fclrs, ByteBuffer bclrs, + FloatBuffer norms, + int vertexAttrCount, int[] vertexAttrSizes, FloatBuffer[] vertexAttrBufs, + int texCoordSetCount, int[] texCoordSetMap, + int numActiveTexUnitState, + int texStride, + FloatBuffer[] texCoords, + int cDirty, int[] indexCoord, int[] sarray, int strip_len) { + JoglContext ctx = (JoglContext) absCtx; + GL gl = context(ctx).getGL(); + + boolean floatCoordDefined = ((vdefined & GeometryArrayRetained.COORD_FLOAT) != 0); + boolean doubleCoordDefined = ((vdefined & GeometryArrayRetained.COORD_DOUBLE) != 0); + boolean floatColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_FLOAT) != 0); + boolean byteColorsDefined = ((vdefined & GeometryArrayRetained.COLOR_BYTE) != 0); + boolean normalsDefined = ((vdefined & GeometryArrayRetained.NORMAL_FLOAT) != 0); + boolean vattrDefined = ((vdefined & GeometryArrayRetained.VATTR_FLOAT) != 0); + boolean textureDefined = ((vdefined & GeometryArrayRetained.TEXCOORD_FLOAT) != 0); + + // Enable normalize for non-uniform scale (which rescale can't handle) + if (isNonUniformScale) { + gl.glEnable(GL.GL_NORMALIZE); + } + + // Define the data pointers + if (floatCoordDefined) { + fverts.position(0); + gl.glVertexPointer(3, GL.GL_FLOAT, 0, fverts); + } else if (doubleCoordDefined){ + dverts.position(0); + gl.glVertexPointer(3, GL.GL_DOUBLE, 0, dverts); + } + if (floatColorsDefined) { + fclrs.position(0); + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + gl.glColorPointer(4, GL.GL_FLOAT, 0, fclrs); + } else { + gl.glColorPointer(3, GL.GL_FLOAT, 0, fclrs); + } + } else if (byteColorsDefined) { + bclrs.position(0); + if ((vformat & GeometryArray.WITH_ALPHA) != 0) { + gl.glColorPointer(4, GL.GL_UNSIGNED_BYTE, 0, bclrs); + } else { + gl.glColorPointer(3, GL.GL_UNSIGNED_BYTE, 0, bclrs); + } + } + if (normalsDefined) { + norms.position(0); + gl.glNormalPointer(GL.GL_FLOAT, 0, norms); + } + + if (vattrDefined) { + for (int i = 0; i < vertexAttrCount; i++) { + FloatBuffer vertexAttrs = vertexAttrBufs[i]; + int sz = vertexAttrSizes[i]; + ctx.enableVertexAttrArray(gl, i); + vertexAttrs.position(0); + ctx.vertexAttrPointer(gl, i, sz, GL.GL_FLOAT, 0, vertexAttrs); + } + } + + if (textureDefined) { + int texSet = 0; + for (int i = 0; i < numActiveTexUnitState; i++) { + if ((i < texCoordSetCount) && + ((texSet = texCoordSetMap[i]) != -1)) { + FloatBuffer buf = texCoords[texSet]; + buf.position(0); + enableTexCoordPointer(gl, i, texStride, + GL.GL_FLOAT, 0, buf); + } else { + disableTexCoordPointer(gl, i); + } + } + + // Reset client active texture unit to 0 + clientActiveTextureUnit(gl, 0); + } + + lockArray(gl, vertexCount); + + if (geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET || + geo_type == GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET) { + int primType = 0; + switch (geo_type) { + case GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET: + primType = GL.GL_TRIANGLE_STRIP; + break; + case GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET: + primType = GL.GL_TRIANGLE_FAN; + break; + case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET: + primType = GL.GL_LINE_STRIP; + break; + } + + // Note: using MultiDrawElements is probably more expensive than + // not in this case due to the need to allocate more temporary + // direct buffers and slice up the incoming indices array + int offset = initialIndexIndex; + IntBuffer indicesBuffer = IntBuffer.wrap(indexCoord); + for (int i = 0; i < strip_len; i++) { + indicesBuffer.position(offset); + int count = sarray[i]; + gl.glDrawElements(primType, count, GL.GL_UNSIGNED_INT, indicesBuffer); + offset += count; + } + } else { + IntBuffer buf = IntBuffer.wrap(indexCoord); + buf.position(initialIndexIndex); + switch (geo_type){ + case GeometryRetained.GEO_TYPE_INDEXED_QUAD_SET : gl.glDrawElements(GL.GL_QUADS, validIndexCount, GL.GL_UNSIGNED_INT, buf); break; + case GeometryRetained.GEO_TYPE_INDEXED_TRI_SET : gl.glDrawElements(GL.GL_TRIANGLES, validIndexCount, GL.GL_UNSIGNED_INT, buf); break; + case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET: gl.glDrawElements(GL.GL_POINTS, validIndexCount, GL.GL_UNSIGNED_INT, buf); break; + case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET : gl.glDrawElements(GL.GL_LINES, validIndexCount, GL.GL_UNSIGNED_INT, buf); break; + } + } + + unlockArray(gl); + + // clean up if we turned on normalize + if (isNonUniformScale) { + gl.glDisable(GL.GL_NORMALIZE); + } + + if (vattrDefined) { + resetVertexAttrs(gl, ctx, vertexAttrCount); + } + + if (textureDefined) { + resetTexture(gl, ctx); + } + } + + + // --------------------------------------------------------------------- + + // + // GraphicsContext3D methods + // + + // Native method for readRaster + void readRaster(Context ctx, + int type, int xSrcOffset, int ySrcOffset, + int width, int height, int hCanvas, + int imageDataType, + int imageFormat, + Object imageBuffer, + int depthFormat, + Object depthBuffer) { + + GL gl = context(ctx).getGL(); + gl.glPixelStorei(GL.GL_PACK_ROW_LENGTH, width); + gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1); + int yAdjusted = hCanvas - height - ySrcOffset; + + if ((type & Raster.RASTER_COLOR) != 0) { + int oglFormat = 0; + if(imageDataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY) { + + switch (imageFormat) { + case ImageComponentRetained.TYPE_BYTE_BGR: + oglFormat = GL.GL_BGR; + break; + case ImageComponentRetained.TYPE_BYTE_RGB: + oglFormat = GL.GL_RGB; + break; + case ImageComponentRetained.TYPE_BYTE_ABGR: + if (gl.isExtensionAvailable("GL_EXT_abgr")) { // If its zero, should never come here! + oglFormat = GL.GL_ABGR_EXT; + } else { + assert false; + return; + } + break; + case ImageComponentRetained.TYPE_BYTE_RGBA: + // all RGB types are stored as RGBA + oglFormat = GL.GL_RGBA; + break; + case ImageComponentRetained.TYPE_BYTE_LA: + // all LA types are stored as LA8 + oglFormat = GL.GL_LUMINANCE_ALPHA; + break; + case ImageComponentRetained.TYPE_BYTE_GRAY: + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_INT_BGR: + case ImageComponentRetained.TYPE_INT_RGB: + case ImageComponentRetained.TYPE_INT_ARGB: + default: + assert false; + return; + } + + gl.glReadPixels(xSrcOffset, yAdjusted, width, height, + oglFormat, GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap((byte[]) imageBuffer)); + + + } else if(imageDataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_ARRAY) { + int intType = GL.GL_UNSIGNED_INT_8_8_8_8; + boolean forceAlphaToOne = false; + + switch (imageFormat) { + /* GL_BGR */ + case ImageComponentRetained.TYPE_INT_BGR: /* Assume XBGR format */ + oglFormat = GL.GL_RGBA; + intType = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + forceAlphaToOne = true; + break; + case ImageComponentRetained.TYPE_INT_RGB: /* Assume XRGB format */ + forceAlphaToOne = true; + /* Fall through to next case */ + case ImageComponentRetained.TYPE_INT_ARGB: + oglFormat = GL.GL_BGRA; + intType = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + break; + /* This method only supports 3 and 4 components formats and INT types. */ + case ImageComponentRetained.TYPE_BYTE_LA: + case ImageComponentRetained.TYPE_BYTE_GRAY: + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_BYTE_BGR: + case ImageComponentRetained.TYPE_BYTE_RGB: + case ImageComponentRetained.TYPE_BYTE_RGBA: + case ImageComponentRetained.TYPE_BYTE_ABGR: + default: + assert false; + return; + } + + /* Force Alpha to 1.0 if needed */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 0.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 1.0f); + } + + gl.glReadPixels(xSrcOffset, yAdjusted, width, height, + oglFormat, intType, IntBuffer.wrap((int[]) imageBuffer)); + + /* Restore Alpha scale and bias */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 1.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 0.0f); + } + + } else { + assert false; + } + } + + if ((type & Raster.RASTER_DEPTH) != 0) { + + if (depthFormat == DepthComponentRetained.DEPTH_COMPONENT_TYPE_INT) { + // yOffset is adjusted for OpenGL - Y upward + gl.glReadPixels(xSrcOffset, yAdjusted, width, height, + GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_INT, IntBuffer.wrap((int[]) depthBuffer)); + } else { + // DEPTH_COMPONENT_TYPE_FLOAT + // yOffset is adjusted for OpenGL - Y upward + gl.glReadPixels(xSrcOffset, yAdjusted, width, height, + GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, FloatBuffer.wrap((float[]) depthBuffer)); + } + } + + } + + // --------------------------------------------------------------------- + + // + // CgShaderProgramRetained methods + // + + // ShaderAttributeValue methods + + ShaderError setCgUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform1i()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgSetParameter1i(param.vParam(), value); + } + + if (param.fParam() != null) { + CgGL.cgSetParameter1i(param.fParam(), value); + } + + return null; + } + + ShaderError setCgUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform1f()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgSetParameter1f(param.vParam(), value); + } + + if (param.fParam() != null) { + CgGL.cgSetParameter1f(param.fParam(), value); + } + + return null; + } + + ShaderError setCgUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform2i()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgSetParameter2i(param.vParam(), value[0], value[1]); + } + + if (param.fParam() != null) { + CgGL.cgSetParameter2i(param.fParam(), value[0], value[1]); + } + + return null; + } + + ShaderError setCgUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform2f()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgSetParameter2f(param.vParam(), value[0], value[1]); + } + + if (param.fParam() != null) { + CgGL.cgSetParameter2f(param.fParam(), value[0], value[1]); + } + + return null; + } + + ShaderError setCgUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform3i()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgSetParameter3i(param.vParam(), value[0], value[1], value[2]); + } + + if (param.fParam() != null) { + CgGL.cgSetParameter3i(param.fParam(), value[0], value[1], value[2]); + } + + return null; + } + + ShaderError setCgUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform3f()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgSetParameter3f(param.vParam(), value[0], value[1], value[2]); + } + + if (param.fParam() != null) { + CgGL.cgSetParameter3f(param.fParam(), value[0], value[1], value[2]); + } + + return null; + } + + ShaderError setCgUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform4i()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgSetParameter4i(param.vParam(), value[0], value[1], value[2], value[3]); + } + + if (param.fParam() != null) { + CgGL.cgSetParameter4i(param.fParam(), value[0], value[1], value[2], value[3]); + } + + return null; + } + + ShaderError setCgUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform4f()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgSetParameter4f(param.vParam(), value[0], value[1], value[2], value[3]); + } + + if (param.fParam() != null) { + CgGL.cgSetParameter4f(param.fParam(), value[0], value[1], value[2], value[3]); + } + + return null; + } + + ShaderError setCgUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniformMatrix3f()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetMatrixParameterfr(param.vParam(), value, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetMatrixParameterfr(param.fParam(), value, 0); + } + + return null; + } + + ShaderError setCgUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniformMatrix4f()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetMatrixParameterfr(param.vParam(), value, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetMatrixParameterfr(param.fParam(), value, 0); + } + + return null; + } + + // ShaderAttributeArray methods + + ShaderError setCgUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform1iArray()"); + + float[] fval = new float[value.length]; + for (int i = 0; i < value.length; i++) { + fval[i] = value[i]; + } + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetParameterArray1f(param.vParam(), 0, numElements, fval, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetParameterArray1f(param.fParam(), 0, numElements, fval, 0); + } + + return null; + } + + ShaderError setCgUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform1fArray()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetParameterArray1f(param.vParam(), 0, numElements, value, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetParameterArray1f(param.fParam(), 0, numElements, value, 0); + } + + return null; + } + + ShaderError setCgUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform2iArray()"); + + float[] fval = new float[value.length]; + for (int i = 0; i < value.length; i++) { + fval[i] = value[i]; + } + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetParameterArray2f(param.vParam(), 0, numElements, fval, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetParameterArray2f(param.fParam(), 0, numElements, fval, 0); + } + + return null; + } + + ShaderError setCgUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform2fArray()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetParameterArray2f(param.vParam(), 0, numElements, value, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetParameterArray2f(param.fParam(), 0, numElements, value, 0); + } + + return null; + } + + ShaderError setCgUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform3iArray()"); + + float[] fval = new float[value.length]; + for (int i = 0; i < value.length; i++) { + fval[i] = value[i]; + } + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetParameterArray3f(param.vParam(), 0, numElements, fval, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetParameterArray3f(param.fParam(), 0, numElements, fval, 0); + } + + return null; + } + + ShaderError setCgUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform3fArray()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetParameterArray2f(param.vParam(), 0, numElements, value, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetParameterArray2f(param.fParam(), 0, numElements, value, 0); + } + + return null; + } + + ShaderError setCgUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform4iArray()"); + + float[] fval = new float[value.length]; + for (int i = 0; i < value.length; i++) { + fval[i] = value[i]; + } + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetParameterArray4f(param.vParam(), 0, numElements, fval, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetParameterArray4f(param.fParam(), 0, numElements, fval, 0); + } + + return null; + } + + ShaderError setCgUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniform4fArray()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetParameterArray2f(param.vParam(), 0, numElements, value, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetParameterArray2f(param.fParam(), 0, numElements, value, 0); + } + + return null; + } + + ShaderError setCgUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniformMatrix3fArray()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetMatrixParameterArrayfr(param.vParam(), 0, numElements, value, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetMatrixParameterArrayfr(param.fParam(), 0, numElements, value, 0); + } + + return null; + } + + ShaderError setCgUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setCgUniformMatrix4fArray()"); + + JoglCgShaderParameter param = (JoglCgShaderParameter) uniformLocation; + if (param.vParam() != null) { + CgGL.cgGLSetMatrixParameterArrayfr(param.vParam(), 0, numElements, value, 0); + } + + if (param.fParam() != null) { + CgGL.cgGLSetMatrixParameterArrayfr(param.fParam(), 0, numElements, value, 0); + } + + return null; + } + + // interfaces for shader compilation, etc. + ShaderError createCgShader(Context ctx, int shaderType, ShaderId[] shaderId) { + if (VERBOSE) System.err.println("JoglPipeline.createCgShader()"); + + JoglContext jctx = (JoglContext) ctx; + JoglCgShaderInfo info = new JoglCgShaderInfo(); + info.setJ3DShaderType(shaderType); + if (shaderType == Shader.SHADER_TYPE_VERTEX) { + info.setShaderProfile(jctx.getCgVertexProfile()); + } else if (shaderType == Shader.SHADER_TYPE_FRAGMENT) { + info.setShaderProfile(jctx.getCgFragmentProfile()); + } else { + throw new AssertionError("unrecognized shaderType " + shaderType); + } + shaderId[0] = info; + return null; + } + ShaderError destroyCgShader(Context ctx, ShaderId shaderId) { + if (VERBOSE) System.err.println("JoglPipeline.destroyCgShader()"); + + JoglCgShaderInfo info = (JoglCgShaderInfo) shaderId; + CGprogram program = info.getCgShader(); + if (program != null) { + CgGL.cgDestroyProgram(program); + } + return null; + } + ShaderError compileCgShader(Context ctx, ShaderId shaderId, String programString) { + if (VERBOSE) System.err.println("JoglPipeline.compileCgShader()"); + + if (programString == null) + throw new AssertionError("shader program string is null"); + JoglCgShaderInfo info = (JoglCgShaderInfo) shaderId; + JoglContext jctx = (JoglContext) ctx; + CGprogram program = CgGL.cgCreateProgram(jctx.getCgContext(), + CgGL.CG_SOURCE, + programString, + info.getShaderProfile(), + null, + null); + int lastError = 0; + if ((lastError = CgGL.cgGetError()) != 0) { + ShaderError err = new ShaderError(ShaderError.COMPILE_ERROR, + "Cg shader compile error"); + err.setDetailMessage(getCgErrorLog(jctx, lastError)); + return err; + } + info.setCgShader(program); + return null; + } + + ShaderError createCgShaderProgram(Context ctx, ShaderProgramId[] shaderProgramId) { + if (VERBOSE) System.err.println("JoglPipeline.createCgShaderProgram()"); + + JoglCgShaderProgramInfo info = new JoglCgShaderProgramInfo(); + shaderProgramId[0] = info; + return null; + } + ShaderError destroyCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + if (VERBOSE) System.err.println("JoglPipeline.destroyCgShaderProgram()"); + // Nothing to do in pure Java port + return null; + } + ShaderError linkCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId, + ShaderId[] shaderIds) { + if (VERBOSE) System.err.println("JoglPipeline.linkCgShaderProgram()"); + + JoglCgShaderProgramInfo shaderProgramInfo = (JoglCgShaderProgramInfo) shaderProgramId; + // NOTE: we assume that the caller has already verified that there + // is at most one vertex program and one fragment program + shaderProgramInfo.setVertexShader(null); + shaderProgramInfo.setFragmentShader(null); + for (int i = 0; i < shaderIds.length; i++) { + JoglCgShaderInfo shader = (JoglCgShaderInfo) shaderIds[i]; + if (shader.getJ3DShaderType() == Shader.SHADER_TYPE_VERTEX) { + shaderProgramInfo.setVertexShader(shader); + } else { + shaderProgramInfo.setFragmentShader(shader); + } + + CgGL.cgGLLoadProgram(shader.getCgShader()); + int lastError = 0; + if ((lastError = CgGL.cgGetError()) != 0) { + ShaderError err = new ShaderError(ShaderError.LINK_ERROR, + "Cg shader link/load error"); + err.setDetailMessage(getCgErrorLog((JoglContext) ctx, + lastError)); + return err; + } + + CgGL.cgGLBindProgram(shader.getCgShader()); + if ((lastError = CgGL.cgGetError()) != 0) { + ShaderError err = new ShaderError(ShaderError.LINK_ERROR, + "Cg shader link/bind error"); + err.setDetailMessage(getCgErrorLog((JoglContext) ctx, + lastError)); + return err; + } + } + + return null; + } + void lookupCgVertexAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, boolean[] errArr) { + if (VERBOSE) System.err.println("JoglPipeline.lookupCgVertexAttrNames()"); + + JoglCgShaderProgramInfo shaderProgramInfo = (JoglCgShaderProgramInfo) shaderProgramId; + if (shaderProgramInfo.getVertexShader() == null) { + // If there if no vertex shader, no attributes can be looked up, so all fail + for (int i = 0; i < errArr.length; i++) { + errArr[i] = false; + } + return; + } + + shaderProgramInfo.setVertexAttributes(new CGparameter[numAttrNames]); + for (int i = 0; i < numAttrNames; i++) { + String attrName = attrNames[i]; + shaderProgramInfo.getVertexAttributes()[i] = + CgGL.cgGetNamedParameter(shaderProgramInfo.getVertexShader().getCgShader(), + attrName); + if (shaderProgramInfo.getVertexAttributes()[i] == null) { + errArr[i] = true; + } + } + } + void lookupCgShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, ShaderAttrLoc[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr) { + if (VERBOSE) System.err.println("JoglPipeline.lookupCgShaderAttrNames()"); + + JoglCgShaderProgramInfo shaderProgramInfo = + (JoglCgShaderProgramInfo) shaderProgramId; + + // Set the loc, type, and size arrays to out-of-bounds values + for (int i = 0; i < numAttrNames; i++) { + locArr[i] = null; + typeArr[i] = -1; + sizeArr[i] = -1; + } + + int[] vType = new int[1]; + int[] vSize = new int[1]; + boolean[] vIsArray = new boolean[1]; + int[] fType = new int[1]; + int[] fSize = new int[1]; + boolean[] fIsArray = new boolean[1]; + + boolean err = false; + + // Now lookup the location of each name in the attrNames array + for (int i = 0; i < numAttrNames; i++) { + String attrName = attrNames[i]; + // Get uniform attribute location -- note that we need to + // lookup the name in both the vertex and fragment shader + // (although we will generalize it to look at the list of "N" + // shaders). If all parameter locations are NULL, then no + // struct will be allocated and -1 will be stored for this + // attribute. If there is more than one non-NULL parameter, + // then all must be of the same type and dimensionality, + // otherwise an error will be generated and -1 will be stored + // for this attribute. If all non-NULL parameters are of the + // same type and dimensionality, then a struct is allocated + // containing the list of parameters. + // + // When any of the setCgUniform methods are called, the + // attribute will be set for each parameter in the list. + CGparameter vLoc = null; + if (shaderProgramInfo.getVertexShader() != null) { + vLoc = lookupCgParams(shaderProgramInfo.getVertexShader(), + attrName, + vType, vSize, vIsArray); + if (vLoc != null) { + sizeArr[i] = vSize[0]; + isArrayArr[i] = vIsArray[0]; + typeArr[i] = cgToJ3dType(vType[0]); + } + } + + CGparameter fLoc = null; + if (shaderProgramInfo.getVertexShader() != null) { + fLoc = lookupCgParams(shaderProgramInfo.getFragmentShader(), + attrName, + fType, fSize, fIsArray); + if (fLoc != null) { + sizeArr[i] = fSize[0]; + isArrayArr[i] = fIsArray[0]; + typeArr[i] = cgToJ3dType(fType[0]); + } + } + + // If the name lookup found an entry in both vertex and + // fragment program, verify that the type and size are the + // same. + if (vLoc != null && fLoc != null) { + if (vType != fType || vSize != fSize || vIsArray != fIsArray) { + // TODO: the following needs to be propagated to ShaderError + System.err.println("JAVA 3D : error shader attribute type mismatch: " + attrName); + System.err.println(" 1 : type = " + vType[0] + ", size = " + vSize[0] + ", isArray = " + vIsArray[0]); + System.err.println(" 0 : type = " + fType[0] + ", size = " + fSize[0] + ", isArray = " + fIsArray[0]); + err = true; + } + } + + // Report an error if we got a mismatch or if the attribute + // was not found in either the vertex or the fragment program + if (err || (vLoc == null && fLoc == null)) { + // TODO: distinguish between (err) and (vParam and fParam both NULL) + // so we can report a more helpful error message + // locPtr[i] = (jlong)-1; + } else { + // TODO: need to store the cgParamInfo pointers in the + // shader program so we can free them later. + // + // NOTE: WE CURRENTLY HAVE A MEMORY LEAK. + locArr[i] = new JoglCgShaderParameter(vLoc, fLoc); + } + } + } + + ShaderError useCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + if (VERBOSE) System.err.println("JoglPipeline.useCgShaderProgram()"); + + JoglCgShaderProgramInfo shaderProgramInfo = + (JoglCgShaderProgramInfo) shaderProgramId; + JoglContext jctx = (JoglContext) ctx; + + // Disable shader profiles + CgGL.cgGLDisableProfile(jctx.getCgVertexProfile()); + CgGL.cgGLDisableProfile(jctx.getCgFragmentProfile()); + if (shaderProgramInfo != null) { + if (shaderProgramInfo.getVertexShader() != null) { + CgGL.cgGLBindProgram(shaderProgramInfo.getVertexShader().getCgShader()); + CgGL.cgGLEnableProfile(shaderProgramInfo.getVertexShader().getShaderProfile()); + } else { + CgGL.cgGLUnbindProgram(jctx.getCgVertexProfile()); + } + + if (shaderProgramInfo.getFragmentShader() != null) { + CgGL.cgGLBindProgram(shaderProgramInfo.getFragmentShader().getCgShader()); + CgGL.cgGLEnableProfile(shaderProgramInfo.getFragmentShader().getShaderProfile()); + } else { + CgGL.cgGLUnbindProgram(jctx.getCgFragmentProfile()); + } + } else { + CgGL.cgGLUnbindProgram(jctx.getCgVertexProfile()); + CgGL.cgGLUnbindProgram(jctx.getCgFragmentProfile()); + } + + jctx.setShaderProgram(shaderProgramInfo); + return null; + } + + // + // Helper methods for above + // + private String getCgErrorLog(JoglContext ctx, int lastError) { + if (lastError == 0) + throw new AssertionError("lastError == 0"); + String errString = CgGL.cgGetErrorString(lastError); + String listing = CgGL.cgGetLastListing(ctx.getCgContext()); + return (errString + System.getProperty("line.separator") + listing); + } + + private int cgToJ3dType(int type) { + switch (type) { + case CgGL.CG_BOOL: + case CgGL.CG_BOOL1: + case CgGL.CG_FIXED: + case CgGL.CG_FIXED1: + case CgGL.CG_HALF: + case CgGL.CG_HALF1: + case CgGL.CG_INT: + case CgGL.CG_INT1: + return ShaderAttributeObjectRetained.TYPE_INTEGER; + + // XXXX: add ShaderAttribute support for setting samplers. In the + // mean time, the binding between sampler and texture unit will + // need to be specified in the shader itself (which it already is + // in most example shaders). + // + // case CgGL.CG_SAMPLER2D: + // case CgGL.CG_SAMPLER3D: + // case CgGL.CG_SAMPLERCUBE: + + case CgGL.CG_BOOL2: + case CgGL.CG_FIXED2: + case CgGL.CG_HALF2: + case CgGL.CG_INT2: + return ShaderAttributeObjectRetained.TYPE_TUPLE2I; + + case CgGL.CG_BOOL3: + case CgGL.CG_FIXED3: + case CgGL.CG_HALF3: + case CgGL.CG_INT3: + return ShaderAttributeObjectRetained.TYPE_TUPLE3I; + + case CgGL.CG_BOOL4: + case CgGL.CG_FIXED4: + case CgGL.CG_HALF4: + case CgGL.CG_INT4: + return ShaderAttributeObjectRetained.TYPE_TUPLE4I; + + case CgGL.CG_FLOAT: + case CgGL.CG_FLOAT1: + return ShaderAttributeObjectRetained.TYPE_FLOAT; + + case CgGL.CG_FLOAT2: + return ShaderAttributeObjectRetained.TYPE_TUPLE2F; + + case CgGL.CG_FLOAT3: + return ShaderAttributeObjectRetained.TYPE_TUPLE3F; + + case CgGL.CG_FLOAT4: + return ShaderAttributeObjectRetained.TYPE_TUPLE4F; + + case CgGL.CG_FLOAT3x3: + return ShaderAttributeObjectRetained.TYPE_MATRIX3F; + + case CgGL.CG_FLOAT4x4: + return ShaderAttributeObjectRetained.TYPE_MATRIX4F; + + // Java 3D does not support the following sampler types: + // + // case CgGL.CG_SAMPLER1D: + // case CgGL.CG_SAMPLERRECT: + } + + return -1; + } + + private CGparameter lookupCgParams(JoglCgShaderInfo shader, + String attrNameString, + int[] type, + int[] size, + boolean[] isArray) { + CGparameter loc = CgGL.cgGetNamedParameter(shader.getCgShader(), attrNameString); + if (loc != null) { + type[0] = CgGL.cgGetParameterType(loc); + if (type[0] == CgGL.CG_ARRAY) { + isArray[0] = true; + size[0] = CgGL.cgGetArraySize(loc, 0); + CGparameter firstElem = CgGL.cgGetArrayParameter(loc, 0); + type[0] = CgGL.cgGetParameterType(firstElem); + } else { + isArray[0] = false; + size[0] = 1; + } + } + return loc; + } + + + + // --------------------------------------------------------------------- + + // + // GLSLShaderProgramRetained methods + // + + // ShaderAttributeValue methods + + ShaderError setGLSLUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform1i()"); + + context(ctx).getGL().glUniform1iARB(unbox(uniformLocation), value); + return null; + } + + ShaderError setGLSLUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform1f()"); + + context(ctx).getGL().glUniform1fARB(unbox(uniformLocation), value); + return null; + } + + ShaderError setGLSLUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform2i()"); + + context(ctx).getGL().glUniform2iARB(unbox(uniformLocation), value[0], value[1]); + return null; + } + + ShaderError setGLSLUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform2f()"); + + context(ctx).getGL().glUniform2fARB(unbox(uniformLocation), value[0], value[1]); + return null; + } + + ShaderError setGLSLUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform3i()"); + + context(ctx).getGL().glUniform3iARB(unbox(uniformLocation), value[0], value[1], value[2]); + return null; + } + + ShaderError setGLSLUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform3f()"); + + context(ctx).getGL().glUniform3fARB(unbox(uniformLocation), value[0], value[1], value[2]); + return null; + } + + ShaderError setGLSLUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform4i()"); + + context(ctx).getGL().glUniform4iARB(unbox(uniformLocation), value[0], value[1], value[2], value[3]); + return null; + } + + ShaderError setGLSLUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform4f()"); + + context(ctx).getGL().glUniform4fARB(unbox(uniformLocation), value[0], value[1], value[2], value[3]); + return null; + } + + ShaderError setGLSLUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniformMatrix3f()"); + + // Load attribute + // transpose is true : each matrix is supplied in row major order + context(ctx).getGL().glUniformMatrix3fvARB(unbox(uniformLocation), 1, true, value, 0); + return null; + } + + ShaderError setGLSLUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniformMatrix4f()"); + + // Load attribute + // transpose is true : each matrix is supplied in row major order + context(ctx).getGL().glUniformMatrix4fvARB(unbox(uniformLocation), 1, true, value, 0); + return null; + } + + // ShaderAttributeArray methods + + ShaderError setGLSLUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform1iArray()"); + + context(ctx).getGL().glUniform1ivARB(unbox(uniformLocation), numElements, value, 0); + return null; + } + + ShaderError setGLSLUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform1fArray()"); + + context(ctx).getGL().glUniform1fvARB(unbox(uniformLocation), numElements, value, 0); + return null; + } + + ShaderError setGLSLUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform2iArray()"); + + context(ctx).getGL().glUniform2ivARB(unbox(uniformLocation), numElements, value, 0); + return null; + } + + ShaderError setGLSLUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform2fArray()"); + + context(ctx).getGL().glUniform2fvARB(unbox(uniformLocation), numElements, value, 0); + return null; + } + + ShaderError setGLSLUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform3iArray()"); + + context(ctx).getGL().glUniform3ivARB(unbox(uniformLocation), numElements, value, 0); + return null; + } + + ShaderError setGLSLUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform3fArray()"); + + context(ctx).getGL().glUniform3fvARB(unbox(uniformLocation), numElements, value, 0); + return null; + } + + ShaderError setGLSLUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform4iArray()"); + + context(ctx).getGL().glUniform4ivARB(unbox(uniformLocation), numElements, value, 0); + return null; + } + + ShaderError setGLSLUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniform4fArray()"); + + context(ctx).getGL().glUniform4fvARB(unbox(uniformLocation), numElements, value, 0); + return null; + } + + ShaderError setGLSLUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniformMatrix3fArray()"); + + // Load attribute + // transpose is true : each matrix is supplied in row major order + context(ctx).getGL().glUniformMatrix3fvARB(unbox(uniformLocation), numElements, true, value, 0); + return null; + } + + ShaderError setGLSLUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + if (VERBOSE) System.err.println("JoglPipeline.setGLSLUniformMatrix4fArray()"); + + // Load attribute + // transpose is true : each matrix is supplied in row major order + context(ctx).getGL().glUniformMatrix4fvARB(unbox(uniformLocation), numElements, true, value, 0); + return null; + } + + // interfaces for shader compilation, etc. + ShaderError createGLSLShader(Context ctx, int shaderType, ShaderId[] shaderId) { + if (VERBOSE) System.err.println("JoglPipeline.createGLSLShader()"); + + GL gl = context(ctx).getGL(); + + int shaderHandle = 0; + if (shaderType == Shader.SHADER_TYPE_VERTEX) { + shaderHandle = gl.glCreateShaderObjectARB(GL.GL_VERTEX_SHADER_ARB); + } else if (shaderType == Shader.SHADER_TYPE_FRAGMENT) { + shaderHandle = gl.glCreateShaderObjectARB(GL.GL_FRAGMENT_SHADER_ARB); + } + + if (shaderHandle == 0) { + return new ShaderError(ShaderError.COMPILE_ERROR, + "Unable to create native shader object"); + } + + shaderId[0] = new JoglShaderObject(shaderHandle); + return null; + } + ShaderError destroyGLSLShader(Context ctx, ShaderId shaderId) { + if (VERBOSE) System.err.println("JoglPipeline.destroyGLSLShader()"); + + GL gl = context(ctx).getGL(); + gl.glDeleteObjectARB(unbox(shaderId)); + return null; + } + ShaderError compileGLSLShader(Context ctx, ShaderId shaderId, String program) { + if (VERBOSE) System.err.println("JoglPipeline.compileGLSLShader()"); + + int id = unbox(shaderId); + if (id == 0) { + throw new AssertionError("shaderId == 0"); + } + + if (program == null) { + throw new AssertionError("shader program string is null"); + } + + GL gl = context(ctx).getGL(); + gl.glShaderSourceARB(id, 1, new String[] { program }, null, 0); + gl.glCompileShaderARB(id); + int[] status = new int[1]; + gl.glGetObjectParameterivARB(id, GL.GL_OBJECT_COMPILE_STATUS_ARB, status, 0); + if (status[0] == 0) { + String detailMsg = getInfoLog(gl, id); + ShaderError res = new ShaderError(ShaderError.COMPILE_ERROR, + "GLSL shader compile error"); + res.setDetailMessage(detailMsg); + return res; + } + return null; + } + + ShaderError createGLSLShaderProgram(Context ctx, ShaderProgramId[] shaderProgramId) { + if (VERBOSE) System.err.println("JoglPipeline.createGLSLShaderProgram()"); + + GL gl = context(ctx).getGL(); + + int shaderProgramHandle = gl.glCreateProgramObjectARB(); + if (shaderProgramHandle == 0) { + return new ShaderError(ShaderError.LINK_ERROR, + "Unable to create native shader program object"); + } + shaderProgramId[0] = new JoglShaderObject(shaderProgramHandle); + return null; + } + ShaderError destroyGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + if (VERBOSE) System.err.println("JoglPipeline.destroyGLSLShaderProgram()"); + context(ctx).getGL().glDeleteObjectARB(unbox(shaderProgramId)); + return null; + } + ShaderError linkGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId, + ShaderId[] shaderIds) { + if (VERBOSE) System.err.println("JoglPipeline.linkGLSLShaderProgram()"); + + GL gl = context(ctx).getGL(); + int id = unbox(shaderProgramId); + for (int i = 0; i < shaderIds.length; i++) { + gl.glAttachObjectARB(id, unbox(shaderIds[i])); + } + gl.glLinkProgramARB(id); + int[] status = new int[1]; + gl.glGetObjectParameterivARB(id, GL.GL_OBJECT_LINK_STATUS_ARB, status, 0); + if (status[0] == 0) { + String detailMsg = getInfoLog(gl, id); + ShaderError res = new ShaderError(ShaderError.LINK_ERROR, + "GLSL shader program link error"); + res.setDetailMessage(detailMsg); + return res; + } + return null; + } + ShaderError bindGLSLVertexAttrName(Context ctx, ShaderProgramId shaderProgramId, + String attrName, int attrIndex) { + if (VERBOSE) System.err.println("JoglPipeline.bindGLSLVertexAttrName()"); + + JoglContext jctx = (JoglContext) ctx; + context(ctx).getGL().glBindAttribLocationARB(unbox(shaderProgramId), + attrIndex + VirtualUniverse.mc.glslVertexAttrOffset, + attrName); + return null; + } + void lookupGLSLShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, ShaderAttrLoc[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr) { + if (VERBOSE) System.err.println("JoglPipeline.lookupGLSLShaderAttrNames()"); + + // set the loc, type, and size arrays to out-of-bound values + for (int i = 0; i < attrNames.length; i++) { + locArr[i] = null; + typeArr[i] = -1; + sizeArr[i] = -1; + } + + // Loop through the list of active uniform variables, one at a + // time, searching for a match in the attrNames array. + // + // NOTE: Since attrNames isn't sorted, and we don't have a + // hashtable of names to index locations, we will do a + // brute-force, linear search of the array. This leads to an + // O(n^2) algorithm (actually O(n*m) where n is attrNames.length + // and m is the number of uniform variables), but since we expect + // N to be small, we will not optimize this at this time. + int id = unbox(shaderProgramId); + int[] tmp = new int[1]; + int[] tmp2 = new int[1]; + int[] tmp3 = new int[1]; + GL gl = context(ctx).getGL(); + gl.glGetObjectParameterivARB(id, + GL.GL_OBJECT_ACTIVE_UNIFORMS_ARB, + tmp, 0); + int numActiveUniforms = tmp[0]; + gl.glGetObjectParameterivARB(id, + GL.GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, + tmp, 0); + int maxStrLen = tmp[0]; + byte[] nameBuf = new byte[maxStrLen]; + + for (int i = 0; i < numActiveUniforms; i++) { + gl.glGetActiveUniformARB(id, i, maxStrLen, tmp3, 0, + tmp, 0, + tmp2, 0, + nameBuf, 0); + int size = tmp[0]; + int type = tmp2[0]; + String name = null; + try { + // TODO KCR : Shouldn't this use the default locale? + name = new String(nameBuf, 0, tmp3[0], "US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + // Issue 247 - we need to workaround an ATI bug where they erroneously + // report individual elements of arrays rather than the array itself + if (name.length() >= 3 && name.endsWith("]")) { + if (name.endsWith("[0]")) { + name = name.substring(0, name.length() - 3); + } else { + // Ignore this name + continue; + } + } + + // Now try to find the name + for (int j = 0; j < numAttrNames; j++) { + if (name.equals(attrNames[j])) { + sizeArr[j] = size; + isArrayArr[j] = (size > 1); + typeArr[j] = glslToJ3dType(type); + break; + } + } + } + + // Now lookup the location of each name in the attrNames array + for (int i = 0; i < numAttrNames; i++) { + // Get uniform attribute location + int loc = gl.glGetUniformLocationARB(id, attrNames[i]); + locArr[i] = new JoglShaderObject(loc); + } + } + + ShaderError useGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + if (VERBOSE) System.err.println("JoglPipeline.useGLSLShaderProgram()"); + + context(ctx).getGL().glUseProgramObjectARB(unbox(shaderProgramId)); + ((JoglContext) ctx).setShaderProgram((JoglShaderObject) shaderProgramId); + return null; + } + + //---------------------------------------------------------------------- + // Helper methods for above shader routines + // + private int unbox(ShaderAttrLoc loc) { + if (loc == null) + return 0; + return ((JoglShaderObject) loc).getValue(); + } + + private int unbox(ShaderProgramId id) { + if (id == null) + return 0; + return ((JoglShaderObject) id).getValue(); + } + + private int unbox(ShaderId id) { + if (id == null) + return 0; + return ((JoglShaderObject) id).getValue(); + } + + private String getInfoLog(GL gl, int id) { + int[] infoLogLength = new int[1]; + gl.glGetObjectParameterivARB(id, GL.GL_OBJECT_INFO_LOG_LENGTH_ARB, infoLogLength, 0); + if (infoLogLength[0] > 0) { + byte[] storage = new byte[infoLogLength[0]]; + int[] len = new int[1]; + gl.glGetInfoLogARB(id, infoLogLength[0], len, 0, storage, 0); + try { + // TODO KCR : Shouldn't this use the default locale? + return new String(storage, 0, len[0], "US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + return null; + } + + private int glslToJ3dType(int type) { + switch (type) { + case GL.GL_BOOL_ARB: + case GL.GL_INT: + case GL.GL_SAMPLER_2D_ARB: + case GL.GL_SAMPLER_3D_ARB: + case GL.GL_SAMPLER_CUBE_ARB: + return ShaderAttributeObjectRetained.TYPE_INTEGER; + + case GL.GL_FLOAT: + return ShaderAttributeObjectRetained.TYPE_FLOAT; + + case GL.GL_INT_VEC2_ARB: + case GL.GL_BOOL_VEC2_ARB: + return ShaderAttributeObjectRetained.TYPE_TUPLE2I; + + case GL.GL_FLOAT_VEC2_ARB: + return ShaderAttributeObjectRetained.TYPE_TUPLE2F; + + case GL.GL_INT_VEC3_ARB: + case GL.GL_BOOL_VEC3_ARB: + return ShaderAttributeObjectRetained.TYPE_TUPLE3I; + + case GL.GL_FLOAT_VEC3_ARB: + return ShaderAttributeObjectRetained.TYPE_TUPLE3F; + + case GL.GL_INT_VEC4_ARB: + case GL.GL_BOOL_VEC4_ARB: + return ShaderAttributeObjectRetained.TYPE_TUPLE4I; + + case GL.GL_FLOAT_VEC4_ARB: + return ShaderAttributeObjectRetained.TYPE_TUPLE4F; + + // case GL.GL_FLOAT_MAT2_ARB: + + case GL.GL_FLOAT_MAT3_ARB: + return ShaderAttributeObjectRetained.TYPE_MATRIX3F; + + case GL.GL_FLOAT_MAT4_ARB: + return ShaderAttributeObjectRetained.TYPE_MATRIX4F; + + // Java 3D does not support the following sampler types: + // + // case GL.GL_SAMPLER_1D_ARB: + // case GL.GL_SAMPLER_1D_SHADOW_ARB: + // case GL.GL_SAMPLER_2D_SHADOW_ARB: + // case GL.GL_SAMPLER_2D_RECT_ARB: + // case GL.GL_SAMPLER_2D_RECT_SHADOW_ARB: + } + + return -1; + } + + // --------------------------------------------------------------------- + + // + // ImageComponent2DRetained methods + // + + // free d3d surface referred to by id + void freeD3DSurface(ImageComponent2DRetained image, int hashId) { + // Nothing to do + } + + // --------------------------------------------------------------------- + + // + // Renderer methods + // + + void cleanupRenderer() { + // Nothing to do + } + + + // --------------------------------------------------------------------- + + // + // ColoringAttributesRetained methods + // + + void updateColoringAttributes(Context ctx, + float dRed, float dGreen, float dBlue, + float red, float green, float blue, + float alpha, + boolean lightEnable, + int shadeModel) { + if (VERBOSE) System.err.println("JoglPipeline.updateColoringAttributes()"); + + GL gl = context(ctx).getGL(); + + float cr, cg, cb; + + if (lightEnable) { + cr = dRed; cg = dGreen; cb = dBlue; + } else { + cr = red; cg = green; cb = blue; + } + gl.glColor4f(cr, cg, cb, alpha); + if (shadeModel == ColoringAttributes.SHADE_FLAT) { + gl.glShadeModel(GL.GL_FLAT); + } else { + gl.glShadeModel(GL.GL_SMOOTH); + } + } + + + // --------------------------------------------------------------------- + + // + // DirectionalLightRetained methods + // + + private static final float[] black = new float[4]; + void updateDirectionalLight(Context ctx, + int lightSlot, float red, float green, + float blue, float dirx, float diry, float dirz) { + if (VERBOSE) System.err.println("JoglPipeline.updateDirectionalLight()"); + + GL gl = context(ctx).getGL(); + + int lightNum = GL.GL_LIGHT0 + lightSlot; + float[] values = new float[4]; + + values[0] = red; + values[1] = green; + values[2] = blue; + values[3] = 1.0f; + gl.glLightfv(lightNum, GL.GL_DIFFUSE, values, 0); + gl.glLightfv(lightNum, GL.GL_SPECULAR, values, 0); + values[0] = -dirx; + values[1] = -diry; + values[2] = -dirz; + values[3] = 0.0f; + gl.glLightfv(lightNum, GL.GL_POSITION, values, 0); + gl.glLightfv(lightNum, GL.GL_AMBIENT, black, 0); + gl.glLightf(lightNum, GL.GL_CONSTANT_ATTENUATION, 1.0f); + gl.glLightf(lightNum, GL.GL_LINEAR_ATTENUATION, 0.0f); + gl.glLightf(lightNum, GL.GL_QUADRATIC_ATTENUATION, 0.0f); + gl.glLightf(lightNum, GL.GL_SPOT_EXPONENT, 0.0f); + gl.glLightf(lightNum, GL.GL_SPOT_CUTOFF, 180.0f); + } + + + // --------------------------------------------------------------------- + + // + // PointLightRetained methods + // + + void updatePointLight(Context ctx, + int lightSlot, float red, float green, + float blue, float attenx, float atteny, float attenz, + float posx, float posy, float posz) { + if (VERBOSE) System.err.println("JoglPipeline.updatePointLight()"); + + GL gl = context(ctx).getGL(); + + int lightNum = GL.GL_LIGHT0 + lightSlot; + float[] values = new float[4]; + + values[0] = red; + values[1] = green; + values[2] = blue; + values[3] = 1.0f; + gl.glLightfv(lightNum, GL.GL_DIFFUSE, values, 0); + gl.glLightfv(lightNum, GL.GL_SPECULAR, values, 0); + gl.glLightfv(lightNum, GL.GL_AMBIENT, black, 0); + values[0] = posx; + values[1] = posy; + values[2] = posz; + gl.glLightfv(lightNum, GL.GL_POSITION, values, 0); + gl.glLightf(lightNum, GL.GL_CONSTANT_ATTENUATION, attenx); + gl.glLightf(lightNum, GL.GL_LINEAR_ATTENUATION, atteny); + gl.glLightf(lightNum, GL.GL_QUADRATIC_ATTENUATION, attenz); + gl.glLightf(lightNum, GL.GL_SPOT_EXPONENT, 0.0f); + gl.glLightf(lightNum, GL.GL_SPOT_CUTOFF, 180.0f); + } + + + // --------------------------------------------------------------------- + + // + // SpotLightRetained methods + // + + void updateSpotLight(Context ctx, + int lightSlot, float red, float green, + float blue, float attenx, float atteny, float attenz, + float posx, float posy, float posz, float spreadAngle, + float concentration, float dirx, float diry, + float dirz) { + if (VERBOSE) System.err.println("JoglPipeline.updateSpotLight()"); + + GL gl = context(ctx).getGL(); + + int lightNum = GL.GL_LIGHT0 + lightSlot; + float[] values = new float[4]; + + values[0] = red; + values[1] = green; + values[2] = blue; + values[3] = 1.0f; + gl.glLightfv(lightNum, GL.GL_DIFFUSE, values, 0); + gl.glLightfv(lightNum, GL.GL_SPECULAR, values, 0); + gl.glLightfv(lightNum, GL.GL_AMBIENT, black, 0); + values[0] = posx; + values[1] = posy; + values[2] = posz; + gl.glLightfv(lightNum, GL.GL_POSITION, values, 0); + gl.glLightf(lightNum, GL.GL_CONSTANT_ATTENUATION, attenx); + gl.glLightf(lightNum, GL.GL_LINEAR_ATTENUATION, atteny); + gl.glLightf(lightNum, GL.GL_QUADRATIC_ATTENUATION, attenz); + values[0] = dirx; + values[1] = diry; + values[2] = dirz; + gl.glLightfv(lightNum, GL.GL_SPOT_DIRECTION, values, 0); + gl.glLightf(lightNum, GL.GL_SPOT_EXPONENT, concentration); + gl.glLightf(lightNum, GL.GL_SPOT_CUTOFF, (float) (spreadAngle * 180.0f / Math.PI)); + } + + + // --------------------------------------------------------------------- + + // + // ExponentialFogRetained methods + // + + void updateExponentialFog(Context ctx, + float red, float green, float blue, + float density) { + if (VERBOSE) System.err.println("JoglPipeline.updateExponentialFog()"); + + GL gl = context(ctx).getGL(); + + float[] color = new float[3]; + color[0] = red; + color[1] = green; + color[2] = blue; + gl.glFogi(GL.GL_FOG_MODE, GL.GL_EXP); + gl.glFogfv(GL.GL_FOG_COLOR, color, 0); + gl.glFogf(GL.GL_FOG_DENSITY, density); + gl.glEnable(GL.GL_FOG); + } + + + // --------------------------------------------------------------------- + + // + // LinearFogRetained methods + // + + void updateLinearFog(Context ctx, + float red, float green, float blue, + double fdist, double bdist) { + if (VERBOSE) System.err.println("JoglPipeline.updateLinearFog()"); + + GL gl = context(ctx).getGL(); + + float[] color = new float[3]; + color[0] = red; + color[1] = green; + color[2] = blue; + gl.glFogi(GL.GL_FOG_MODE, GL.GL_LINEAR); + gl.glFogfv(GL.GL_FOG_COLOR, color, 0); + gl.glFogf(GL.GL_FOG_START, (float) fdist); + gl.glFogf(GL.GL_FOG_END, (float) bdist); + gl.glEnable(GL.GL_FOG); + } + + + // --------------------------------------------------------------------- + + // + // LineAttributesRetained methods + // + + void updateLineAttributes(Context ctx, + float lineWidth, int linePattern, + int linePatternMask, + int linePatternScaleFactor, + boolean lineAntialiasing) { + if (VERBOSE) System.err.println("JoglPipeline.updateLineAttributes()"); + + GL gl = context(ctx).getGL(); + gl.glLineWidth(lineWidth); + + if (linePattern == LineAttributes.PATTERN_SOLID) { + gl.glDisable(GL.GL_LINE_STIPPLE); + } else { + if (linePattern == LineAttributes.PATTERN_DASH) { // dashed lines + gl.glLineStipple(1, (short) 0x00ff); + } else if (linePattern == LineAttributes.PATTERN_DOT) { // dotted lines + gl.glLineStipple(1, (short) 0x0101); + } else if (linePattern == LineAttributes.PATTERN_DASH_DOT) { // dash-dotted lines + gl.glLineStipple(1, (short) 0x087f); + } else if (linePattern == LineAttributes.PATTERN_USER_DEFINED) { // user-defined mask + gl.glLineStipple(linePatternScaleFactor, (short) linePatternMask); + } + gl.glEnable(GL.GL_LINE_STIPPLE); + } + + /* XXXX: Polygon Mode check, blend enable */ + if (lineAntialiasing) { + gl.glEnable(GL.GL_LINE_SMOOTH); + } else { + gl.glDisable(GL.GL_LINE_SMOOTH); + } + } + + + // --------------------------------------------------------------------- + + // + // MaterialRetained methods + // + + void updateMaterial(Context ctx, + float red, float green, float blue, float alpha, + float aRed, float aGreen, float aBlue, + float eRed, float eGreen, float eBlue, + float dRed, float dGreen, float dBlue, + float sRed, float sGreen, float sBlue, + float shininess, int colorTarget, boolean lightEnable) { + if (VERBOSE) System.err.println("JoglPipeline.updateMaterial()"); + + float[] color = new float[4]; + + GL gl = context(ctx).getGL(); + + gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, shininess); + switch (colorTarget) { + case Material.DIFFUSE: + gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE); + break; + case Material.AMBIENT: + gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT); + break; + case Material.EMISSIVE: + gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_EMISSION); + break; + case Material.SPECULAR: + gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR); + break; + case Material.AMBIENT_AND_DIFFUSE: + gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE); + break; + } + + color[0] = eRed; color[1] = eGreen; color[2] = eBlue; + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_EMISSION, color, 0); + + color[0] = aRed; color[1] = aGreen; color[2] = aBlue; + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, color, 0); + + color[0] = sRed; color[1] = sGreen; color[2] = sBlue; + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, color, 0); + + float cr, cg, cb; + + if (lightEnable) { + color[0] = dRed; color[1] = dGreen; color[2] = dBlue; + } else { + color[0] = red; color[1] = green; color[2] = blue; + } + color[3] = alpha; + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, color, 0); + gl.glColor4f(color[0], color[1], color[2], color[3]); + + if (lightEnable) { + gl.glEnable(GL.GL_LIGHTING); + } else { + gl.glDisable(GL.GL_LIGHTING); + } + } + + + // --------------------------------------------------------------------- + + // + // ModelClipRetained methods + // + + void updateModelClip(Context ctx, int planeNum, boolean enableFlag, + double A, double B, double C, double D) { + if (VERBOSE) System.err.println("JoglPipeline.updateModelClip()"); + + GL gl = context(ctx).getGL(); + + double[] equation = new double[4]; + int pl = GL.GL_CLIP_PLANE0 + planeNum; + + // OpenGL clip planes are opposite to J3d clip planes + if (enableFlag) { + equation[0] = -A; + equation[1] = -B; + equation[2] = -C; + equation[3] = -D; + gl.glClipPlane(pl, DoubleBuffer.wrap(equation)); + gl.glEnable(pl); + } else { + gl.glDisable(pl); + } + } + + + // --------------------------------------------------------------------- + + // + // PointAttributesRetained methods + // + + void updatePointAttributes(Context ctx, float pointSize, boolean pointAntialiasing) { + if (VERBOSE) System.err.println("JoglPipeline.updatePointAttributes()"); + + GL gl = context(ctx).getGL(); + gl.glPointSize(pointSize); + + // XXXX: Polygon Mode check, blend enable + if (pointAntialiasing) { + gl.glEnable(GL.GL_POINT_SMOOTH); + } else { + gl.glDisable(GL.GL_POINT_SMOOTH); + } + } + + + // --------------------------------------------------------------------- + + // + // PolygonAttributesRetained methods + // + + void updatePolygonAttributes(Context ctx, + int polygonMode, int cullFace, + boolean backFaceNormalFlip, + float polygonOffset, + float polygonOffsetFactor) { + if (VERBOSE) System.err.println("JoglPipeline.updatePolygonAttributes()"); + + GL gl = context(ctx).getGL(); + + if (cullFace == PolygonAttributes.CULL_NONE) { + gl.glDisable(GL.GL_CULL_FACE); + } else { + if (cullFace == PolygonAttributes.CULL_BACK) { + gl.glCullFace(GL.GL_BACK); + } else { + gl.glCullFace(GL.GL_FRONT); + } + gl.glEnable(GL.GL_CULL_FACE); + } + + if (backFaceNormalFlip && (cullFace != PolygonAttributes.CULL_BACK)) { + gl.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE); + } else { + gl.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_FALSE); + } + + if (polygonMode == PolygonAttributes.POLYGON_POINT) { + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_POINT); + } else if (polygonMode == PolygonAttributes.POLYGON_LINE) { + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); + } else { + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); + } + + gl.glPolygonOffset(polygonOffsetFactor, polygonOffset); + + if ((polygonOffsetFactor != 0.0) || (polygonOffset != 0.0)) { + switch (polygonMode) { + case PolygonAttributes.POLYGON_POINT: + gl.glEnable(GL.GL_POLYGON_OFFSET_POINT); + gl.glDisable(GL.GL_POLYGON_OFFSET_LINE); + gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); + break; + case PolygonAttributes.POLYGON_LINE: + gl.glEnable(GL.GL_POLYGON_OFFSET_LINE); + gl.glDisable(GL.GL_POLYGON_OFFSET_POINT); + gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); + break; + case PolygonAttributes.POLYGON_FILL: + gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); + gl.glDisable(GL.GL_POLYGON_OFFSET_POINT); + gl.glDisable(GL.GL_POLYGON_OFFSET_LINE); + break; + } + } else { + gl.glDisable(GL.GL_POLYGON_OFFSET_POINT); + gl.glDisable(GL.GL_POLYGON_OFFSET_LINE); + gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); + } + } + + + // --------------------------------------------------------------------- + + // + // RenderingAttributesRetained methods + // + + void updateRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride, + boolean depthBufferEnable, + boolean depthBufferWriteEnable, + int depthTestFunction, + float alphaTestValue, int alphaTestFunction, + boolean ignoreVertexColors, + boolean rasterOpEnable, int rasterOp, + boolean userStencilAvailable, boolean stencilEnable, + int stencilFailOp, int stencilZFailOp, int stencilZPassOp, + int stencilFunction, int stencilReferenceValue, + int stencilCompareMask, int stencilWriteMask ) { + if (VERBOSE) System.err.println("JoglPipeline.updateRenderingAttributes()"); + + GL gl = context(ctx).getGL(); + + if (!depthBufferEnableOverride) { + if (depthBufferEnable) { + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glDepthFunc(getFunctionValue(depthTestFunction)); + } else { + gl.glDisable(GL.GL_DEPTH_TEST); + } + } + + if (!depthBufferWriteEnableOverride) { + if (depthBufferWriteEnable) { + gl.glDepthMask(true); + } else { + gl.glDepthMask(false); + } + } + + if (alphaTestFunction == RenderingAttributes.ALWAYS) { + gl.glDisable(GL.GL_ALPHA_TEST); + } else { + gl.glEnable(GL.GL_ALPHA_TEST); + gl.glAlphaFunc(getFunctionValue(alphaTestFunction), alphaTestValue); + } + + if (ignoreVertexColors) { + gl.glDisable(GL.GL_COLOR_MATERIAL); + } else { + gl.glEnable(GL.GL_COLOR_MATERIAL); + } + + if (rasterOpEnable) { + gl.glEnable(GL.GL_COLOR_LOGIC_OP); + switch (rasterOp) { + case RenderingAttributes.ROP_CLEAR: + gl.glLogicOp(GL.GL_CLEAR); + break; + case RenderingAttributes.ROP_AND: + gl.glLogicOp(GL.GL_AND); + break; + case RenderingAttributes.ROP_AND_REVERSE: + gl.glLogicOp(GL.GL_AND_REVERSE); + break; + case RenderingAttributes.ROP_COPY: + gl.glLogicOp(GL.GL_COPY); + break; + case RenderingAttributes.ROP_AND_INVERTED: + gl.glLogicOp(GL.GL_AND_INVERTED); + break; + case RenderingAttributes.ROP_NOOP: + gl.glLogicOp(GL.GL_NOOP); + break; + case RenderingAttributes.ROP_XOR: + gl.glLogicOp(GL.GL_XOR); + break; + case RenderingAttributes.ROP_OR: + gl.glLogicOp(GL.GL_OR); + break; + case RenderingAttributes.ROP_NOR: + gl.glLogicOp(GL.GL_NOR); + break; + case RenderingAttributes.ROP_EQUIV: + gl.glLogicOp(GL.GL_EQUIV); + break; + case RenderingAttributes.ROP_INVERT: + gl.glLogicOp(GL.GL_INVERT); + break; + case RenderingAttributes.ROP_OR_REVERSE: + gl.glLogicOp(GL.GL_OR_REVERSE); + break; + case RenderingAttributes.ROP_COPY_INVERTED: + gl.glLogicOp(GL.GL_COPY_INVERTED); + break; + case RenderingAttributes.ROP_OR_INVERTED: + gl.glLogicOp(GL.GL_OR_INVERTED); + break; + case RenderingAttributes.ROP_NAND: + gl.glLogicOp(GL.GL_NAND); + break; + case RenderingAttributes.ROP_SET: + gl.glLogicOp(GL.GL_SET); + break; + } + } else { + gl.glDisable(GL.GL_COLOR_LOGIC_OP); + } + + if (userStencilAvailable) { + if (stencilEnable) { + gl.glEnable(GL.GL_STENCIL_TEST); + + gl.glStencilOp(getStencilOpValue(stencilFailOp), + getStencilOpValue(stencilZFailOp), + getStencilOpValue(stencilZPassOp)); + + gl.glStencilFunc(getFunctionValue(stencilFunction), + stencilReferenceValue, stencilCompareMask); + + gl.glStencilMask(stencilWriteMask); + + } else { + gl.glDisable(GL.GL_STENCIL_TEST); + } + } + } + + private int getFunctionValue(int func) { + switch (func) { + case RenderingAttributes.ALWAYS: + func = GL.GL_ALWAYS; + break; + case RenderingAttributes.NEVER: + func = GL.GL_NEVER; + break; + case RenderingAttributes.EQUAL: + func = GL.GL_EQUAL; + break; + case RenderingAttributes.NOT_EQUAL: + func = GL.GL_NOTEQUAL; + break; + case RenderingAttributes.LESS: + func = GL.GL_LESS; + break; + case RenderingAttributes.LESS_OR_EQUAL: + func = GL.GL_LEQUAL; + break; + case RenderingAttributes.GREATER: + func = GL.GL_GREATER; + break; + case RenderingAttributes.GREATER_OR_EQUAL: + func = GL.GL_GEQUAL; + break; + } + + return func; + } + + private int getStencilOpValue(int op) { + switch (op) { + case RenderingAttributes.STENCIL_KEEP: + op = GL.GL_KEEP; + break; + case RenderingAttributes.STENCIL_ZERO: + op = GL.GL_ZERO; + break; + case RenderingAttributes.STENCIL_REPLACE: + op = GL.GL_REPLACE; + break; + case RenderingAttributes.STENCIL_INCR: + op = GL.GL_INCR; + break; + case RenderingAttributes.STENCIL_DECR: + op = GL.GL_DECR; + break; + case RenderingAttributes.STENCIL_INVERT: + op = GL.GL_INVERT; + break; + } + + return op; + } + + + // --------------------------------------------------------------------- + + // + // TexCoordGenerationRetained methods + // + + /** + * This method updates the native context: + * trans contains eyeTovworld transform in d3d + * trans contains vworldToEye transform in ogl + */ + void updateTexCoordGeneration(Context ctx, + boolean enable, int genMode, int format, + float planeSx, float planeSy, float planeSz, float planeSw, + float planeTx, float planeTy, float planeTz, float planeTw, + float planeRx, float planeRy, float planeRz, float planeRw, + float planeQx, float planeQy, float planeQz, float planeQw, + double[] vworldToEc) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexCoordGeneration()"); + + GL gl = context(ctx).getGL(); + + float[] planeS = new float[4]; + float[] planeT = new float[4]; + float[] planeR = new float[4]; + float[] planeQ = new float[4]; + + if (enable) { + gl.glEnable(GL.GL_TEXTURE_GEN_S); + gl.glEnable(GL.GL_TEXTURE_GEN_T); + if (format == TexCoordGeneration.TEXTURE_COORDINATE_3) { + gl.glEnable(GL.GL_TEXTURE_GEN_R); + gl.glDisable(GL.GL_TEXTURE_GEN_Q); + } else if (format == TexCoordGeneration.TEXTURE_COORDINATE_4) { + gl.glEnable(GL.GL_TEXTURE_GEN_R); + gl.glEnable(GL.GL_TEXTURE_GEN_Q); + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_R); + gl.glDisable(GL.GL_TEXTURE_GEN_Q); + } + + if (genMode != TexCoordGeneration.SPHERE_MAP) { + planeS[0] = planeSx; planeS[1] = planeSy; + planeS[2] = planeSz; planeS[3] = planeSw; + planeT[0] = planeTx; planeT[1] = planeTy; + planeT[2] = planeTz; planeT[3] = planeTw; + if (format == TexCoordGeneration.TEXTURE_COORDINATE_3) { + planeR[0] = planeRx; planeR[1] = planeRy; + planeR[2] = planeRz; planeR[3] = planeRw; + } else if (format == TexCoordGeneration.TEXTURE_COORDINATE_4) { + planeR[0] = planeRx; planeR[1] = planeRy; + planeR[2] = planeRz; planeR[3] = planeRw; + planeQ[0] = planeQx; planeQ[1] = planeQy; + planeQ[2] = planeQz; planeQ[3] = planeQw; + } + } + + switch (genMode) { + case TexCoordGeneration.OBJECT_LINEAR: + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + gl.glTexGenfv(GL.GL_S, GL.GL_OBJECT_PLANE, planeS, 0); + gl.glTexGenfv(GL.GL_T, GL.GL_OBJECT_PLANE, planeT, 0); + + if (format == TexCoordGeneration.TEXTURE_COORDINATE_3) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + gl.glTexGenfv(GL.GL_R, GL.GL_OBJECT_PLANE, planeR, 0); + } else if (format == TexCoordGeneration.TEXTURE_COORDINATE_4) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + gl.glTexGenfv(GL.GL_R, GL.GL_OBJECT_PLANE, planeR, 0); + gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); + gl.glTexGenfv(GL.GL_Q, GL.GL_OBJECT_PLANE, planeQ, 0); + } + break; + case TexCoordGeneration.EYE_LINEAR: + + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glPushMatrix(); + + if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + gl.glLoadTransposeMatrixd(vworldToEc, 0); + } else { + double[] v = new double[16]; + copyTranspose(vworldToEc, v); + gl.glLoadMatrixd(v, 0); + } + + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + gl.glTexGenfv(GL.GL_S, GL.GL_EYE_PLANE, planeS, 0); + gl.glTexGenfv(GL.GL_T, GL.GL_EYE_PLANE, planeT, 0); + + if (format == TexCoordGeneration.TEXTURE_COORDINATE_3) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + gl.glTexGenfv(GL.GL_R, GL.GL_EYE_PLANE, planeR, 0); + } else if (format == TexCoordGeneration.TEXTURE_COORDINATE_4) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + gl.glTexGenfv(GL.GL_R, GL.GL_EYE_PLANE, planeR, 0); + gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR); + gl.glTexGenfv(GL.GL_Q, GL.GL_EYE_PLANE, planeQ, 0); + } + gl.glPopMatrix(); + break; + case TexCoordGeneration.SPHERE_MAP: + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); + if (format == TexCoordGeneration.TEXTURE_COORDINATE_3) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); + } else if (format == TexCoordGeneration.TEXTURE_COORDINATE_4) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); + gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); + } + + break; + case TexCoordGeneration.NORMAL_MAP: + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + if (format == TexCoordGeneration.TEXTURE_COORDINATE_3) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + } else if (format == TexCoordGeneration.TEXTURE_COORDINATE_4) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + } + break; + case TexCoordGeneration.REFLECTION_MAP: + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP); + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP); + if (format == TexCoordGeneration.TEXTURE_COORDINATE_3) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP); + } else if (format == TexCoordGeneration.TEXTURE_COORDINATE_4) { + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP); + gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_REFLECTION_MAP); + } + break; + } + } else { + gl.glDisable(GL.GL_TEXTURE_GEN_S); + gl.glDisable(GL.GL_TEXTURE_GEN_T); + gl.glDisable(GL.GL_TEXTURE_GEN_R); + gl.glDisable(GL.GL_TEXTURE_GEN_Q); + } + } + + + // --------------------------------------------------------------------- + + // + // TransparencyAttributesRetained methods + // + + private static final int screen_door[][] = { + /* 0 / 16 */ + { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + /* 1 / 16 */ + { + 0x00000000, 0x22222222, 0x00000000, 0x00000000, + 0x00000000, 0x22222222, 0x00000000, 0x00000000, + 0x00000000, 0x22222222, 0x00000000, 0x00000000, + 0x00000000, 0x22222222, 0x00000000, 0x00000000, + 0x00000000, 0x22222222, 0x00000000, 0x00000000, + 0x00000000, 0x22222222, 0x00000000, 0x00000000, + 0x00000000, 0x22222222, 0x00000000, 0x00000000, + 0x00000000, 0x22222222, 0x00000000, 0x00000000, + }, + /* 2 / 16 */ + { + 0x00000000, 0x22222222, 0x00000000, 0x88888888, + 0x00000000, 0x22222222, 0x00000000, 0x88888888, + 0x00000000, 0x22222222, 0x00000000, 0x88888888, + 0x00000000, 0x22222222, 0x00000000, 0x88888888, + 0x00000000, 0x22222222, 0x00000000, 0x88888888, + 0x00000000, 0x22222222, 0x00000000, 0x88888888, + 0x00000000, 0x22222222, 0x00000000, 0x88888888, + 0x00000000, 0x22222222, 0x00000000, 0x88888888, + }, + /* 3 / 16 */ + { + 0x00000000, 0xaaaaaaaa, 0x00000000, 0x88888888, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0x88888888, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0x88888888, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0x88888888, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0x88888888, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0x88888888, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0x88888888, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0x88888888, + }, + /* 4 / 16 */ + { + 0x00000000, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x00000000, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + }, + /* 5 / 16 */ + { + 0x11111111, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x00000000, 0xaaaaaaaa, + }, + /* 6 / 16 */ + { + 0x11111111, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x11111111, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + }, + /* 7 / 16 */ + { + 0x55555555, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x44444444, 0xaaaaaaaa, + }, + /* 8 / 16 */ + { + 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + }, + /* 9 / 16 */ + { + 0x77777777, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, + }, + /* 10 / 16 */ + { + 0x77777777, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0x77777777, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + }, + /* 11 / 16 */ + { + 0xffffffff, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xdddddddd, 0xaaaaaaaa, + }, + /* 12 / 16 */ + { + 0xffffffff, 0xaaaaaaaa, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xaaaaaaaa, 0xffffffff, 0xaaaaaaaa, + }, + /* 13 / 16 */ + { + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xaaaaaaaa, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xaaaaaaaa, + }, + /* 14 / 16 */ + { + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xbbbbbbbb, 0xffffffff, 0xeeeeeeee, + }, + /* 15 / 16 */ + { + 0xffffffff, 0xffffffff, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xffffffff, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xffffffff, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xffffffff, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xffffffff, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xffffffff, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xffffffff, 0xffffffff, 0xeeeeeeee, + 0xffffffff, 0xffffffff, 0xffffffff, 0xeeeeeeee, + }, + /* 16 / 16 */ + { + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + }; + private static final ByteBuffer[] screen_door_table = new ByteBuffer[screen_door.length]; + static { + int eachLen = screen_door[0].length; + ByteBuffer buf = BufferUtil.newByteBuffer(screen_door.length * eachLen * BufferUtil.SIZEOF_INT); + IntBuffer intBuf = buf.asIntBuffer(); + for (int i = 0; i < screen_door.length; i++) { + intBuf.put(screen_door[i]); + } + buf.rewind(); + for (int i = 0; i < screen_door.length; i++) { + buf.position(i * eachLen); + buf.limit((i+1) * eachLen); + screen_door_table[i] = buf.slice(); + } + } + + private static final int[] blendFunctionTable = new int[TransparencyAttributes.MAX_BLEND_FUNC_TABLE_SIZE]; + static { + blendFunctionTable[TransparencyAttributes.BLEND_ZERO] = GL.GL_ZERO; + blendFunctionTable[TransparencyAttributes.BLEND_ONE] = GL.GL_ONE; + blendFunctionTable[TransparencyAttributes.BLEND_SRC_ALPHA] = GL.GL_SRC_ALPHA; + blendFunctionTable[TransparencyAttributes.BLEND_ONE_MINUS_SRC_ALPHA] = GL.GL_ONE_MINUS_SRC_ALPHA; + blendFunctionTable[TransparencyAttributes.BLEND_DST_COLOR] = GL.GL_DST_COLOR; + blendFunctionTable[TransparencyAttributes.BLEND_ONE_MINUS_DST_COLOR] = GL.GL_ONE_MINUS_DST_COLOR; + blendFunctionTable[TransparencyAttributes.BLEND_SRC_COLOR] = GL.GL_SRC_COLOR; + blendFunctionTable[TransparencyAttributes.BLEND_ONE_MINUS_SRC_COLOR] = GL.GL_ONE_MINUS_SRC_COLOR; + blendFunctionTable[TransparencyAttributes.BLEND_CONSTANT_COLOR] = GL.GL_CONSTANT_COLOR; + } + + void updateTransparencyAttributes(Context ctx, + float alpha, int geometryType, + int polygonMode, + boolean lineAA, boolean pointAA, + int transparencyMode, + int srcBlendFunction, + int dstBlendFunction) { + if (VERBOSE) System.err.println("JoglPipeline.updateTransparencyAttributes()"); + + GL gl = context(ctx).getGL(); + + if (transparencyMode != TransparencyAttributes.SCREEN_DOOR) { + gl.glDisable(GL.GL_POLYGON_STIPPLE); + } else { + gl.glEnable(GL.GL_POLYGON_STIPPLE); + gl.glPolygonStipple(screen_door_table[(int)(alpha * 16)]); + } + + if ((transparencyMode < TransparencyAttributes.SCREEN_DOOR) || + ((((geometryType & RenderMolecule.LINE) != 0) || + (polygonMode == PolygonAttributes.POLYGON_LINE)) + && lineAA) || + ((((geometryType & RenderMolecule.POINT) != 0) || + (polygonMode == PolygonAttributes.POLYGON_POINT)) + && pointAA)) { + gl.glEnable(GL.GL_BLEND); + // valid range of blendFunction 0..3 is already verified in shared code. + gl.glBlendFunc(blendFunctionTable[srcBlendFunction], blendFunctionTable[dstBlendFunction]); + } else { + gl.glDisable(GL.GL_BLEND); + } + } + + + // --------------------------------------------------------------------- + + // + // TextureAttributesRetained methods + // + + void updateTextureAttributes(Context ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, + float textureBlendColorRed, + float textureBlendColorGreen, + float textureBlendColorBlue, + float textureBlendColorAlpha, + int textureFormat) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureAttributes()"); + + GL gl = context(ctx).getGL(); + gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, + (perspCorrectionMode == TextureAttributes.NICEST) ? GL.GL_NICEST : GL.GL_FASTEST); + + // set OGL texture matrix + gl.glPushAttrib(GL.GL_TRANSFORM_BIT); + gl.glMatrixMode(GL.GL_TEXTURE); + + if (isIdentity) { + gl.glLoadIdentity(); + } else if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + gl.glLoadTransposeMatrixd(transform, 0); + } else { + double[] mx = new double[16]; + copyTranspose(transform, mx); + gl.glLoadMatrixd(mx, 0); + } + + gl.glPopAttrib(); + + // set texture color + float[] color = new float[4]; + color[0] = textureBlendColorRed; + color[1] = textureBlendColorGreen; + color[2] = textureBlendColorBlue; + color[3] = textureBlendColorAlpha; + gl.glTexEnvfv(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_COLOR, color, 0); + + // set texture environment mode + + switch (textureMode) { + case TextureAttributes.MODULATE: + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE); + break; + case TextureAttributes.DECAL: + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL); + break; + case TextureAttributes.BLEND: + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_BLEND); + break; + case TextureAttributes.REPLACE: + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); + break; + case TextureAttributes.COMBINE: + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_COMBINE); + break; + } + + if (gl.isExtensionAvailable("GL_SGI_texture_color_table")) { + gl.glDisable(GL.GL_TEXTURE_COLOR_TABLE_SGI); + } + } + + void updateRegisterCombiners(Context absCtx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, + float textureBlendColorRed, + float textureBlendColorGreen, + float textureBlendColorBlue, + float textureBlendColorAlpha, + int textureFormat, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale) { + if (VERBOSE) System.err.println("JoglPipeline.updateRegisterCombiners()"); + + JoglContext ctx = (JoglContext) absCtx; + GL gl = context(ctx).getGL(); + + if (perspCorrectionMode == TextureAttributes.NICEST) { + gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); + } else { + gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_FASTEST); + } + + // set OGL texture matrix + gl.glPushAttrib(GL.GL_TRANSFORM_BIT); + gl.glMatrixMode(GL.GL_TEXTURE); + + if (isIdentity) { + gl.glLoadIdentity(); + } else if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + gl.glLoadTransposeMatrixd(transform, 0); + } else { + double[] mx = new double[16]; + copyTranspose(transform, mx); + gl.glLoadMatrixd(mx, 0); + } + + gl.glPopAttrib(); + + // set texture color + float[] color = new float[4]; + color[0] = textureBlendColorRed; + color[1] = textureBlendColorGreen; + color[2] = textureBlendColorBlue; + color[3] = textureBlendColorAlpha; + gl.glTexEnvfv(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_COLOR, color, 0); + + // set texture environment mode + gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); + int textureUnit = ctx.getCurrentTextureUnit(); + int combinerUnit = ctx.getCurrentCombinerUnit(); + int fragment; + if (combinerUnit == GL.GL_COMBINER0_NV) { + fragment = GL.GL_PRIMARY_COLOR_NV; + } else { + fragment = GL.GL_SPARE0_NV; + } + + switch (textureMode) { + case TextureAttributes.MODULATE: + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_A_NV, fragment, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_B_NV, textureUnit, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_A_NV, fragment, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ALPHA); + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_B_NV, textureUnit, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ALPHA); + + gl.glCombinerOutputNV(combinerUnit, GL.GL_RGB, + GL.GL_SPARE0_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, + GL.GL_NONE, GL.GL_NONE, false, false, false); + gl.glCombinerOutputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_SPARE0_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, + GL.GL_NONE, GL.GL_NONE, false, false, false); + break; + + case TextureAttributes.DECAL: + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_A_NV, fragment, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_B_NV, textureUnit, + GL.GL_UNSIGNED_INVERT_NV, GL.GL_ALPHA); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_C_NV, textureUnit, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_D_NV, textureUnit, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ALPHA); + + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_A_NV, fragment, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ALPHA); + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_B_NV, GL.GL_ZERO, + GL.GL_UNSIGNED_INVERT_NV, GL.GL_ALPHA); + + gl.glCombinerOutputNV(combinerUnit, GL.GL_RGB, + GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, + GL.GL_NONE, GL.GL_NONE, false, false, false); + gl.glCombinerOutputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_SPARE0_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, + GL.GL_NONE, GL.GL_NONE, false, false, false); + break; + + case TextureAttributes.BLEND: + gl.glCombinerParameterfvNV(GL.GL_CONSTANT_COLOR0_NV, color, 0); + + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_A_NV, fragment, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_B_NV, textureUnit, + GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_C_NV, GL.GL_CONSTANT_COLOR0_NV, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_D_NV, textureUnit, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_A_NV, fragment, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ALPHA); + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_B_NV, textureUnit, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ALPHA); + + gl.glCombinerOutputNV(combinerUnit, GL.GL_RGB, + GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, + GL.GL_NONE, GL.GL_NONE, false, false, false); + gl.glCombinerOutputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_SPARE0_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, + GL.GL_NONE, GL.GL_NONE, false, false, false); + break; + + case TextureAttributes.REPLACE: + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_A_NV, textureUnit, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_B_NV, GL.GL_ZERO, + GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_A_NV, textureUnit, + GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ALPHA); + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_B_NV, GL.GL_ZERO, + GL.GL_UNSIGNED_INVERT_NV, GL.GL_ALPHA); + + gl.glCombinerOutputNV(combinerUnit, GL.GL_RGB, + GL.GL_SPARE0_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, + GL.GL_NONE, GL.GL_NONE, false, false, false); + gl.glCombinerOutputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_SPARE0_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, + GL.GL_NONE, GL.GL_NONE, false, false, false); + break; + + case TextureAttributes.COMBINE: + if (combineRgbMode == TextureAttributes.COMBINE_DOT3) { + int color1 = getCombinerArg(gl, combineRgbSrc[0], textureUnit, combinerUnit); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_A_NV, color1, + GL.GL_EXPAND_NORMAL_NV, GL.GL_RGB); + int color2 = getCombinerArg(gl, combineRgbSrc[1], textureUnit, combinerUnit); + gl.glCombinerInputNV(combinerUnit, GL.GL_RGB, + GL.GL_VARIABLE_B_NV, color2, + GL.GL_EXPAND_NORMAL_NV, GL.GL_RGB); + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_A_NV, GL.GL_ZERO, + GL.GL_UNSIGNED_INVERT_NV, GL.GL_ALPHA); + gl.glCombinerInputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_VARIABLE_B_NV, GL.GL_ZERO, + GL.GL_UNSIGNED_INVERT_NV, GL.GL_ALPHA); + + gl.glCombinerOutputNV(combinerUnit, GL.GL_RGB, + GL.GL_SPARE0_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, + GL.GL_NONE/*SCALE_BY_FOUR_NV*/, GL.GL_NONE, true, + false, false); + gl.glCombinerOutputNV(combinerUnit, GL.GL_ALPHA, + GL.GL_SPARE0_NV, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, + GL.GL_NONE, GL.GL_NONE, false, + false, false); + } + break; + } + + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_A_NV, + GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_B_NV, + GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_C_NV, + GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_D_NV, + GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_E_NV, + GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_F_NV, + GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_G_NV, + GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_ALPHA); + + if (gl.isExtensionAvailable("GL_SGI_texture_color_table")) + gl.glDisable(GL.GL_TEXTURE_COLOR_TABLE_SGI); + // GL_SGI_texture_color_table + } + + void updateTextureColorTable(Context ctx, int numComponents, + int colorTableSize, + int[] textureColorTable) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureColorTable()"); + + GL gl = context(ctx).getGL(); + if (gl.isExtensionAvailable("GL_SGI_texture_color_table")) { + if (numComponents == 3) { + gl.glColorTable(GL.GL_TEXTURE_COLOR_TABLE_SGI, GL.GL_RGB, + colorTableSize, GL.GL_RGB, GL.GL_INT, IntBuffer.wrap(textureColorTable)); + } else { + gl.glColorTable(GL.GL_TEXTURE_COLOR_TABLE_SGI, GL.GL_RGBA, + colorTableSize, GL.GL_RGBA, GL.GL_INT, IntBuffer.wrap(textureColorTable)); + } + gl.glEnable(GL.GL_TEXTURE_COLOR_TABLE_SGI); + } + } + + void updateCombiner(Context ctx, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale) { + if (VERBOSE) System.err.println("JoglPipeline.updateCombiner()"); + + GL gl = context(ctx).getGL(); + int[] GLrgbMode = new int[1]; + int[] GLalphaMode = new int[1]; + getGLCombineMode(gl, combineRgbMode, combineAlphaMode, + GLrgbMode, GLalphaMode); + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_COMBINE_RGB, GLrgbMode[0]); + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_COMBINE_ALPHA, GLalphaMode[0]); + + int nargs; + if (combineRgbMode == TextureAttributes.COMBINE_REPLACE) { + nargs = 1; + } else if (combineRgbMode == TextureAttributes.COMBINE_INTERPOLATE) { + nargs = 3; + } else { + nargs = 2; + } + + for (int i = 0; i < nargs; i++) { + gl.glTexEnvi(GL.GL_TEXTURE_ENV, _gl_combineRgbSrcIndex[i], + _gl_combineSrc[combineRgbSrc[i]]); + gl.glTexEnvi(GL.GL_TEXTURE_ENV, _gl_combineRgbOpIndex[i], + _gl_combineFcn[combineRgbFcn[i]]); + } + + if (combineAlphaMode == TextureAttributes.COMBINE_REPLACE) { + nargs = 1; + } else if (combineAlphaMode == TextureAttributes.COMBINE_INTERPOLATE) { + nargs = 3; + } else { + nargs = 2; + } + + for (int i = 0; i < nargs; i++) { + gl.glTexEnvi(GL.GL_TEXTURE_ENV, _gl_combineAlphaSrcIndex[i], + _gl_combineSrc[combineAlphaSrc[i]]); + gl.glTexEnvi(GL.GL_TEXTURE_ENV, _gl_combineAlphaOpIndex[i], + _gl_combineFcn[combineAlphaFcn[i]]); + } + + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_RGB_SCALE, combineRgbScale); + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_ALPHA_SCALE, combineAlphaScale); + } + + // Helper routines for above + + private void getGLCombineMode(GL gl, int combineRgbMode, int combineAlphaMode, + int[] GLrgbMode, int[] GLalphaMode) { + switch (combineRgbMode) { + case TextureAttributes.COMBINE_REPLACE: + GLrgbMode[0] = GL.GL_REPLACE; + break; + case TextureAttributes.COMBINE_MODULATE: + GLrgbMode[0] = GL.GL_MODULATE; + break; + case TextureAttributes.COMBINE_ADD: + GLrgbMode[0] = GL.GL_ADD; + break; + case TextureAttributes.COMBINE_ADD_SIGNED: + GLrgbMode[0] = GL.GL_ADD_SIGNED; + break; + case TextureAttributes.COMBINE_SUBTRACT: + GLrgbMode[0] = GL.GL_SUBTRACT; + break; + case TextureAttributes.COMBINE_INTERPOLATE: + GLrgbMode[0] = GL.GL_INTERPOLATE; + break; + case TextureAttributes.COMBINE_DOT3: + GLrgbMode[0] = GL.GL_DOT3_RGB; + break; + default: + break; + } + + switch (combineAlphaMode) { + case TextureAttributes.COMBINE_REPLACE: + GLalphaMode[0] = GL.GL_REPLACE; + break; + case TextureAttributes.COMBINE_MODULATE: + GLalphaMode[0] = GL.GL_MODULATE; + break; + case TextureAttributes.COMBINE_ADD: + GLalphaMode[0] = GL.GL_ADD; + break; + case TextureAttributes.COMBINE_ADD_SIGNED: + GLalphaMode[0] = GL.GL_ADD_SIGNED; + break; + case TextureAttributes.COMBINE_SUBTRACT: + GLalphaMode[0] = GL.GL_SUBTRACT; + break; + case TextureAttributes.COMBINE_INTERPOLATE: + GLalphaMode[0] = GL.GL_INTERPOLATE; + break; + case TextureAttributes.COMBINE_DOT3: + // dot3 will only make sense for alpha if rgb is also + // doing dot3. So if rgb is not doing dot3, fallback to replace + if (combineRgbMode == TextureAttributes.COMBINE_DOT3) { + GLrgbMode[0] = GL.GL_DOT3_RGBA; + } else { + GLalphaMode[0] = GL.GL_REPLACE; + } + break; + default: + break; + } + } + + // mapping from java enum to gl enum + private static final int[] _gl_combineRgbSrcIndex = { + GL.GL_SOURCE0_RGB, + GL.GL_SOURCE1_RGB, + GL.GL_SOURCE2_RGB, + }; + + private static final int[] _gl_combineAlphaSrcIndex = { + GL.GL_SOURCE0_ALPHA, + GL.GL_SOURCE1_ALPHA, + GL.GL_SOURCE2_ALPHA, + }; + + private static final int[] _gl_combineRgbOpIndex = { + GL.GL_OPERAND0_RGB, + GL.GL_OPERAND1_RGB, + GL.GL_OPERAND2_RGB, + }; + + private static final int[] _gl_combineAlphaOpIndex = { + GL.GL_OPERAND0_ALPHA, + GL.GL_OPERAND1_ALPHA, + GL.GL_OPERAND2_ALPHA, + }; + + private static final int[] _gl_combineSrc = { + GL.GL_PRIMARY_COLOR, // TextureAttributes.COMBINE_OBJECT_COLOR + GL.GL_TEXTURE, // TextureAttributes.COMBINE_TEXTURE + GL.GL_CONSTANT, // TextureAttributes.COMBINE_CONSTANT_COLOR + GL.GL_PREVIOUS, // TextureAttributes.COMBINE_PREVIOUS_TEXTURE_UNIT_STATE + }; + + private static final int[] _gl_combineFcn = { + GL.GL_SRC_COLOR, // TextureAttributes.COMBINE_SRC_COLOR + GL.GL_ONE_MINUS_SRC_COLOR, // TextureAttributes.COMBINE_ONE_MINUS_SRC_COLOR + GL.GL_SRC_ALPHA, // TextureAttributes.COMBINE_SRC_ALPHA + GL.GL_ONE_MINUS_SRC_ALPHA, // TextureAttributes.COMBINE_ONE_MINUS_SRC_ALPHA + }; + + private int getCombinerArg(GL gl, int arg, int textureUnit, int combUnit) { + int comb = 0; + + switch (arg) { + case TextureAttributes.COMBINE_OBJECT_COLOR: + if (combUnit == GL.GL_COMBINER0_NV) { + comb = GL.GL_PRIMARY_COLOR_NV; + } else { + comb = GL.GL_SPARE0_NV; + } + break; + case TextureAttributes.COMBINE_TEXTURE_COLOR: + comb = textureUnit; + break; + case TextureAttributes.COMBINE_CONSTANT_COLOR: + comb = GL.GL_CONSTANT_COLOR0_NV; + break; + case TextureAttributes.COMBINE_PREVIOUS_TEXTURE_UNIT_STATE: + comb = textureUnit -1; + break; + } + + return comb; + } + + + // --------------------------------------------------------------------- + + // + // TextureUnitStateRetained methods + // + + void updateTextureUnitState(Context ctx, int index, boolean enable) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureUnitState()"); + + GL gl = context(ctx).getGL(); + JoglContext jctx = (JoglContext) ctx; + + if (index >= 0 && gl.isExtensionAvailable("GL_VERSION_1_3")) { + gl.glActiveTexture(index + GL.GL_TEXTURE0); + gl.glClientActiveTexture(GL.GL_TEXTURE0 + index); + if (gl.isExtensionAvailable("GL_NV_register_combiners")) { + jctx.setCurrentTextureUnit(index + GL.GL_TEXTURE0); + jctx.setCurrentCombinerUnit(index + GL.GL_COMBINER0_NV); + gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, index + 1); + } + } + + if (!enable) { + // if not enabled, then don't enable any tex mapping + gl.glDisable(GL.GL_TEXTURE_1D); + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glDisable(GL.GL_TEXTURE_3D); + gl.glDisable(GL.GL_TEXTURE_CUBE_MAP); + } + + // if it is enabled, the enable flag will be taken care of + // in the bindTexture call + } + + + // --------------------------------------------------------------------- + + // + // TextureRetained methods + // Texture2DRetained methods + // + + void bindTexture2D(Context ctx, int objectId, boolean enable) { + if (VERBOSE) System.err.println("JoglPipeline.bindTexture2D(objectId=" + objectId + ",enable=" + enable + ")"); + + GL gl = context(ctx).getGL(); + gl.glDisable(GL.GL_TEXTURE_CUBE_MAP); + gl.glDisable(GL.GL_TEXTURE_3D); + + if (!enable) { + gl.glDisable(GL.GL_TEXTURE_2D); + } else { + gl.glBindTexture(GL.GL_TEXTURE_2D, objectId); + gl.glEnable(GL.GL_TEXTURE_2D); + } + } + + void updateTexture2DImage(Context ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int dataType, Object data) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DImage(width=" + width + ",height=" + height + ",level=" + level + ")"); + + updateTexture2DImage(ctx, GL.GL_TEXTURE_2D, + numLevels, level, textureFormat, imageFormat, + width, height, boundaryWidth, dataType, data); + } + + void updateTexture2DSubImage(Context ctx, + int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int dataType, Object data) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DSubImage()"); + + updateTexture2DSubImage(ctx, GL.GL_TEXTURE_2D, + level, xoffset, yoffset, + textureFormat, imageFormat, + imgXOffset, imgYOffset, tilew, width, height, + dataType, data); + } + + void updateTexture2DLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLOD, float maximumLOD) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DLodRange()"); + + updateTextureLodRange(ctx, GL.GL_TEXTURE_2D, + baseLevel, maximumLevel, + minimumLOD, maximumLOD); + } + + void updateTexture2DLodOffset(Context ctx, + float lodOffsetS, float lodOffsetT, + float lodOffsetR) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DLodOffset()"); + + updateTextureLodOffset(ctx, GL.GL_TEXTURE_2D, + lodOffsetS, lodOffsetT, lodOffsetR); + } + + void updateTexture2DBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DBoundary()"); + + updateTextureBoundary(ctx, GL.GL_TEXTURE_2D, + boundaryModeS, boundaryModeT, -1, + boundaryRed, boundaryGreen, + boundaryBlue, boundaryAlpha); + } + + void updateTexture2DFilterModes(Context ctx, + int minFilter, int magFilter) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DFilterModes()"); + + updateTextureFilterModes(ctx, GL.GL_TEXTURE_2D, minFilter, magFilter); + } + + void updateTexture2DSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DSharpenFunc()"); + + updateTextureSharpenFunc(ctx, GL.GL_TEXTURE_2D, + numSharpenTextureFuncPts, sharpenTextureFuncPts); + } + + void updateTexture2DFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DFilter4Func()"); + + updateTextureFilter4Func(ctx, GL.GL_TEXTURE_2D, + numFilter4FuncPts, filter4FuncPts); + } + + void updateTexture2DAnisotropicFilter(Context ctx, float degree) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture2DAnisotropicFilter()"); + + updateTextureAnisotropicFilter(ctx, GL.GL_TEXTURE_2D, degree); + } + + private void updateTextureLodRange(Context ctx, + int target, + int baseLevel, int maximumLevel, + float minimumLOD, float maximumLOD) { + GL gl = context(ctx).getGL(); + // checking of the availability of the extension is already done + // in the shared code + gl.glTexParameteri(target, GL.GL_TEXTURE_BASE_LEVEL, baseLevel); + gl.glTexParameteri(target, GL.GL_TEXTURE_MAX_LEVEL, maximumLevel); + gl.glTexParameterf(target, GL.GL_TEXTURE_MIN_LOD, minimumLOD); + gl.glTexParameterf(target, GL.GL_TEXTURE_MAX_LOD, maximumLOD); + } + + private void updateTextureLodOffset(Context ctx, + int target, + float lodOffsetS, float lodOffsetT, + float lodOffsetR) { + GL gl = context(ctx).getGL(); + // checking of the availability of the extension is already done + // in the shared code + gl.glTexParameterf(target, GL.GL_TEXTURE_LOD_BIAS_S_SGIX, lodOffsetS); + gl.glTexParameterf(target, GL.GL_TEXTURE_LOD_BIAS_T_SGIX, lodOffsetT); + gl.glTexParameterf(target, GL.GL_TEXTURE_LOD_BIAS_R_SGIX, lodOffsetR); + } + + private void updateTextureAnisotropicFilter(Context ctx, int target, float degree) { + GL gl = context(ctx).getGL(); + // checking of the availability of anisotropic filter functionality + // is already done in the shared code + gl.glTexParameterf(target, + GL.GL_TEXTURE_MAX_ANISOTROPY_EXT, + degree); + } + + // --------------------------------------------------------------------- + + // + // Texture3DRetained methods + // + + void bindTexture3D(Context ctx, int objectId, boolean enable) { + if (VERBOSE) System.err.println("JoglPipeline.bindTexture3D()"); + + GL gl = context(ctx).getGL(); + // textureCubeMap will take precedure over 3D Texture + gl.glDisable(GL.GL_TEXTURE_CUBE_MAP); + + if (!enable) { + gl.glDisable(GL.GL_TEXTURE_3D); + } else { + gl.glBindTexture(GL.GL_TEXTURE_3D, objectId); + gl.glEnable(GL.GL_TEXTURE_3D); + } + } + + void updateTexture3DImage(Context ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, int depth, + int boundaryWidth, + int dataType, Object data) { + + /* TODO Chien : Need to support INT, and NIO buffers */ + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DImage()"); + + GL gl = context(ctx).getGL(); + + int format = 0; + int internalFormat = 0; + int type = GL.GL_UNSIGNED_INT_8_8_8_8; + boolean forceAlphaToOne = false; + + // check if we are trying to draw NPOT on a system that doesn't support it + boolean textureNonPowerOfTwoAvailable = + gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") || + gl.isExtensionAvailable("GL_VERSION_2_0"); + + if (!textureNonPowerOfTwoAvailable && + (!isPowerOfTwo(width) || !isPowerOfTwo(height) || !isPowerOfTwo(depth))) { + // disable texture by setting width, height and depth to 0 + width = height = depth = 0; + } + + switch (textureFormat) { + case Texture.INTENSITY: + internalFormat = GL.GL_INTENSITY; + break; + case Texture.LUMINANCE: + internalFormat = GL.GL_LUMINANCE; + break; + case Texture.ALPHA: + internalFormat = GL.GL_ALPHA; + break; + case Texture.LUMINANCE_ALPHA: + internalFormat = GL.GL_LUMINANCE_ALPHA; + break; + case Texture.RGB: + internalFormat = GL.GL_RGB; + break; + case Texture.RGBA: + internalFormat = GL.GL_RGBA; + break; + default: + assert false; + return; + } + + if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_BUFFER)) { + + switch (imageFormat) { + case ImageComponentRetained.TYPE_BYTE_BGR: + format = GL.GL_BGR; + break; + case ImageComponentRetained.TYPE_BYTE_RGB: + format = GL.GL_RGB; + break; + case ImageComponentRetained.TYPE_BYTE_ABGR: + if (gl.isExtensionAvailable("GL_EXT_abgr")) { // If its zero, should never come here! + format = GL.GL_ABGR_EXT; + } else { + assert false; + return; + } + break; + case ImageComponentRetained.TYPE_BYTE_RGBA: + // all RGB types are stored as RGBA + format = GL.GL_RGBA; + break; + case ImageComponentRetained.TYPE_BYTE_LA: + // all LA types are stored as LA8 + format = GL.GL_LUMINANCE_ALPHA; + break; + case ImageComponentRetained.TYPE_BYTE_GRAY: + if (internalFormat == GL.GL_ALPHA) { + format = GL.GL_ALPHA; + } else { + format = GL.GL_LUMINANCE; + } + break; + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_INT_BGR: + case ImageComponentRetained.TYPE_INT_RGB: + case ImageComponentRetained.TYPE_INT_ARGB: + default: + assert false; + return; + } + + gl.glTexImage3D(GL.GL_TEXTURE_3D, + level, internalFormat, + width, height, depth, boundaryWidth, + format, GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap((byte[]) data)); + + } else if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_BUFFER)) { + + switch (imageFormat) { + /* GL_BGR */ + case ImageComponentRetained.TYPE_INT_BGR: /* Assume XBGR format */ + format = GL.GL_RGBA; + type = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + forceAlphaToOne = true; + break; + case ImageComponentRetained.TYPE_INT_RGB: /* Assume XRGB format */ + forceAlphaToOne = true; + /* Fall through to next case */ + case ImageComponentRetained.TYPE_INT_ARGB: + format = GL.GL_BGRA; + type = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + break; + /* This method only supports 3 and 4 components formats and INT types. */ + case ImageComponentRetained.TYPE_BYTE_LA: + case ImageComponentRetained.TYPE_BYTE_GRAY: + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_BYTE_BGR: + case ImageComponentRetained.TYPE_BYTE_RGB: + case ImageComponentRetained.TYPE_BYTE_RGBA: + case ImageComponentRetained.TYPE_BYTE_ABGR: + default: + assert false; + return; + } + + /* Force Alpha to 1.0 if needed */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 0.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 1.0f); + } + + gl.glTexImage3D(GL.GL_TEXTURE_3D, + level, internalFormat, + width, height, depth, boundaryWidth, + format, type, IntBuffer.wrap((int[]) data)); + + /* Restore Alpha scale and bias */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 1.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 0.0f); + } + } else { + assert false; + } + } + + void updateTexture3DSubImage(Context ctx, + int level, + int xoffset, int yoffset, int zoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, int imgZOffset, + int tilew, int tileh, + int width, int height, int depth, + int dataType, Object data) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DSubImage()"); + + /* TODO Chien : Need to support INT, and NIO buffers */ + GL gl = context(ctx).getGL(); + + int format = 0; + int internalFormat = 0; + int type = GL.GL_UNSIGNED_INT_8_8_8_8; + int numBytes = 0; + boolean forceAlphaToOne = false; + boolean pixelStore = false; + + if (imgXOffset > 0 || (width < tilew)) { + pixelStore = true; + gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, tilew); + } + + // if NPOT textures are not supported, check if h=w=0, if so we have been + // disabled due to a NPOT texture being sent to a context that doesn't + // support it: disable the glTexSubImage as well + boolean textureNonPowerOfTwoAvailable = + gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") || + gl.isExtensionAvailable("GL_VERSION_2_0"); + + if (!textureNonPowerOfTwoAvailable) { + int[] tmp = new int[1]; + int texWidth, texHeight, texDepth; + gl.glGetTexLevelParameteriv(GL.GL_TEXTURE_2D, 0, GL.GL_TEXTURE_WIDTH, tmp, 0); + texWidth = tmp[0]; + gl.glGetTexLevelParameteriv(GL.GL_TEXTURE_2D, 0, GL.GL_TEXTURE_HEIGHT, tmp, 0); + texHeight = tmp[0]; + gl.glGetTexLevelParameteriv(GL.GL_TEXTURE_2D, 0, GL.GL_TEXTURE_DEPTH, tmp, 0); + texDepth = tmp[0]; + if ((texWidth == 0) && (texHeight == 0) && (texDepth == 0)) { + // disable the sub-image by setting it's width, height and depth to 0 + width = height = depth = 0; + } + } + + switch (textureFormat) { + case Texture.INTENSITY: + internalFormat = GL.GL_INTENSITY; + break; + case Texture.LUMINANCE: + internalFormat = GL.GL_LUMINANCE; + break; + case Texture.ALPHA: + internalFormat = GL.GL_ALPHA; + break; + case Texture.LUMINANCE_ALPHA: + internalFormat = GL.GL_LUMINANCE_ALPHA; + break; + case Texture.RGB: + internalFormat = GL.GL_RGB; + break; + case Texture.RGBA: + internalFormat = GL.GL_RGBA; + break; + default: + assert false; + } + + if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_BUFFER)) { + + switch (imageFormat) { + case ImageComponentRetained.TYPE_BYTE_BGR: + format = GL.GL_BGR; + numBytes = 3; + break; + case ImageComponentRetained.TYPE_BYTE_RGB: + format = GL.GL_RGB; + numBytes = 3; + break; + case ImageComponentRetained.TYPE_BYTE_ABGR: + if (gl.isExtensionAvailable("GL_EXT_abgr")) { // If its zero, should never come here! + format = GL.GL_ABGR_EXT; + numBytes = 4; + } else { + assert false; + return; + } + break; + case ImageComponentRetained.TYPE_BYTE_RGBA: + // all RGB types are stored as RGBA + format = GL.GL_RGBA; + numBytes = 4; + break; + case ImageComponentRetained.TYPE_BYTE_LA: + // all LA types are stored as LA8 + format = GL.GL_LUMINANCE_ALPHA; + numBytes = 2; + break; + case ImageComponentRetained.TYPE_BYTE_GRAY: + if (internalFormat == GL.GL_ALPHA) { + format = GL.GL_ALPHA; + numBytes = 1; + } else { + format = GL.GL_LUMINANCE; + numBytes = 1; + } + break; + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_INT_BGR: + case ImageComponentRetained.TYPE_INT_RGB: + case ImageComponentRetained.TYPE_INT_ARGB: + default: + assert false; + return; + } + + ByteBuffer buf = ByteBuffer.wrap((byte[]) data); + int offset = (tilew * tileh * imgZOffset + + tilew * imgYOffset + imgXOffset) * numBytes; + buf.position(offset); + gl.glTexSubImage3D(GL.GL_TEXTURE_3D, + level, xoffset, yoffset, zoffset, + width, height, depth, + format, GL.GL_UNSIGNED_BYTE, + buf); + + } else if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_BUFFER)) { + + switch (imageFormat) { + /* GL_BGR */ + case ImageComponentRetained.TYPE_INT_BGR: /* Assume XBGR format */ + format = GL.GL_RGBA; + type = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + forceAlphaToOne = true; + break; + case ImageComponentRetained.TYPE_INT_RGB: /* Assume XRGB format */ + forceAlphaToOne = true; + /* Fall through to next case */ + case ImageComponentRetained.TYPE_INT_ARGB: + format = GL.GL_BGRA; + type = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + break; + /* This method only supports 3 and 4 components formats and INT types. */ + case ImageComponentRetained.TYPE_BYTE_LA: + case ImageComponentRetained.TYPE_BYTE_GRAY: + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_BYTE_BGR: + case ImageComponentRetained.TYPE_BYTE_RGB: + case ImageComponentRetained.TYPE_BYTE_RGBA: + case ImageComponentRetained.TYPE_BYTE_ABGR: + default: + assert false; + return; + } + + /* Force Alpha to 1.0 if needed */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 0.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 1.0f); + } + + IntBuffer buf = IntBuffer.wrap((int[]) data); + int offset = tilew * tileh * imgZOffset + + tilew * imgYOffset + imgXOffset; + buf.position(offset); + gl.glTexSubImage3D(GL.GL_TEXTURE_3D, + level, xoffset, yoffset, zoffset, + width, height, depth, + format, type, + buf); + + /* Restore Alpha scale and bias */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 1.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 0.0f); + } + } else { + assert false; + return; + } + + if (pixelStore) { + gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 0); + } + + } + + + void updateTexture3DLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DLodRange()"); + + updateTextureLodRange(ctx, GL.GL_TEXTURE_3D, + baseLevel, maximumLevel, + minimumLod, maximumLod); + } + + void updateTexture3DLodOffset(Context ctx, + float lodOffsetS, float lodOffsetT, + float lodOffsetR) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DLodOffset()"); + + updateTextureLodOffset(ctx, GL.GL_TEXTURE_3D, + lodOffsetS, lodOffsetT, lodOffsetR); + } + + void updateTexture3DBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + int boundaryModeR, float boundaryRed, + float boundaryGreen, float boundaryBlue, + float boundaryAlpha) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DBoundary()"); + + updateTextureBoundary(ctx, GL.GL_TEXTURE_2D, + boundaryModeS, boundaryModeT, boundaryModeR, + boundaryRed, boundaryGreen, + boundaryBlue, boundaryAlpha); + } + + void updateTexture3DFilterModes(Context ctx, + int minFilter, int magFilter) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DFilterModes()"); + + updateTextureFilterModes(ctx, GL.GL_TEXTURE_3D, + minFilter, magFilter); + } + + void updateTexture3DSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DSharpenFunc()"); + + updateTextureSharpenFunc(ctx, GL.GL_TEXTURE_3D, + numSharpenTextureFuncPts, sharpenTextureFuncPts); + } + + void updateTexture3DFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DFilter4Func()"); + + updateTextureFilter4Func(ctx, GL.GL_TEXTURE_3D, + numFilter4FuncPts, filter4FuncPts); + } + + void updateTexture3DAnisotropicFilter(Context ctx, float degree) { + if (VERBOSE) System.err.println("JoglPipeline.updateTexture3DAnisotropicFilter()"); + + updateTextureAnisotropicFilter(ctx, GL.GL_TEXTURE_3D, degree); + } + + + // --------------------------------------------------------------------- + + // + // TextureCubeMapRetained methods + // + + void bindTextureCubeMap(Context ctx, int objectId, boolean enable) { + if (VERBOSE) System.err.println("JoglPipeline.bindTextureCubeMap()"); + + GL gl = context(ctx).getGL(); + // TextureCubeMap will take precedure over 3D Texture so + // there is no need to disable 3D Texture here. + if (!enable) { + gl.glDisable(GL.GL_TEXTURE_CUBE_MAP); + } else { + gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP, objectId); + gl.glEnable(GL.GL_TEXTURE_CUBE_MAP); + } + } + + void updateTextureCubeMapImage(Context ctx, + int face, int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int dataType, Object data) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapImage()"); + + updateTexture2DImage(ctx, _gl_textureCubeMapFace[face], + numLevels, level, textureFormat, imageFormat, + width, height, boundaryWidth, dataType, data); + } + + void updateTextureCubeMapSubImage(Context ctx, + int face, int level, int xoffset, int yoffset, + int textureFormat,int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int dataType, Object data) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapSubImage()"); + + updateTexture2DSubImage(ctx, _gl_textureCubeMapFace[face], + level, xoffset, yoffset, textureFormat, + imageFormat, imgXOffset, imgYOffset, tilew, + width, height, dataType, data); + } + + void updateTextureCubeMapLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapLodRange()"); + + updateTextureLodRange(ctx, + GL.GL_TEXTURE_CUBE_MAP, + baseLevel, maximumLevel, + minimumLod, maximumLod); + } + + void updateTextureCubeMapLodOffset(Context ctx, + float lodOffsetS, float lodOffsetT, + float lodOffsetR) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapLodOffset()"); + + updateTextureLodOffset(ctx, + GL.GL_TEXTURE_CUBE_MAP, + lodOffsetS, lodOffsetT, lodOffsetR); + } + + void updateTextureCubeMapBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapBoundary()"); + + updateTextureBoundary(ctx, + GL.GL_TEXTURE_CUBE_MAP, + boundaryModeS, boundaryModeT, -1, + boundaryRed, boundaryGreen, + boundaryBlue, boundaryAlpha); + } + + void updateTextureCubeMapFilterModes(Context ctx, + int minFilter, int magFilter) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapFilterModes()"); + + updateTextureFilterModes(ctx, + GL.GL_TEXTURE_CUBE_MAP, + minFilter, magFilter); + } + + void updateTextureCubeMapSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapSharpenFunc()"); + + updateTextureSharpenFunc(ctx, + GL.GL_TEXTURE_CUBE_MAP, + numSharpenTextureFuncPts, sharpenTextureFuncPts); + } + + void updateTextureCubeMapFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapFilter4Func()"); + + updateTextureFilter4Func(ctx, + GL.GL_TEXTURE_CUBE_MAP, + numFilter4FuncPts, filter4FuncPts); + } + + void updateTextureCubeMapAnisotropicFilter(Context ctx, float degree) { + if (VERBOSE) System.err.println("JoglPipeline.updateTextureCubeMapAnisotropicFilter()"); + + updateTextureAnisotropicFilter(ctx, + GL.GL_TEXTURE_CUBE_MAP, + degree); + } + + //---------------------------------------------------------------------- + // + // Helper routines for above texture methods + // + + private void updateTexture2DImage(Context ctx, + int target, + int numLevels, + int level, + int textureFormat, + int imageFormat, + int width, + int height, + int boundaryWidth, + int dataType, + Object data) { + GL gl = context(ctx).getGL(); + + int format = 0, internalFormat = 0; + int type = GL.GL_UNSIGNED_INT_8_8_8_8; + boolean forceAlphaToOne = false; + + // check if we are trying to draw NPOT on a system that doesn't support it + boolean textureNonPowerOfTwoAvailable = + gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") || + gl.isExtensionAvailable("GL_VERSION_2_0"); + + if (!textureNonPowerOfTwoAvailable && + (!isPowerOfTwo(width) || !isPowerOfTwo(height))) { + // disable texture by setting width and height to 0 + width = height = 0; + } + + switch (textureFormat) { + case Texture.INTENSITY: + internalFormat = GL.GL_INTENSITY; + break; + case Texture.LUMINANCE: + internalFormat = GL.GL_LUMINANCE; + break; + case Texture.ALPHA: + internalFormat = GL.GL_ALPHA; + break; + case Texture.LUMINANCE_ALPHA: + internalFormat = GL.GL_LUMINANCE_ALPHA; + break; + case Texture.RGB: + internalFormat = GL.GL_RGB; + break; + case Texture.RGBA: + internalFormat = GL.GL_RGBA; + break; + default: + assert false; + } + + if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_BUFFER)) { + + switch (imageFormat) { + case ImageComponentRetained.TYPE_BYTE_BGR: + format = GL.GL_BGR; + break; + case ImageComponentRetained.TYPE_BYTE_RGB: + format = GL.GL_RGB; + break; + case ImageComponentRetained.TYPE_BYTE_ABGR: + if (gl.isExtensionAvailable("GL_EXT_abgr")) { // If its zero, should never come here! + format = GL.GL_ABGR_EXT; + } else { + assert false; + return; + } + break; + case ImageComponentRetained.TYPE_BYTE_RGBA: + // all RGB types are stored as RGBA + format = GL.GL_RGBA; + break; + case ImageComponentRetained.TYPE_BYTE_LA: + // all LA types are stored as LA8 + format = GL.GL_LUMINANCE_ALPHA; + break; + case ImageComponentRetained.TYPE_BYTE_GRAY: + if (internalFormat == GL.GL_ALPHA) { + format = GL.GL_ALPHA; + } else { + format = GL.GL_LUMINANCE; + } + break; + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_INT_BGR: + case ImageComponentRetained.TYPE_INT_RGB: + case ImageComponentRetained.TYPE_INT_ARGB: + default: + assert false; + return; + } + + gl.glTexImage2D(target, level, internalFormat, + width, height, boundaryWidth, + format, GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap((byte[]) data)); + + } else if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_BUFFER)) { + + switch (imageFormat) { + /* GL_BGR */ + case ImageComponentRetained.TYPE_INT_BGR: /* Assume XBGR format */ + format = GL.GL_RGBA; + type = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + forceAlphaToOne = true; + break; + case ImageComponentRetained.TYPE_INT_RGB: /* Assume XRGB format */ + forceAlphaToOne = true; + /* Fall through to next case */ + case ImageComponentRetained.TYPE_INT_ARGB: + format = GL.GL_BGRA; + type = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + break; + /* This method only supports 3 and 4 components formats and INT types. */ + case ImageComponentRetained.TYPE_BYTE_LA: + case ImageComponentRetained.TYPE_BYTE_GRAY: + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_BYTE_BGR: + case ImageComponentRetained.TYPE_BYTE_RGB: + case ImageComponentRetained.TYPE_BYTE_RGBA: + case ImageComponentRetained.TYPE_BYTE_ABGR: + default: + assert false; + return; + } + + /* Force Alpha to 1.0 if needed */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 0.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 1.0f); + } + + gl.glTexImage2D(target, level, internalFormat, + width, height, boundaryWidth, + format, type, IntBuffer.wrap((int[]) data)); + + /* Restore Alpha scale and bias */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 1.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 0.0f); + } + } else { + assert false; + } + } + + private void updateTexture2DSubImage(Context ctx, + int target, + int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int dataType, Object data) { + GL gl = context(ctx).getGL(); + + int format = 0, internalFormat=0; + int numBytes = 0; + int type = GL.GL_UNSIGNED_INT_8_8_8_8; + boolean forceAlphaToOne = false; + boolean pixelStore = false; + + if (imgXOffset > 0 || (width < tilew)) { + pixelStore = true; + gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, tilew); + } + + // if NPOT textures are not supported, check if h=w=0, if so we have been + // disabled due to a NPOT texture being sent to a context that doesn't + // support it: disable the glTexSubImage as well + boolean textureNonPowerOfTwoAvailable = + gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") || + gl.isExtensionAvailable("GL_VERSION_2_0"); + + if (!textureNonPowerOfTwoAvailable) { + int[] tmp = new int[1]; + int texWidth, texHeight; + gl.glGetTexLevelParameteriv(GL.GL_TEXTURE_2D, 0, GL.GL_TEXTURE_WIDTH, tmp, 0); + texWidth = tmp[0]; + gl.glGetTexLevelParameteriv(GL.GL_TEXTURE_2D, 0, GL.GL_TEXTURE_HEIGHT, tmp, 0); + texHeight = tmp[0]; + if ((texWidth == 0) && (texHeight == 0)) { + // disable the sub-image by setting it's width and height to 0 + width = height = 0; + } + } + + switch (textureFormat) { + case Texture.INTENSITY: + internalFormat = GL.GL_INTENSITY; + break; + case Texture.LUMINANCE: + internalFormat = GL.GL_LUMINANCE; + break; + case Texture.ALPHA: + internalFormat = GL.GL_ALPHA; + break; + case Texture.LUMINANCE_ALPHA: + internalFormat = GL.GL_LUMINANCE_ALPHA; + break; + case Texture.RGB: + internalFormat = GL.GL_RGB; + break; + case Texture.RGBA: + internalFormat = GL.GL_RGBA; + break; + default: + assert false; + } + + if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_BUFFER)) { + + switch (imageFormat) { + case ImageComponentRetained.TYPE_BYTE_BGR: + format = GL.GL_BGR; + numBytes = 3; + break; + case ImageComponentRetained.TYPE_BYTE_RGB: + format = GL.GL_RGB; + numBytes = 3; + break; + case ImageComponentRetained.TYPE_BYTE_ABGR: + if (gl.isExtensionAvailable("GL_EXT_abgr")) { // If its zero, should never come here! + format = GL.GL_ABGR_EXT; + numBytes = 4; + } else { + assert false; + return; + } + break; + case ImageComponentRetained.TYPE_BYTE_RGBA: + // all RGB types are stored as RGBA + format = GL.GL_RGBA; + numBytes = 4; + break; + case ImageComponentRetained.TYPE_BYTE_LA: + // all LA types are stored as LA8 + format = GL.GL_LUMINANCE_ALPHA; + numBytes = 2; + break; + case ImageComponentRetained.TYPE_BYTE_GRAY: + if (internalFormat == GL.GL_ALPHA) { + format = GL.GL_ALPHA; + numBytes = 1; + } else { + format = GL.GL_LUMINANCE; + numBytes = 1; + } + break; + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_INT_BGR: + case ImageComponentRetained.TYPE_INT_RGB: + case ImageComponentRetained.TYPE_INT_ARGB: + default: + assert false; + return; + } + + ByteBuffer buf = ByteBuffer.wrap((byte[]) data); + + // offset by the imageOffset + buf.position((tilew * imgYOffset + imgXOffset) * numBytes); + gl.glTexSubImage2D(target, level, xoffset, yoffset, width, height, + format, GL.GL_UNSIGNED_BYTE, buf); + + } else if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_BUFFER)) { + + switch (imageFormat) { + /* GL_BGR */ + case ImageComponentRetained.TYPE_INT_BGR: /* Assume XBGR format */ + format = GL.GL_RGBA; + type = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + forceAlphaToOne = true; + break; + case ImageComponentRetained.TYPE_INT_RGB: /* Assume XRGB format */ + forceAlphaToOne = true; + /* Fall through to next case */ + case ImageComponentRetained.TYPE_INT_ARGB: + format = GL.GL_BGRA; + type = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + break; + /* This method only supports 3 and 4 components formats and INT types. */ + case ImageComponentRetained.TYPE_BYTE_LA: + case ImageComponentRetained.TYPE_BYTE_GRAY: + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_BYTE_BGR: + case ImageComponentRetained.TYPE_BYTE_RGB: + case ImageComponentRetained.TYPE_BYTE_RGBA: + case ImageComponentRetained.TYPE_BYTE_ABGR: + default: + assert false; + return; + } + /* Force Alpha to 1.0 if needed */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 0.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 1.0f); + } + + IntBuffer buf = IntBuffer.wrap((int[]) data); + + // offset by the imageOffset + buf.position(tilew * imgYOffset + imgXOffset); + gl.glTexSubImage2D(target, level, xoffset, yoffset, width, height, + format, type, buf); + + /* Restore Alpha scale and bias */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 1.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 0.0f); + } + } else { + assert false; + return; + } + + if (pixelStore) { + gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 0); + } + + } + + + private static boolean isPowerOfTwo(int val) { + return ((val & (val - 1)) == 0); + } + + void updateTextureFilterModes(Context ctx, + int target, + int minFilter, + int magFilter) { + GL gl = context(ctx).getGL(); + + if (EXTRA_DEBUGGING) { + System.err.println("minFilter: " + getFilterName(minFilter) + + " magFilter: " + getFilterName(magFilter)); + } + + // FIXME: unclear whether we really need to set up the enum values + // in the JoglContext as is done in the native code depending on + // extension availability; maybe this is the defined fallback + // behavior of the various Java3D modes + + // set texture min filter + switch (minFilter) { + case Texture.FASTEST: + case Texture.BASE_LEVEL_POINT: + gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + break; + case Texture.BASE_LEVEL_LINEAR: + gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + break; + case Texture.MULTI_LEVEL_POINT: + gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, + GL.GL_NEAREST_MIPMAP_NEAREST); + break; + case Texture.NICEST: + case Texture.MULTI_LEVEL_LINEAR: + gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, + GL.GL_LINEAR_MIPMAP_LINEAR); + break; + case Texture.FILTER4: + gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, + GL.GL_FILTER4_SGIS); + break; + } + + // set texture mag filter + switch (magFilter) { + case Texture.FASTEST: + case Texture.BASE_LEVEL_POINT: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + break; + case Texture.NICEST: + case Texture.BASE_LEVEL_LINEAR: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + break; + case Texture.LINEAR_SHARPEN: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, + GL.GL_LINEAR_SHARPEN_SGIS); + break; + case Texture.LINEAR_SHARPEN_RGB: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, + GL.GL_LINEAR_SHARPEN_COLOR_SGIS); + break; + case Texture.LINEAR_SHARPEN_ALPHA: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, + GL.GL_LINEAR_SHARPEN_ALPHA_SGIS); + break; + case Texture2D.LINEAR_DETAIL: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, + GL.GL_LINEAR_DETAIL_SGIS); + break; + case Texture2D.LINEAR_DETAIL_RGB: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, + GL.GL_LINEAR_DETAIL_COLOR_SGIS); + break; + case Texture2D.LINEAR_DETAIL_ALPHA: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, + GL.GL_LINEAR_DETAIL_ALPHA_SGIS); + break; + case Texture.FILTER4: + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, + GL.GL_FILTER4_SGIS); + break; + } + } + + void updateTextureBoundary(Context ctx, + int target, + int boundaryModeS, + int boundaryModeT, + int boundaryModeR, + float boundaryRed, + float boundaryGreen, + float boundaryBlue, + float boundaryAlpha) { + GL gl = context(ctx).getGL(); + + // set texture wrap parameter + switch (boundaryModeS) { + case Texture.WRAP: + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + break; + case Texture.CLAMP: + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP); + break; + case Texture.CLAMP_TO_EDGE: + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, + GL.GL_CLAMP_TO_EDGE); + break; + case Texture.CLAMP_TO_BOUNDARY: + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, + GL.GL_CLAMP_TO_BORDER); + break; + } + + switch (boundaryModeT) { + case Texture.WRAP: + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + break; + case Texture.CLAMP: + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP); + break; + case Texture.CLAMP_TO_EDGE: + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, + GL.GL_CLAMP_TO_EDGE); + break; + case Texture.CLAMP_TO_BOUNDARY: + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, + GL.GL_CLAMP_TO_BORDER); + break; + } + + // applies to Texture3D only + if (boundaryModeR != -1) { + switch (boundaryModeR) { + case Texture.WRAP: + gl.glTexParameteri(target, + GL.GL_TEXTURE_WRAP_R, GL.GL_REPEAT); + break; + + case Texture.CLAMP: + gl.glTexParameteri(target, + GL.GL_TEXTURE_WRAP_R, GL.GL_CLAMP); + break; + case Texture.CLAMP_TO_EDGE: + gl.glTexParameteri(target, + GL.GL_TEXTURE_WRAP_R, + GL.GL_CLAMP_TO_EDGE); + break; + case Texture.CLAMP_TO_BOUNDARY: + gl.glTexParameteri(target, + GL.GL_TEXTURE_WRAP_R, + GL.GL_CLAMP_TO_BORDER); + break; + } + } + + if (boundaryModeS == Texture.CLAMP || + boundaryModeT == Texture.CLAMP || + boundaryModeR == Texture.CLAMP) { + // set texture border color + float[] color = new float[4]; + color[0] = boundaryRed; + color[1] = boundaryGreen; + color[2] = boundaryBlue; + color[3] = boundaryAlpha; + gl.glTexParameterfv(target, GL.GL_TEXTURE_BORDER_COLOR, color, 0); + } + } + + private static final String getFilterName(int filter) { + switch (filter) { + case Texture.FASTEST: + return "Texture.FASTEST"; + case Texture.NICEST: + return "Texture.NICEST"; + case Texture.BASE_LEVEL_POINT: + return "Texture.BASE_LEVEL_POINT"; + case Texture.BASE_LEVEL_LINEAR: + return "Texture.BASE_LEVEL_LINEAR"; + case Texture.MULTI_LEVEL_POINT: + return "Texture.MULTI_LEVEL_POINT"; + case Texture.MULTI_LEVEL_LINEAR: + return "Texture.MULTI_LEVEL_LINEAR"; + case Texture.FILTER4: + return "Texture.FILTER4"; + case Texture.LINEAR_SHARPEN: + return "Texture.LINEAR_SHARPEN"; + case Texture.LINEAR_SHARPEN_RGB: + return "Texture.LINEAR_SHARPEN_RGB"; + case Texture.LINEAR_SHARPEN_ALPHA: + return "Texture.LINEAR_SHARPEN_ALPHA"; + case Texture2D.LINEAR_DETAIL: + return "Texture.LINEAR_DETAIL"; + case Texture2D.LINEAR_DETAIL_RGB: + return "Texture.LINEAR_DETAIL_RGB"; + case Texture2D.LINEAR_DETAIL_ALPHA: + return "Texture.LINEAR_DETAIL_ALPHA"; + default: + return "(unknown)"; + } + } + + private void updateTextureSharpenFunc(Context ctx, + int target, + int numPts, + float[] pts) { + // checking of the availability of sharpen texture functionality + // is already done in shared code + GL gl = context(ctx).getGL(); + gl.glSharpenTexFuncSGIS(target, numPts, pts, 0); + } + + private void updateTextureFilter4Func(Context ctx, + int target, + int numPts, + float[] pts) { + // checking of the availability of filter4 functionality + // is already done in shared code + GL gl = context(ctx).getGL(); + gl.glTexFilterFuncSGIS(target, GL.GL_FILTER4_SGIS, + numPts, pts, 0); + } + + // mapping from java enum to gl enum + private static final int[] _gl_textureCubeMapFace = { + GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + }; + + // --------------------------------------------------------------------- + + // + // MasterControl methods + // + + // Method to return the AWT object + long getAWT() { + if (VERBOSE) System.err.println("JoglPipeline.getAWT()"); + + // FIXME: probably completely unneeded in this implementation, + // but should probably remove this dependence in the shared code + return 0; + } + + // Method to initialize the native J3D library + boolean initializeJ3D(boolean disableXinerama) { + // Dummy method in JOGL pipeline + return true; + } + + // Maximum lights supported by the native API + int getMaximumLights() { + if (VERBOSE) System.err.println("JoglPipeline.getMaximumLights()"); + + // FIXME: this isn't quite what the NativePipeline returns but + // is probably close enough + return 8; + } + + + // --------------------------------------------------------------------- + + // + // Canvas3D methods - native wrappers + // + + // This is the native method for creating the underlying graphics context. + Context createNewContext(Canvas3D cv, long display, Drawable drawable, + long fbConfig, Context shareCtx, boolean isSharedCtx, + boolean offScreen, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + if (VERBOSE) System.err.println("JoglPipeline.createNewContext()"); + GLDrawable draw = null; + GLCapabilitiesChooser indexChooser = null; + JoglGraphicsConfiguration config = (JoglGraphicsConfiguration) cv.graphicsConfiguration; + if (config.getChosenIndex() >= 0) { + indexChooser = new IndexCapabilitiesChooser(config.getChosenIndex()); + } + if (cv.drawable == null) { + draw = + GLDrawableFactory.getFactory().getGLDrawable(cv, + config.getGLCapabilities(), + indexChooser); + cv.drawable = new JoglDrawable(draw); + } else { + draw = drawable(cv.drawable); + } + + // FIXME: assuming that this only gets called after addNotify has been called + draw.setRealized(true); + GLContext context = draw.createContext(context(shareCtx)); + + // Apparently we are supposed to make the context current at + // this point and set up a bunch of properties + if (context.makeCurrent() == GLContext.CONTEXT_NOT_CURRENT) { + throw new IllegalRenderingStateException("Unable to make new context current"); + } + + GL gl = context.getGL(); + JoglContext ctx = new JoglContext(context); + + try { + if (!getPropertiesFromCurrentContext(ctx)) { + throw new IllegalRenderingStateException("Unable to fetch properties from current OpenGL context"); + } + + if(!isSharedCtx){ + // Set up fields in Canvas3D + setupCanvasProperties(cv, ctx, gl, glslLibraryAvailable, cgLibraryAvailable); + } + + // Enable rescale normal + gl.glEnable(GL.GL_RESCALE_NORMAL); + + gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE); + gl.glDepthFunc(GL.GL_LEQUAL); + gl.glEnable(GL.GL_COLOR_MATERIAL); + gl.glReadBuffer(GL.GL_FRONT); + } finally { + context.release(); + } + + return ctx; + } + + void createQueryContext(Canvas3D cv, long display, Drawable drawable, + long fbConfig, boolean offScreen, int width, int height, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + if (VERBOSE) System.err.println("JoglPipeline.createQueryContext()"); + + // FIXME: for now, ignoring the "offscreen" flag -- unclear how + // to create an offscreen buffer at this point -- very likely + // need Canvas3D.offScreenBufferInfo promoted to an Object -- + // this logic will need to be revisited to make sure we capture + // all of the functionality of the NativePipeline + + Frame f = new Frame(); + f.setUndecorated(true); + f.setLayout(new BorderLayout()); + GLCapabilities caps = new GLCapabilities(); + ContextQuerier querier = new ContextQuerier(cv, + glslLibraryAvailable, + cgLibraryAvailable); + // FIXME: should know what GraphicsDevice on which to create + // this Canvas / Frame, and this should probably be known from + // the incoming "display" parameter + QueryCanvas canvas = new QueryCanvas(caps, querier, null); + f.add(canvas, BorderLayout.CENTER); + f.setSize(MIN_FRAME_SIZE, MIN_FRAME_SIZE); + f.setVisible(true); + canvas.doQuery(); + // Attempt to wait for the frame to become visible, but don't block the EDT + if (!EventQueue.isDispatchThread()) { + synchronized(querier) { + if (!querier.done()) { + try { + querier.wait(WAIT_TIME); + } catch (InterruptedException e) { + } + } + } + } + + disposeOnEDT(f); + } + + // This is the native for creating an offscreen buffer + Drawable createOffScreenBuffer(Canvas3D cv, Context ctx, long display, long fbConfig, int width, int height) { + if (VERBOSE) System.err.println("JoglPipeline.createOffScreenBuffer()"); + + // Note 1: when this is called, the incoming Context argument is + // null because (obviously) no drawable or context has been + // created for the Canvas3D yet. + + // Note 2: we ignore the global j3d.usePbuffer flag; JOGL + // doesn't expose pixmap/bitmap surfaces in its public API. + + // First pick up the JoglGraphicsConfiguration and from there + // the GLCapabilities from the Canvas3D + JoglGraphicsConfiguration jcfg = (JoglGraphicsConfiguration) cv.graphicsConfiguration; + // Note that we ignore any chosen index from a prior call to getBestConfiguration(); + // those only enumerate the on-screen visuals, and we need to find one which is + // pbuffer capable + GLCapabilities caps = jcfg.getGLCapabilities(); + if (!GLDrawableFactory.getFactory().canCreateGLPbuffer()) { + // FIXME: do anything else here? Throw exception? + return null; + } + + GLPbuffer pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, null, + width, height, null); + return new JoglDrawable(pbuffer); + } + + void destroyOffScreenBuffer(Canvas3D cv, Context ctx, long display, long fbConfig, Drawable drawable) { + if (VERBOSE) System.err.println("JoglPipeline.destroyOffScreenBuffer()"); + + JoglDrawable jdraw = (JoglDrawable) drawable; + GLPbuffer pbuffer = (GLPbuffer) jdraw.getGLDrawable(); + pbuffer.destroy(); + } + + // This is the native for reading the image from the offscreen buffer + void readOffScreenBuffer(Canvas3D cv, Context ctx, int format, int dataType, Object data, int width, int height) { + if (VERBOSE) System.err.println("JoglPipeline.readOffScreenBuffer()"); + + GL gl = context(ctx).getGL(); + gl.glPixelStorei(GL.GL_PACK_ROW_LENGTH, width); + gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1); + + int type = 0; + if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_BUFFER)) { + + switch (format) { + // GL_BGR + case ImageComponentRetained.TYPE_BYTE_BGR: + type = GL.GL_BGR; + break; + case ImageComponentRetained.TYPE_BYTE_RGB: + type = GL.GL_RGB; + break; + // GL_ABGR_EXT + case ImageComponentRetained.TYPE_BYTE_ABGR: + if (gl.isExtensionAvailable("GL_EXT_abgr")) { // If false, should never come here! + type = GL.GL_ABGR_EXT; + } else { + assert false; + return; + } + break; + case ImageComponentRetained.TYPE_BYTE_RGBA: + type = GL.GL_RGBA; + break; + + /* This method only supports 3 and 4 components formats and BYTE types. */ + case ImageComponentRetained.TYPE_BYTE_LA: + case ImageComponentRetained.TYPE_BYTE_GRAY: + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_INT_BGR: + case ImageComponentRetained.TYPE_INT_RGB: + case ImageComponentRetained.TYPE_INT_ARGB: + default: + throw new AssertionError("illegal format " + format); + } + + gl.glReadPixels(0, 0, width, height, type, GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap((byte[]) data)); + + } else if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_ARRAY) || + (dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_BUFFER)) { + + int intType = GL.GL_UNSIGNED_INT_8_8_8_8; + boolean forceAlphaToOne = false; + + switch (format) { + /* GL_BGR */ + case ImageComponentRetained.TYPE_INT_BGR: /* Assume XBGR format */ + type = GL.GL_RGBA; + intType = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + forceAlphaToOne = true; + break; + case ImageComponentRetained.TYPE_INT_RGB: /* Assume XRGB format */ + forceAlphaToOne = true; + /* Fall through to next case */ + case ImageComponentRetained.TYPE_INT_ARGB: + type = GL.GL_BGRA; + intType = GL.GL_UNSIGNED_INT_8_8_8_8_REV; + break; + /* This method only supports 3 and 4 components formats and BYTE types. */ + case ImageComponentRetained.TYPE_BYTE_LA: + case ImageComponentRetained.TYPE_BYTE_GRAY: + case ImageComponentRetained.TYPE_USHORT_GRAY: + case ImageComponentRetained.TYPE_BYTE_BGR: + case ImageComponentRetained.TYPE_BYTE_RGB: + case ImageComponentRetained.TYPE_BYTE_RGBA: + case ImageComponentRetained.TYPE_BYTE_ABGR: + default: + throw new AssertionError("illegal format " + format); + } + + /* Force Alpha to 1.0 if needed */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 0.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 1.0f); + } + + gl.glReadPixels(0, 0, width, height, type, intType, IntBuffer.wrap((int[]) data)); + + /* Restore Alpha scale and bias */ + if(forceAlphaToOne) { + gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 1.0f); + gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 0.0f); + } + + } else { + throw new AssertionError("illegal image data type " + dataType); + + } + } + + // The native method for swapBuffers + int swapBuffers(Canvas3D cv, Context ctx, long dpy, Drawable drawable) { + if (VERBOSE) System.err.println("JoglPipeline.swapBuffers()"); + GLDrawable draw = drawable(drawable); + draw.swapBuffers(); + return 0; + } + + // notify D3D that Canvas is resize + int resizeD3DCanvas(Canvas3D cv, Context ctx) { + // Dummy method in JOGL pipeline + return 0; + } + + // notify D3D to toggle between FullScreen and window mode + int toggleFullScreenMode(Canvas3D cv, Context ctx) { + // Dummy method in JOGL pipeline + return 0; + } + + // native method for setting Material when no material is present + void updateMaterialColor(Context ctx, float r, float g, float b, float a) { + if (VERBOSE) System.err.println("JoglPipeline.updateMaterialColor()"); + + GL gl = context(ctx).getGL(); + gl.glColor4f(r, g, b, a); + gl.glDisable(GL.GL_LIGHTING); + } + + void destroyContext(long display, Drawable drawable, Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.destroyContext()"); + GLDrawable draw = drawable(drawable); + GLContext context = context(ctx); + if (GLContext.getCurrent() == context) { + context.release(); + } + context.destroy(); + // FIXME: assuming this is the right point at which to make this call + draw.setRealized(false); + } + + // This is the native method for doing accumulation. + void accum(Context ctx, float value) { + if (VERBOSE) System.err.println("JoglPipeline.accum()"); + + GL gl = context(ctx).getGL(); + gl.glReadBuffer(GL.GL_BACK); + gl.glAccum(GL.GL_ACCUM, value); + gl.glReadBuffer(GL.GL_FRONT); + } + + // This is the native method for doing accumulation return. + void accumReturn(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.accumReturn()"); + + GL gl = context(ctx).getGL(); + gl.glAccum(GL.GL_RETURN, 1.0f); + } + + // This is the native method for clearing the accumulation buffer. + void clearAccum(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.clearAccum()"); + + GL gl = context(ctx).getGL(); + gl.glClear(GL.GL_ACCUM_BUFFER_BIT); + } + + // This is the native method for getting the number of lights the underlying + // native library can support. + int getNumCtxLights(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.getNumCtxLights()"); + + GL gl = context(ctx).getGL(); + int[] res = new int[1]; + gl.glGetIntegerv(GL.GL_MAX_LIGHTS, res, 0); + return res[0]; + } + + // Native method for decal 1st child setup + boolean decal1stChildSetup(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.decal1stChildSetup()"); + + GL gl = context(ctx).getGL(); + gl.glEnable(GL.GL_STENCIL_TEST); + gl.glClearStencil(0x0); + gl.glClear(GL.GL_STENCIL_BUFFER_BIT); + gl.glStencilFunc(GL.GL_ALWAYS, 0x1, 0x1); + gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_REPLACE); + if (gl.glIsEnabled(GL.GL_DEPTH_TEST)) + return true; + else + return false; + } + + // Native method for decal nth child setup + void decalNthChildSetup(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.decalNthChildSetup()"); + + GL gl = context(ctx).getGL(); + gl.glDisable(GL.GL_DEPTH_TEST); + gl.glStencilFunc(GL.GL_EQUAL, 0x1, 0x1); + gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); + } + + // Native method for decal reset + void decalReset(Context ctx, boolean depthBufferEnable) { + if (VERBOSE) System.err.println("JoglPipeline.decalReset()"); + + GL gl = context(ctx).getGL(); + gl.glDisable(GL.GL_STENCIL_TEST); + if (depthBufferEnable) + gl.glEnable(GL.GL_DEPTH_TEST); + } + + // Native method for eye lighting + void ctxUpdateEyeLightingEnable(Context ctx, boolean localEyeLightingEnable) { + if (VERBOSE) System.err.println("JoglPipeline.ctxUpdateEyeLightingEnable()"); + + GL gl = context(ctx).getGL(); + + if (localEyeLightingEnable) { + gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE); + } else { + gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_FALSE); + } + } + + // The following three methods are used in multi-pass case + + // native method for setting blend color + void setBlendColor(Context ctx, float red, float green, + float blue, float alpha) { + if (VERBOSE) System.err.println("JoglPipeline.setBlendColor()"); + + GL gl = context(ctx).getGL(); + if (gl.isExtensionAvailable("GL_ARB_imaging")) { + gl.glBlendColor(red, green, blue, alpha); + } + } + + // native method for setting blend func + void setBlendFunc(Context ctx, int srcBlendFunction, int dstBlendFunction) { + if (VERBOSE) System.err.println("JoglPipeline.setBlendFunc()"); + + GL gl = context(ctx).getGL(); + gl.glEnable(GL.GL_BLEND); + gl.glBlendFunc(blendFunctionTable[srcBlendFunction], + blendFunctionTable[dstBlendFunction]); + } + + // native method for setting fog enable flag + void setFogEnableFlag(Context ctx, boolean enable) { + if (VERBOSE) System.err.println("JoglPipeline.setFogEnableFlag()"); + + GL gl = context(ctx).getGL(); + + if (enable) + gl.glEnable(GL.GL_FOG); + else + gl.glDisable(GL.GL_FOG); + } + + // Setup the full scene antialising in D3D and ogl when GL_ARB_multisamle supported + void setFullSceneAntialiasing(Context absCtx, boolean enable) { + if (VERBOSE) System.err.println("JoglPipeline.setFullSceneAntialiasing()"); + + JoglContext ctx = (JoglContext) absCtx; + GL gl = context(ctx).getGL(); + if (ctx.getHasMultisample() && !VirtualUniverse.mc.implicitAntialiasing) { + if (enable) { + gl.glEnable(GL.GL_MULTISAMPLE); + } else { + gl.glDisable(GL.GL_MULTISAMPLE); + } + } + } + + void setGlobalAlpha(Context ctx, float alpha) { + if (VERBOSE) System.err.println("JoglPipeline.setGlobalAlpha()"); + + GL gl = context(ctx).getGL(); + if (gl.isExtensionAvailable("GL_SUN_global_alpha")) { + gl.glEnable(GL.GL_GLOBAL_ALPHA_SUN); + gl.glGlobalAlphaFactorfSUN(alpha); + } + } + + // Native method to update separate specular color control + void updateSeparateSpecularColorEnable(Context ctx, boolean enable) { + if (VERBOSE) System.err.println("JoglPipeline.updateSeparateSpecularColorEnable()"); + + GL gl = context(ctx).getGL(); + + if (enable) { + gl.glLightModeli(GL.GL_LIGHT_MODEL_COLOR_CONTROL, GL.GL_SEPARATE_SPECULAR_COLOR); + } else { + gl.glLightModeli(GL.GL_LIGHT_MODEL_COLOR_CONTROL, GL.GL_SINGLE_COLOR); + } + } + + // Initialization for D3D when scene begins and ends + void beginScene(Context ctx) { + } + void endScene(Context ctx) { + } + + // True under Solaris, + // False under windows when display mode <= 8 bit + boolean validGraphicsMode() { + if (VERBOSE) System.err.println("JoglPipeline.validGraphicsMode()"); + + // FIXME: believe this should do exactly what the native code + // used to, but not 100% sure (also in theory should only run + // this code on the Windows platform? What about Mac OS X?) + DisplayMode currentMode = + GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode(); + // Note: on X11 platforms, a bit depth < 0 simply indicates that + // multiple visuals are supported on the current display mode + + if (VERBOSE) System.err.println(" Returning " + (currentMode.getBitDepth() < 0 || + currentMode.getBitDepth() > 8)); + + return (currentMode.getBitDepth() < 0 || + currentMode.getBitDepth() > 8); + } + + // native method for setting light enables + void setLightEnables(Context ctx, long enableMask, int maxLights) { + if (VERBOSE) System.err.println("JoglPipeline.setLightEnables()"); + + GL gl = context(ctx).getGL(); + + for (int i = 0; i < maxLights; i++) { + if ((enableMask & (1 << i)) != 0) { + gl.glEnable(GL.GL_LIGHT0 + i); + } else { + gl.glDisable(GL.GL_LIGHT0 + i); + } + } + } + + // native method for setting scene ambient + void setSceneAmbient(Context ctx, float red, float green, float blue) { + if (VERBOSE) System.err.println("JoglPipeline.setSceneAmbient()"); + + GL gl = context(ctx).getGL(); + + float[] color = new float[4]; + color[0] = red; + color[1] = green; + color[2] = blue; + color[3] = 1.0f; + gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, color, 0); + } + + // native method for disabling fog + void disableFog(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.disableFog()"); + + GL gl = context(ctx).getGL(); + gl.glDisable(GL.GL_FOG); + } + + // native method for disabling modelClip + void disableModelClip(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.disableModelClip()"); + + GL gl = context(ctx).getGL(); + + gl.glDisable(GL.GL_CLIP_PLANE0); + gl.glDisable(GL.GL_CLIP_PLANE1); + gl.glDisable(GL.GL_CLIP_PLANE2); + gl.glDisable(GL.GL_CLIP_PLANE3); + gl.glDisable(GL.GL_CLIP_PLANE4); + gl.glDisable(GL.GL_CLIP_PLANE5); + } + + // native method for setting default RenderingAttributes + void resetRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride) { + if (VERBOSE) System.err.println("JoglPipeline.resetRenderingAttributes()"); + + GL gl = context(ctx).getGL(); + + if (!depthBufferWriteEnableOverride) { + gl.glDepthMask(true); + } + if (!depthBufferEnableOverride) { + gl.glEnable(GL.GL_DEPTH_TEST); + } + gl.glAlphaFunc(GL.GL_ALWAYS, 0.0f); + gl.glDepthFunc(GL.GL_LEQUAL); + gl.glEnable(GL.GL_COLOR_MATERIAL); + gl.glDisable(GL.GL_COLOR_LOGIC_OP); + } + + // native method for setting default texture + void resetTextureNative(Context ctx, int texUnitIndex) { + if (VERBOSE) System.err.println("JoglPipeline.resetTextureNative()"); + + GL gl = context(ctx).getGL(); + if (texUnitIndex >= 0 && + gl.isExtensionAvailable("GL_VERSION_1_3")) { + gl.glActiveTexture(texUnitIndex + GL.GL_TEXTURE0); + gl.glClientActiveTexture(texUnitIndex + GL.GL_TEXTURE0); + } + + gl.glDisable(GL.GL_TEXTURE_1D); + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glDisable(GL.GL_TEXTURE_3D); + gl.glDisable(GL.GL_TEXTURE_CUBE_MAP); + } + + // native method for activating a particular texture unit + void activeTextureUnit(Context ctx, int texUnitIndex) { + if (VERBOSE) System.err.println("JoglPipeline.activeTextureUnit()"); + + GL gl = context(ctx).getGL(); + if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + gl.glActiveTexture(texUnitIndex + GL.GL_TEXTURE0); + gl.glClientActiveTexture(texUnitIndex + GL.GL_TEXTURE0); + } + } + + // native method for setting default TexCoordGeneration + void resetTexCoordGeneration(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.resetTexCoordGeneration()"); + + GL gl = context(ctx).getGL(); + gl.glDisable(GL.GL_TEXTURE_GEN_S); + gl.glDisable(GL.GL_TEXTURE_GEN_T); + gl.glDisable(GL.GL_TEXTURE_GEN_R); + gl.glDisable(GL.GL_TEXTURE_GEN_Q); + } + + // native method for setting default TextureAttributes + void resetTextureAttributes(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.resetTextureAttributes()"); + + GL gl = context(ctx).getGL(); + + float[] color = new float[4]; + + gl.glPushAttrib(GL.GL_TRANSFORM_BIT); + gl.glMatrixMode(GL.GL_TEXTURE); + gl.glLoadIdentity(); + gl.glPopAttrib(); + gl.glTexEnvfv(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_COLOR, color, 0); + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); + gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); + + if (gl.isExtensionAvailable("GL_NV_register_combiners")) { + gl.glDisable(GL.GL_REGISTER_COMBINERS_NV); + } + + if (gl.isExtensionAvailable("GL_SGI_texture_color_table")) { + gl.glDisable(GL.GL_TEXTURE_COLOR_TABLE_SGI); + } + } + + // native method for setting default PolygonAttributes + void resetPolygonAttributes(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.resetPolygonAttributes()"); + + GL gl = context(ctx).getGL(); + + gl.glCullFace(GL.GL_BACK); + gl.glEnable(GL.GL_CULL_FACE); + + gl.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_FALSE); + + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); + + gl.glPolygonOffset(0.0f, 0.0f); + gl.glDisable(GL.GL_POLYGON_OFFSET_POINT); + gl.glDisable(GL.GL_POLYGON_OFFSET_LINE); + gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); + } + + // native method for setting default LineAttributes + void resetLineAttributes(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.resetLineAttributes()"); + + GL gl = context(ctx).getGL(); + gl.glLineWidth(1.0f); + gl.glDisable(GL.GL_LINE_STIPPLE); + + // XXXX: Polygon Mode check, blend enable + gl.glDisable(GL.GL_LINE_SMOOTH); + } + + // native method for setting default PointAttributes + void resetPointAttributes(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.resetPointAttributes()"); + + GL gl = context(ctx).getGL(); + gl.glPointSize(1.0f); + + // XXXX: Polygon Mode check, blend enable + gl.glDisable(GL.GL_POINT_SMOOTH); + } + + // native method for setting default TransparencyAttributes + void resetTransparency(Context ctx, int geometryType, + int polygonMode, boolean lineAA, + boolean pointAA) { + if (VERBOSE) System.err.println("JoglPipeline.resetTransparency()"); + + GL gl = context(ctx).getGL(); + + if (((((geometryType & RenderMolecule.LINE) != 0) || + (polygonMode == PolygonAttributes.POLYGON_LINE)) + && lineAA) || + ((((geometryType & RenderMolecule.POINT) != 0) || + (polygonMode == PolygonAttributes.POLYGON_POINT)) + && pointAA)) { + gl.glEnable(GL.GL_BLEND); + gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); + } else { + gl.glDisable(GL.GL_BLEND); + } + gl.glDisable(GL.GL_POLYGON_STIPPLE); + } + + // native method for setting default ColoringAttributes + void resetColoringAttributes(Context ctx, + float r, float g, + float b, float a, + boolean enableLight) { + if (VERBOSE) System.err.println("JoglPipeline.resetColoringAttributes()"); + + GL gl = context(ctx).getGL(); + + if (!enableLight) { + gl.glColor4f(r, g, b, a); + } + gl.glShadeModel(GL.GL_SMOOTH); + } + + /** + * This native method makes sure that the rendering for this canvas + * gets done now. + */ + void syncRender(Context ctx, boolean wait) { + if (VERBOSE) System.err.println("JoglPipeline.syncRender()"); + + GL gl = context(ctx).getGL(); + + if (wait) + gl.glFinish(); + else + gl.glFlush(); + } + + // The native method that sets this ctx to be the current one + boolean useCtx(Context ctx, long display, Drawable drawable) { + if (VERBOSE) System.err.println("JoglPipeline.useCtx()"); + GLContext context = context(ctx); + int res = context.makeCurrent(); + return (res != GLContext.CONTEXT_NOT_CURRENT); + } + + // Optionally release the context. Returns true if the context was released. + boolean releaseCtx(Context ctx, long dpy) { + if (VERBOSE) System.err.println("JoglPipeline.releaseCtx()"); + GLContext context = context(ctx); + context.release(); + return true; + } + + void clear(Context ctx, float r, float g, float b) { + if (VERBOSE) System.err.println("JoglPipeline.clear()"); + + JoglContext jctx = (JoglContext) ctx; + GLContext context = context(ctx); + GL gl = context.getGL(); + gl.glClearColor(r, g, b, jctx.getAlphaClearValue()); + gl.glClear(GL.GL_COLOR_BUFFER_BIT); + + // Java 3D always clears the Z-buffer + gl.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT); + gl.glDepthMask(true); + gl.glClear(GL.GL_DEPTH_BUFFER_BIT); + gl.glPopAttrib(); + + } + + void textureFillBackground(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY) { + if (VERBOSE) System.err.println("JoglPipeline.textureFillBackground()"); + + GLContext context = context(ctx); + GL gl = context.getGL(); + + // Temporarily disable fragment and most 3D operations + gl.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_TEXTURE_BIT | GL.GL_POLYGON_BIT); + + disableAttribFor2D(gl); + gl.glDepthMask(false); + gl.glEnable(GL.GL_TEXTURE_2D); + + // reset the polygon mode + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); + + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); + + // load identity modelview and projection matrix + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glMatrixMode(GL.GL_TEXTURE); + gl.glPushMatrix(); + gl.glLoadIdentity(); + + gl.glBegin(GL.GL_QUADS); + gl.glTexCoord2f(texMinU, texMinV); gl.glVertex2f(mapMinX,mapMinY); + gl.glTexCoord2f(texMaxU, texMinV); gl.glVertex2f(mapMaxX,mapMinY); + gl.glTexCoord2f(texMaxU, texMaxV); gl.glVertex2f(mapMaxX,mapMaxY); + gl.glTexCoord2f(texMinU, texMaxV); gl.glVertex2f(mapMinX,mapMaxY); + gl.glEnd(); + + // Restore texture Matrix transform + gl.glPopMatrix(); + + gl.glMatrixMode(GL.GL_MODELVIEW); + // Restore attributes + gl.glPopAttrib(); + + } + + void textureFillRaster(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY, float mapZ, float alpha) { + if (VERBOSE) System.err.println("JoglPipeline.textureFillRaster()"); + + GLContext context = context(ctx); + GL gl = context.getGL(); + + // Temporarily disable fragment and most 3D operations + gl.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_TEXTURE_BIT | GL.GL_POLYGON_BIT | + GL.GL_CURRENT_BIT ); + + disableAttribForRaster(gl); + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE); + gl.glColor4f(1.0f, 1.0f, 1.0f, alpha); + + // reset the polygon mode + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); + + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); + + // load identity modelview and projection matrix + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glPushMatrix(); + gl.glLoadIdentity(); + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glPushMatrix(); + gl.glLoadIdentity(); + gl.glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0); + + gl.glBegin(GL.GL_QUADS); + gl.glTexCoord2f(texMinU, texMinV); gl.glVertex3f(mapMinX,mapMinY, mapZ); + gl.glTexCoord2f(texMaxU, texMinV); gl.glVertex3f(mapMaxX,mapMinY, mapZ); + gl.glTexCoord2f(texMaxU, texMaxV); gl.glVertex3f(mapMaxX,mapMaxY, mapZ); + gl.glTexCoord2f(texMinU, texMaxV); gl.glVertex3f(mapMinX,mapMaxY, mapZ); + gl.glEnd(); + + // Restore matrices + gl.glPopMatrix(); + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glPopMatrix(); + // Restore attributes + gl.glPopAttrib(); + + } + + void executeRasterDepth(Context ctx, float posX, float posY, float posZ, + int srcOffsetX, int srcOffsetY, int rasterWidth, int rasterHeight, + int depthWidth, int depthHeight, int depthFormat, Object depthData) { + if (VERBOSE) System.err.println("JoglPipeline.executeRasterDepth()"); + GLContext context = context(ctx); + GL gl = context.getGL(); + + + gl.glRasterPos3f(posX, posY, posZ); + + int[] drawBuf = new int[1]; + gl.glGetIntegerv(GL.GL_DRAW_BUFFER, drawBuf, 0); + /* disable draw buffer */ + gl.glDrawBuffer(GL.GL_NONE); + + /* + * raster position is upper left corner, default for Java3D + * ImageComponent currently has the data reverse in Y + */ + gl.glPixelZoom(1.0f, -1.0f); + gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, depthWidth); + if (srcOffsetX >= 0) { + gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, srcOffsetX); + if (srcOffsetX + rasterWidth > depthWidth) { + rasterWidth = depthWidth - srcOffsetX; + } + } else { + rasterWidth += srcOffsetX; + if (rasterWidth > depthWidth) { + rasterWidth = depthWidth; + } + } + if (srcOffsetY >= 0) { + gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, srcOffsetY); + if (srcOffsetY + rasterHeight > rasterHeight) { + rasterHeight = rasterHeight - srcOffsetY; + } + } else { + rasterHeight += srcOffsetY; + if (rasterHeight > rasterHeight) { + rasterHeight = rasterHeight; + } + } + + + if (depthFormat == DepthComponentRetained.DEPTH_COMPONENT_TYPE_INT) { + gl.glDrawPixels(rasterWidth, rasterHeight, GL.GL_DEPTH_COMPONENT, + GL.GL_UNSIGNED_INT, IntBuffer.wrap((int[]) depthData)); + } else { /* DepthComponentRetained.DEPTH_COMPONENT_TYPE_FLOAT */ + gl.glDrawPixels(rasterWidth, rasterHeight, GL.GL_DEPTH_COMPONENT, + GL.GL_FLOAT, FloatBuffer.wrap((float[]) depthData)); + } + + /* re-enable draw buffer */ + gl.glDrawBuffer(drawBuf[0]); + + gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, 0); + + } + + // The native method for setting the ModelView matrix. + void setModelViewMatrix(Context ctx, double[] viewMatrix, double[] modelMatrix) { + if (VERBOSE) System.err.println("JoglPipeline.setModelViewMatrix()"); + GLContext context = context(ctx); + GL gl = context.getGL(); + + gl.glMatrixMode(GL.GL_MODELVIEW); + + if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + gl.glLoadTransposeMatrixd(viewMatrix, 0); + gl.glMultTransposeMatrixd(modelMatrix, 0); + } else { + double[] v = new double[16]; + double[] m = new double[16]; + copyTranspose(viewMatrix, v); + copyTranspose(modelMatrix, m); + gl.glLoadMatrixd(v, 0); + gl.glMultMatrixd(m, 0); + } + } + + // The native method for setting the Projection matrix. + void setProjectionMatrix(Context ctx, double[] projMatrix) { + if (VERBOSE) System.err.println("JoglPipeline.setProjectionMatrix()"); + GLContext context = context(ctx); + GL gl = context.getGL(); + + gl.glMatrixMode(GL.GL_PROJECTION); + + if (gl.isExtensionAvailable("GL_VERSION_1_3")) { + // Invert the Z value in clipping coordinates because OpenGL uses + // left-handed clipping coordinates, while Java3D defines right-handed + // coordinates everywhere. + projMatrix[8] *= -1.0; + projMatrix[9] *= -1.0; + projMatrix[10] *= -1.0; + projMatrix[11] *= -1.0; + gl.glLoadTransposeMatrixd(projMatrix, 0); + projMatrix[8] *= -1.0; + projMatrix[9] *= -1.0; + projMatrix[10] *= -1.0; + projMatrix[11] *= -1.0; + } else { + double[] p = new double[16]; + copyTranspose(projMatrix, p); + // Invert the Z value in clipping coordinates because OpenGL uses + // left-handed clipping coordinates, while Java3D defines right-handed + // coordinates everywhere. + p[2] *= -1.0; + p[6] *= -1.0; + p[10] *= -1.0; + p[14] *= -1.0; + gl.glLoadMatrixd(p, 0); + } + } + + // The native method for setting the Viewport. + void setViewport(Context ctx, int x, int y, int width, int height) { + if (VERBOSE) System.err.println("JoglPipeline.setViewport()"); + GL gl = context(ctx).getGL(); + gl.glViewport(x, y, width, height); + } + + // used for display Lists + void newDisplayList(Context ctx, int displayListId) { + if (VERBOSE) System.err.println("JoglPipeline.newDisplayList()"); + if (displayListId <= 0) { + System.err.println("JAVA 3D ERROR : glNewList(" + displayListId + ") -- IGNORED"); + } + + GL gl = context(ctx).getGL(); + gl.glNewList(displayListId, GL.GL_COMPILE); + } + + void endDisplayList(Context ctx) { + if (VERBOSE) System.err.println("JoglPipeline.endDisplayList()"); + GL gl = context(ctx).getGL(); + gl.glEndList(); + } + + int numInvalidLists = 0; + void callDisplayList(Context ctx, int id, boolean isNonUniformScale) { + if (VERBOSE) System.err.println("JoglPipeline.callDisplayList()"); + if (id <= 0) { + if (numInvalidLists < 3) { + ++numInvalidLists; + System.err.println("JAVA 3D ERROR : glCallList(" + id + ") -- IGNORED"); + } else if (numInvalidLists == 3) { + ++numInvalidLists; + System.err.println("JAVA 3D : further glCallList error messages discarded"); + } + return; + } + + GL gl = context(ctx).getGL(); + // Set normalization if non-uniform scale + if (isNonUniformScale) { + gl.glEnable(GL.GL_NORMALIZE); + } + + gl.glCallList(id); + + // Turn normalization back off + if (isNonUniformScale) { + gl.glDisable(GL.GL_NORMALIZE); + } + } + + void freeDisplayList(Context ctx, int id) { + if (VERBOSE) System.err.println("JoglPipeline.freeDisplayList()"); + if (id <= 0) { + System.err.println("JAVA 3D ERROR : glDeleteLists(" + id + ",1) -- IGNORED"); + } + + GL gl = context(ctx).getGL(); + gl.glDeleteLists(id, 1); + } + void freeTexture(Context ctx, int id) { + if (VERBOSE) System.err.println("JoglPipeline.freeTexture()"); + + GL gl = context(ctx).getGL(); + + if (id > 0) { + int[] tmp = new int[1]; + tmp[0] = id; + gl.glDeleteTextures(1, tmp, 0); + } else { + System.err.println("tried to delete tex with texid <= 0"); + } + } + + + void texturemapping(Context ctx, + int px, int py, + int minX, int minY, int maxX, int maxY, + int texWidth, int texHeight, + int rasWidth, + int format, int objectId, + byte[] imageYdown, + int winWidth, int winHeight) { + if (VERBOSE) System.err.println("JoglPipeline.texturemapping()"); + + GL gl = context(ctx).getGL(); + + int glType = GL.GL_RGBA; + + // Temporarily disable fragment and most 3D operations + gl.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_TEXTURE_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_POLYGON_BIT); + disableAttribFor2D(gl); + + // Reset the polygon mode + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); + + gl.glDepthMask(false); + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); + gl.glBindTexture(GL.GL_TEXTURE_2D, objectId); + // set up texture parameter + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + + gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); + gl.glEnable(GL.GL_BLEND); + gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); + + gl.glEnable(GL.GL_TEXTURE_2D); + + // loaded identity modelview and projection matrix + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + + gl.glOrtho(0.0, winWidth, 0.0, winHeight, 0.0, 0.0); + + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glLoadIdentity(); + + if (gl.isExtensionAvailable("GL_EXT_abgr")) { + glType = GL.GL_ABGR_EXT; + } else { + switch (format) { + case ImageComponentRetained.TYPE_BYTE_RGBA: + glType = GL.GL_RGBA; + break; + case ImageComponentRetained.TYPE_BYTE_RGB: + glType = GL.GL_RGB; + break; + } + } + gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, rasWidth); + gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, minX); + gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, minY); + gl.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, minX, minY, + maxX - minX, maxY - minY, + glType, GL.GL_UNSIGNED_BYTE, + ByteBuffer.wrap(imageYdown)); + gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, 0); + + float texMinU = (float) minX/ (float) texWidth; + float texMinV = (float) minY/ (float) texHeight; + float texMaxU = (float) maxX/ (float) texWidth; + float texMaxV = (float) maxY/ (float) texHeight; + float halfWidth = (float)winWidth/2.0f; + float halfHeight = (float)winHeight/2.0f; + + float mapMinX = (float) (((px + minX)- halfWidth)/halfWidth); + float mapMinY = (float) ((halfHeight - (py + maxY))/halfHeight); + float mapMaxX = (float) ((px + maxX - halfWidth)/halfWidth); + float mapMaxY = (float) ((halfHeight - (py + minY))/halfHeight); + + gl.glBegin(GL.GL_QUADS); + + gl.glTexCoord2f(texMinU, texMaxV); gl.glVertex2f(mapMinX,mapMinY); + gl.glTexCoord2f(texMaxU, texMaxV); gl.glVertex2f(mapMaxX,mapMinY); + gl.glTexCoord2f(texMaxU, texMinV); gl.glVertex2f(mapMaxX,mapMaxY); + gl.glTexCoord2f(texMinU, texMinV); gl.glVertex2f(mapMinX,mapMaxY); + gl.glEnd(); + + // Java 3D always clears the Z-buffer + gl.glDepthMask(true); + gl.glClear(GL.GL_DEPTH_BUFFER_BIT); + gl.glPopAttrib(); + } + + boolean initTexturemapping(Context ctx, int texWidth, + int texHeight, int objectId) { + if (VERBOSE) System.err.println("JoglPipeline.initTexturemapping()"); + + GL gl = context(ctx).getGL(); + + int glType = (gl.isExtensionAvailable("GL_EXT_abgr") ? GL.GL_ABGR_EXT : GL.GL_RGBA); + + gl.glBindTexture(GL.GL_TEXTURE_2D, objectId); + + gl.glTexImage2D(GL.GL_PROXY_TEXTURE_2D, 0, GL.GL_RGBA, texWidth, + texHeight, 0, glType, GL.GL_UNSIGNED_BYTE, null); + + int[] width = new int[1]; + gl.glGetTexLevelParameteriv(GL.GL_PROXY_TEXTURE_2D, 0, + GL.GL_TEXTURE_WIDTH, width, 0); + + if (width[0] <= 0) { + return false; + } + + // init texture size only without filling the pixels + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, texWidth, + texHeight, 0, glType, GL.GL_UNSIGNED_BYTE, null); + + return true; + } + + + // Set internal render mode to one of FIELD_ALL, FIELD_LEFT or + // FIELD_RIGHT. Note that it is up to the caller to ensure that + // stereo is available before setting the mode to FIELD_LEFT or + // FIELD_RIGHT. The boolean isTRUE for double buffered mode, FALSE + // foe single buffering. + void setRenderMode(Context ctx, int mode, boolean doubleBuffer) { + if (VERBOSE) System.err.println("JoglPipeline.setRenderMode()"); + + GL gl = context(ctx).getGL(); + int drawBuf = 0; + if (doubleBuffer) { + drawBuf = GL.GL_BACK; + switch (mode) { + case Canvas3D.FIELD_LEFT: + drawBuf = GL.GL_BACK_LEFT; + break; + case Canvas3D.FIELD_RIGHT: + drawBuf = GL.GL_BACK_RIGHT; + break; + case Canvas3D.FIELD_ALL: + drawBuf = GL.GL_BACK; + break; + } + } else { + drawBuf = GL.GL_FRONT; + switch (mode) { + case Canvas3D.FIELD_LEFT: + drawBuf = GL.GL_FRONT_LEFT; + break; + case Canvas3D.FIELD_RIGHT: + drawBuf = GL.GL_FRONT_RIGHT; + break; + case Canvas3D.FIELD_ALL: + drawBuf = GL.GL_FRONT; + break; + } + } + + gl.glDrawBuffer(drawBuf); + } + + // Set glDepthMask. + void setDepthBufferWriteEnable(Context ctx, boolean mode) { + if (VERBOSE) System.err.println("JoglPipeline.setDepthBufferWriteEnable()"); + + GL gl = context(ctx).getGL(); + if (mode) { + gl.glDepthMask(true); + } else { + gl.glDepthMask(false); + } + } + + //---------------------------------------------------------------------- + // Helper private functions for Canvas3D + // + + private boolean getPropertiesFromCurrentContext(JoglContext ctx) { + GL gl = GLU.getCurrentGL(); + // FIXME: this is a heavily abridged set of the stuff in Canvas3D.c; + // probably need to pull much more in + int[] tmp = new int[1]; + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_UNITS, tmp, 0); + ctx.setMaxTexCoordSets(tmp[0]); + if (VirtualUniverse.mc.transparentOffScreen) { + ctx.setAlphaClearValue(0.0f); + } else { + ctx.setAlphaClearValue(1.0f); + } + if (gl.isExtensionAvailable("GL_ARB_vertex_shader")) { + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_COORDS_ARB, tmp, 0); + ctx.setMaxTexCoordSets(tmp[0]); + } + return true; + } + + private int[] extractVersionInfo(String versionString) { + StringTokenizer tok = new StringTokenizer(versionString, ". "); + int major = Integer.valueOf(tok.nextToken()).intValue(); + int minor = Integer.valueOf(tok.nextToken()).intValue(); + + // See if there's vendor-specific information which might + // imply a more recent OpenGL version + tok = new StringTokenizer(versionString, " "); + if (tok.hasMoreTokens()) { + tok.nextToken(); + if (tok.hasMoreTokens()) { + Pattern p = Pattern.compile("\\D*(\\d+)\\.(\\d+)\\.?(\\d*).*"); + Matcher m = p.matcher(tok.nextToken()); + if (m.matches()) { + int altMajor = Integer.valueOf(m.group(1)).intValue(); + int altMinor = Integer.valueOf(m.group(2)).intValue(); + // Avoid possibly confusing situations by requiring + // major version to match + if (altMajor == major && + altMinor > minor) { + minor = altMinor; + } + } + } + } + return new int[] { major, minor }; + } + + private int getTextureColorTableSize(GL gl) { + if (!gl.isExtensionAvailable("GL_ARB_imaging")) { + return 0; + } + + gl.glColorTable(GL.GL_PROXY_TEXTURE_COLOR_TABLE_SGI, GL.GL_RGBA, 256, GL.GL_RGB, + GL.GL_INT, null); + int[] tmp = new int[1]; + gl.glGetColorTableParameteriv(GL.GL_PROXY_TEXTURE_COLOR_TABLE_SGI, + GL.GL_COLOR_TABLE_WIDTH, tmp, 0); + return tmp[0]; + } + + + private void checkTextureExtensions(Canvas3D cv, + JoglContext ctx, + GL gl, + boolean gl13) { + if (gl13) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_MULTI_TEXTURE; + cv.multiTexAccelerated = true; + int[] tmp = new int[1]; + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_UNITS, tmp, 0); + cv.maxTextureUnits = tmp[0]; + cv.maxTexCoordSets = cv.maxTextureUnits; + if (gl.isExtensionAvailable("GL_ARB_vertex_shader")) { + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_COORDS_ARB, tmp, 0); + cv.maxTexCoordSets = tmp[0]; + } + } + + if (gl.isExtensionAvailable("GL_SGI_texture_color_table") || + gl.isExtensionAvailable("GL_ARB_imaging")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_COLOR_TABLE; + + // get texture color table size + // need to check later + cv.textureColorTableSize = getTextureColorTableSize(gl); + if (cv.textureColorTableSize <= 0) { + cv.textureExtendedFeatures &= ~Canvas3D.TEXTURE_COLOR_TABLE; + } + if (cv.textureColorTableSize > 256) { + cv.textureColorTableSize = 256; + } + } + + if (gl.isExtensionAvailable("GL_ARB_texture_env_combine")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_COMBINE; + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_COMBINE_SUBTRACT; + } else if (gl.isExtensionAvailable("GL_EXT_texture_env_combine")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_COMBINE; + } + + if (gl.isExtensionAvailable("GL_NV_register_combiners")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_REGISTER_COMBINERS; + } + + if (gl.isExtensionAvailable("GL_ARB_texture_env_dot3") || + gl.isExtensionAvailable("GL_EXT_texture_env_dot3")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_COMBINE_DOT3; + } + + if (gl13) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_CUBE_MAP; + } + + if (gl.isExtensionAvailable("GL_SGIS_sharpen_texture")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_SHARPEN; + } + + if (gl.isExtensionAvailable("GL_SGIS_detail_texture")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_DETAIL; + } + + if (gl.isExtensionAvailable("GL_SGIS_texture_filter4")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_FILTER4; + } + + if (gl.isExtensionAvailable("GL_EXT_texture_filter_anisotropic")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_ANISOTROPIC_FILTER; + float[] tmp = new float[1]; + gl.glGetFloatv(GL. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, tmp, 0); + cv.anisotropicDegreeMax = tmp[0]; + } + + if (gl.isExtensionAvailable("GL_SGIX_texture_lod_bias")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_LOD_OFFSET; + } + + if (gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two")) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_NON_POWER_OF_TWO; + } + } + + + private void checkGLSLShaderExtensions(Canvas3D cv, + JoglContext ctx, + GL gl, + boolean glslLibraryAvailable) { + if (glslLibraryAvailable && + gl.isExtensionAvailable("GL_ARB_shader_objects") && + gl.isExtensionAvailable("GL_ARB_shading_language_100")) { + // Initialize shader vertex attribute function pointers + ctx.initGLSLVertexAttributeImpl(); + + // FIXME: this isn't complete and would need to set up the + // JoglContext for dispatch of various routines such as those + // related to vertex attributes + int[] tmp = new int[1]; + gl.glGetIntegerv(GL. GL_MAX_TEXTURE_IMAGE_UNITS_ARB, tmp, 0); + cv.maxTextureImageUnits = tmp[0]; + gl.glGetIntegerv(GL. GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, tmp, 0); + cv.maxVertexTextureImageUnits = tmp[0]; + gl.glGetIntegerv(GL. GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, tmp, 0); + cv.maxCombinedTextureImageUnits = tmp[0]; + int vertexAttrOffset = VirtualUniverse.mc.glslVertexAttrOffset; + ctx.setGLSLVertexAttrOffset(vertexAttrOffset); + gl.glGetIntegerv(GL. GL_MAX_VERTEX_ATTRIBS_ARB, tmp, 0); + cv.maxVertexAttrs = tmp[0]; + // decr count to allow for reserved vertex attrs + cv.maxVertexAttrs -= vertexAttrOffset; + if (cv.maxVertexAttrs < 0) { + cv.maxVertexAttrs = 0; + } + cv.shadingLanguageGLSL = true; + } + } + + private boolean createCgContext(JoglContext ctx) { + CGcontext cgContext = CgGL.cgCreateContext(); + + int err = CgGL.cgGetError(); + if (err != 0) { + String detail = CgGL.cgGetErrorString(err); + System.err.println("JAVA 3D ERROR : Fatal error in creating Cg context: \"" + + detail + "\""); + return false; + } + + if (cgContext == null) { + System.err.println("JAVA 3D ERROR : Invalid null Cg context"); + return false; + } + + ctx.setCgContext(cgContext); + + // Use GL_ARB_vertex_program extension if supported by video card + if (CgGL.cgGLIsProfileSupported(CgGL.CG_PROFILE_ARBVP1)) { + ctx.setCgVertexProfile(CgGL.CG_PROFILE_ARBVP1); + } else if (CgGL.cgGLIsProfileSupported(CgGL.CG_PROFILE_VP20)) { + ctx.setCgVertexProfile(CgGL.CG_PROFILE_VP20); + } else { + System.err.println("JAVA 3D ERROR : No CG vertex program profile is supported"); + ctx.setCgContext(null); + return false; + } + + // Use GL_ARB_fragment_program extension if supported by video card + if (CgGL.cgGLIsProfileSupported(CgGL.CG_PROFILE_ARBFP1)) { + ctx.setCgFragmentProfile(CgGL.CG_PROFILE_ARBFP1); + } else if (CgGL.cgGLIsProfileSupported(CgGL.CG_PROFILE_FP20)) { + ctx.setCgFragmentProfile(CgGL.CG_PROFILE_FP20); + } else { + System.err.println("JAVA 3D ERROR : No CG fragment program profile is supported"); + ctx.setCgContext(null); + return false; + } + + return true; + } + + private void checkCgShaderExtensions(Canvas3D cv, + JoglContext ctx, + GL gl, + boolean cgLibraryAvailable) { + if (cgLibraryAvailable) { + if (!createCgContext(ctx)) { + return; + } + cv.shadingLanguageCg = true; + // TODO: Query Cg texture sampler limits + cv.maxTextureImageUnits = cv.maxTextureUnits; + cv.maxVertexTextureImageUnits = 0; + cv.maxCombinedTextureImageUnits = cv.maxTextureUnits; + // TODO: Query max vertex attrs + cv.maxVertexAttrs = 7; + // Initialize shader vertex attribute function pointers + ctx.initCgVertexAttributeImpl(); + } + } + + private void setupCanvasProperties(Canvas3D cv, + JoglContext ctx, + GL gl, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + // Note: this includes relevant portions from both the + // NativePipeline's getPropertiesFromCurrentContext and setupCanvasProperties + + // Reset all fields + cv.multiTexAccelerated = false; + cv.maxTextureUnits = 0; + cv.maxTexCoordSets = 0; + cv.maxTextureImageUnits = 0; + cv.maxVertexTextureImageUnits = 0; + cv.maxCombinedTextureImageUnits = 0; + cv.maxVertexAttrs = 0; + cv.extensionsSupported = 0; + cv.textureExtendedFeatures = 0; + cv.textureColorTableSize = 0; + cv.anisotropicDegreeMax = 0; + cv.textureBoundaryWidthMax = 0; + cv.textureWidthMax = 0; + cv.textureHeightMax = 0; + cv.texture3DWidthMax = 0; + cv.texture3DHeightMax = 0; + cv.texture3DDepthMax = 0; + cv.shadingLanguageGLSL = false; + cv.shadingLanguageCg = false; + + // Now make queries and set up these fields + String glVersion = gl.glGetString(GL.GL_VERSION); + String glVendor = gl.glGetString(GL.GL_VENDOR); + String glRenderer = gl.glGetString(GL.GL_RENDERER); + cv.nativeGraphicsVersion = glVersion; + cv.nativeGraphicsVendor = glVendor; + cv.nativeGraphicsRenderer = glRenderer; + + // find out the version, major and minor version number + int[] versionNumbers = extractVersionInfo(glVersion); + int major = versionNumbers[0]; + int minor = versionNumbers[1]; + + /////////////////////////////////////////// + // setup the graphics context properties // + + // NOTE: Java 3D now requires OpenGL 1.3 for full functionality. + // For backwards compatibility with certain older graphics cards and + // drivers (e.g., the Linux DRI driver for older ATI cards), + // we will try to run on OpenGL 1.2 in an unsupported manner. However, + // we will not attempt to use OpenGL extensions for any features that + // are available in OpenGL 1.3, specifically multitexture, multisample, + // and cube map textures. + + if (major < 1 || (major == 1 && minor < 2)) { + throw new IllegalRenderingStateException( + "Java 3D ERROR : OpenGL 1.2 or better is required (GL_VERSION=" + + major + "." + minor + ")"); + } + + boolean gl20 = false; + boolean gl13 = false; + if (major > 1) { + // OpenGL 2.x -- set flags for 1.3 and 2.0 or greater + gl20 = true; + gl13 = true; + } else { + if (minor == 2) { + System.err.println("*********************************************************"); + System.err.println("*** JAVA 3D: WARNING OpenGL 1.2 is no longer supported."); + System.err.println("*** Will attempt to run with reduced functionality."); + System.err.println("*********************************************************"); + } else { + gl13 = true; + } + } + + if (gl20) { + assert gl13; + assert gl.isExtensionAvailable("GL_VERSION_2_0"); + } + if (gl13) { + assert gl.isExtensionAvailable("GL_VERSION_1_3"); + } + + // Set up properties for OpenGL 1.3 + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_3D; + + // Note that we don't query for GL_ARB_imaging here + + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_LOD_RANGE; + + // look for OpenGL 2.0 features + if (gl20) { + cv.textureExtendedFeatures |= Canvas3D.TEXTURE_NON_POWER_OF_TWO; + } + + // Setup GL_EXT_abgr + if (gl.isExtensionAvailable("GL_EXT_abgr")) { + cv.extensionsSupported |= Canvas3D.EXT_ABGR; + } + + // GL_BGR is always supported + cv.extensionsSupported |= Canvas3D.EXT_BGR; + + // Setup multisample + // FIXME: this is not correct for the Windows platform yet + if (gl13) { + cv.extensionsSupported |= Canvas3D.MULTISAMPLE; + } + + if ((cv.extensionsSupported & Canvas3D.MULTISAMPLE) != 0 && + !VirtualUniverse.mc.implicitAntialiasing) { + gl.glDisable(GL.GL_MULTISAMPLE); + } + + // Check texture extensions + checkTextureExtensions(cv, ctx, gl, gl13); + + // Check shader extensions + if (gl13) { + checkGLSLShaderExtensions(cv, ctx, gl, glslLibraryAvailable); + checkCgShaderExtensions(cv, ctx, gl, cgLibraryAvailable); + } else { + // Force shaders to be disabled, since no multitexture support + checkGLSLShaderExtensions(cv, ctx, gl, false); + checkCgShaderExtensions(cv, ctx, gl, false); + } + + // Setup GL_SUN_gloabl_alpha + if (gl.isExtensionAvailable("GL_SUN_gloabl_alpha")) { + cv.extensionsSupported |= Canvas3D.SUN_GLOBAL_ALPHA; + } + + cv.textureBoundaryWidthMax = 1; + { + int[] tmp = new int[1]; + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, tmp, 0); + cv.textureWidthMax = tmp[0]; + cv.textureHeightMax = tmp[0]; + + tmp[0] = -1; + gl.glGetIntegerv(GL.GL_MAX_3D_TEXTURE_SIZE, tmp, 0); + cv.texture3DWidthMax = tmp[0]; + cv.texture3DHeightMax = tmp[0]; + cv.texture3DDepthMax = tmp[0]; + } + } + + /* + * Function to disable most rendering attributes when doing a 2D + * clear, image copy, or image composite operation. Note that the + * caller must save/restore the attributes with + * pushAttrib(GL_ENABLE_BIT|...) and popAttrib() + */ + private void disableAttribFor2D(GL gl) { + gl.glDisable(GL.GL_ALPHA_TEST); + gl.glDisable(GL.GL_BLEND); + gl.glDisable(GL.GL_COLOR_LOGIC_OP); + gl.glDisable(GL.GL_COLOR_MATERIAL); + gl.glDisable(GL.GL_CULL_FACE); + gl.glDisable(GL.GL_DEPTH_TEST); + gl.glDisable(GL.GL_FOG); + gl.glDisable(GL.GL_LIGHTING); + gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); + gl.glDisable(GL.GL_POLYGON_STIPPLE); + gl.glDisable(GL.GL_STENCIL_TEST); + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glDisable(GL.GL_TEXTURE_GEN_Q); + gl.glDisable(GL.GL_TEXTURE_GEN_R); + gl.glDisable(GL.GL_TEXTURE_GEN_S); + gl.glDisable(GL.GL_TEXTURE_GEN_T); + + + for (int i = 0; i < 6; i++) { + gl.glDisable(GL.GL_CLIP_PLANE0 + i); + } + + gl.glDisable(GL.GL_TEXTURE_3D); + gl.glDisable(GL.GL_TEXTURE_CUBE_MAP); + + if (gl.isExtensionAvailable("GL_NV_register_combiners")) { + gl.glDisable(GL.GL_REGISTER_COMBINERS_NV); + } + + if (gl.isExtensionAvailable("GL_SGI_texture_color_table")) { + gl.glDisable(GL.GL_TEXTURE_COLOR_TABLE_SGI); + } + + if (gl.isExtensionAvailable("GL_SUN_global_alpha")) { + gl.glDisable(GL.GL_GLOBAL_ALPHA_SUN); + } + + } + + private void disableAttribForRaster(GL gl) { + + gl.glDisable(GL.GL_COLOR_MATERIAL); + gl.glDisable(GL.GL_CULL_FACE); + gl.glDisable(GL.GL_LIGHTING); + gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); + gl.glDisable(GL.GL_POLYGON_STIPPLE); + + // TODO: Disable if Raster.CLIP_POSITION is true +// for (int i = 0; i < 6; i++) { +// gl.glDisable(GL.GL_CLIP_PLANE0 + i); +// } + + if (gl.isExtensionAvailable("GL_SUN_global_alpha")) { + gl.glDisable(GL.GL_GLOBAL_ALPHA_SUN); + } + } + + private void copyTranspose(double[] src, double[] dst) { + dst[0] = src[0]; + dst[1] = src[4]; + dst[2] = src[8]; + dst[3] = src[12]; + dst[4] = src[1]; + dst[5] = src[5]; + dst[6] = src[9]; + dst[7] = src[13]; + dst[8] = src[2]; + dst[9] = src[6]; + dst[10] = src[10]; + dst[11] = src[14]; + dst[12] = src[3]; + dst[13] = src[7]; + dst[14] = src[11]; + dst[15] = src[15]; + } + + // --------------------------------------------------------------------- + + // + // Canvas3D / GraphicsConfigTemplate3D methods - logic dealing with + // native graphics configuration or drawing surface + // + + // Return a graphics config based on the one passed in. Note that we can + // assert that the input config is non-null and was created from a + // GraphicsConfigTemplate3D. + // This method must return a valid GraphicsConfig, or else it must throw + // an exception if one cannot be returned. + GraphicsConfiguration getGraphicsConfig(GraphicsConfiguration gconfig) { + if (VERBOSE) System.err.println("JoglPipeline.getGraphicsConfig()"); + JoglGraphicsConfiguration config = (JoglGraphicsConfiguration) gconfig; + GLCapabilitiesChooser indexChooser = null; + if (config.getChosenIndex() >= 0) { + indexChooser = new IndexCapabilitiesChooser(config.getChosenIndex()); + } + + AbstractGraphicsConfiguration absConfig = + GLDrawableFactory.getFactory().chooseGraphicsConfiguration(config.getGLCapabilities(), + indexChooser, + new AWTGraphicsDevice(config.getDevice())); + if (absConfig == null) { + return null; + } + return ((AWTGraphicsConfiguration) absConfig).getGraphicsConfiguration(); + + /* + + System.err.println("JoglPipeline.getGraphicsConfig()"); + // Just return the input graphics config for now. eventually, we will + // use the input graphics config to get the GraphicsConfigTemplate3D + // parameters, which we will use to create a new graphics config with JOGL. + return gconfig; + */ + } + + // Get the native FBconfig pointer + long getFbConfig(GraphicsConfigInfo gcInfo) { + if (VERBOSE) System.err.println("JoglPipeline.getFbConfig()"); + return 0L; // Dummy method in JOGL + } + + + private static final int DISABLE_STEREO = 1; + private static final int DISABLE_AA = 2; + private static final int DISABLE_DOUBLE_BUFFER = 3; + + // Get best graphics config from pipeline + GraphicsConfiguration getBestConfiguration(GraphicsConfigTemplate3D gct, + GraphicsConfiguration[] gc) { + if (VERBOSE) System.err.println("JoglPipeline.getBestConfiguration()"); + /* + System.err.println("gct.getDoubleBuffer(): " + gct.getDoubleBuffer()); + System.err.println("gct.getStereo(): " + gct.getStereo()); + System.err.println("gct.getDepthBits(): " + gct.getDepthSize()); + System.err.println("gct.getRedSize(): " + gct.getRedSize()); + System.err.println("gct.getGreenSize(): " + gct.getGreenSize()); + System.err.println("gct.getBlueSize(): " + gct.getBlueSize()); + System.err.println("gct.getSceneAntialiasing(): " + gct.getSceneAntialiasing()); + */ + + // Create a GLCapabilities based on the GraphicsConfigTemplate3D + GLCapabilities caps = new GLCapabilities(); + caps.setDoubleBuffered(gct.getDoubleBuffer() <= GraphicsConfigTemplate.PREFERRED); + caps.setStereo (gct.getStereo() <= GraphicsConfigTemplate.PREFERRED); + caps.setDepthBits (gct.getDepthSize()); + caps.setStencilBits (gct.getStencilSize()); + caps.setRedBits (Math.max(5, gct.getRedSize())); + caps.setGreenBits (Math.max(5, gct.getGreenSize())); + caps.setBlueBits (Math.max(5, gct.getBlueSize())); + caps.setSampleBuffers(gct.getSceneAntialiasing() <= GraphicsConfigTemplate.PREFERRED); + // FIXME: should be smarter about choosing the number of samples + // (Java3D's native code has a loop trying 8, 6, 4, 3, and 2 samples) + caps.setNumSamples(4); + + java.util.List<Integer> capsToDisable = new ArrayList<Integer>(); + // Add PREFERRED capabilities in order we will try disabling them + if (gct.getStereo() == GraphicsConfigTemplate.PREFERRED) { + capsToDisable.add(new Integer(DISABLE_STEREO)); + } + if (gct.getSceneAntialiasing() == GraphicsConfigTemplate.PREFERRED) { + capsToDisable.add(new Integer(DISABLE_AA)); + } + if (gct.getDoubleBuffer() == GraphicsConfigTemplate.PREFERRED) { + capsToDisable.add(new Integer(DISABLE_DOUBLE_BUFFER)); + } + + // Pick the GraphicsDevice from a random configuration + GraphicsDevice dev = gc[0].getDevice(); + + // Create a Frame and dummy GLCanvas to perform eager pixel format selection + + // Note that we loop in similar fashion to the NativePipeline's + // native code in the situation where we need to disable certain + // capabilities which aren't required + boolean tryAgain = true; + CapabilitiesCapturer capturer = null; + while (tryAgain) { + Frame f = new Frame(dev.getDefaultConfiguration()); + f.setUndecorated(true); + f.setLayout(new BorderLayout()); + capturer = new CapabilitiesCapturer(); + try { + QueryCanvas canvas = new QueryCanvas(caps, capturer, dev); + f.add(canvas, BorderLayout.CENTER); + f.setSize(MIN_FRAME_SIZE, MIN_FRAME_SIZE); + f.setVisible(true); + canvas.doQuery(); + if (DEBUG_CONFIG) { + System.err.println("Waiting for CapabilitiesCapturer"); + } + // Try to wait for result without blocking EDT + if (!EventQueue.isDispatchThread()) { + synchronized(capturer) { + if (!capturer.done()) { + try { + capturer.wait(WAIT_TIME); + } catch (InterruptedException e) { + } + } + } + } + disposeOnEDT(f); + tryAgain = false; + } catch (GLException e) { + // Failure to select a pixel format; try switching off one + // of the only-preferred capabilities + if (capsToDisable.size() == 0) { + tryAgain = false; + } else { + int whichToDisable = capsToDisable.remove(0).intValue(); + switch (whichToDisable) { + case DISABLE_STEREO: + caps.setStereo(false); + break; + + case DISABLE_AA: + caps.setSampleBuffers(false); + break; + + case DISABLE_DOUBLE_BUFFER: + caps.setDoubleBuffered(false); + break; + + default: + throw new AssertionError("missing case statement"); + } + } + } + } + int chosenIndex = capturer.getChosenIndex(); + GLCapabilities chosenCaps = null; + if (chosenIndex < 0) { + if (DEBUG_CONFIG) { + System.err.println("CapabilitiesCapturer returned invalid index"); + } + // It's possible some platforms or implementations might not + // support the GLCapabilitiesChooser mechanism; feed in the + // same GLCapabilities later which we gave to the selector + chosenCaps = caps; + } else { + if (DEBUG_CONFIG) { + System.err.println("CapabilitiesCapturer returned index=" + chosenIndex); + } + chosenCaps = capturer.getCapabilities(); + } + + JoglGraphicsConfiguration config = new JoglGraphicsConfiguration(chosenCaps, chosenIndex, dev); + + // FIXME: because of the fact that JoglGraphicsConfiguration + // doesn't override hashCode() or equals(), we will basically be + // creating a new one each time getBestConfiguration() is + // called; in theory, we should probably map the same + // GLCapabilities on the same GraphicsDevice to the same + // JoglGraphicsConfiguration object + + // Cache the GraphicsTemplate3D + synchronized (Canvas3D.graphicsConfigTable) { + GraphicsConfigInfo gcInfo = new GraphicsConfigInfo(gct); + // We don't need this + // gcInfo.setPrivateData(privateData); + Canvas3D.graphicsConfigTable.put(config, gcInfo); + } + + return config; + + /* + + // TODO: implement this + + // TODO: construct a unique GraphicsConfiguration object that will be + // used the key in the hashmap so we can lookup the GraphicsTemplate3D + GraphicsConfiguration gc1 = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + + // Cache the GraphicsTemplate3D + synchronized (Canvas3D.graphicsConfigTable) { + if (Canvas3D.graphicsConfigTable.get(gc1) == null) { + GraphicsConfigInfo gcInfo = new GraphicsConfigInfo(gct); + // gcInfo.setPrivateData(privateData); + Canvas3D.graphicsConfigTable.put(gc1, gcInfo); + } + } + return gc1; + + */ + } + + // Determine whether specified graphics config is supported by pipeline + boolean isGraphicsConfigSupported(GraphicsConfigTemplate3D gct, + GraphicsConfiguration gc) { + if (VERBOSE) System.err.println("JoglPipeline.isGraphicsConfigSupported()"); + + // FIXME: it looks like this method is implemented incorrectly + // in the existing NativePipeline in both the Windows and X11 + // ports. According to the semantics of the javadoc, it looks + // like this method is supposed to figure out the OpenGL + // capabilities which would be requested by the passed + // GraphicsConfiguration object were it to be used, and see + // whether it is possible to create a context with them. + // Instead, on both platforms, the implementations basically set + // up a query based on the contents of the + // GraphicsConfigTemplate3D object, using the + // GraphicsConfiguration object only to figure out on which + // GraphicsDevice and screen we're making the request, and see + // whether it's possible to choose an OpenGL pixel format based + // on that information. This makes this method less useful and + // we can probably just safely return true here uniformly + // without breaking anything. + return true; + } + + // Methods to get actual capabilities from Canvas3D + boolean hasDoubleBuffer(Canvas3D cv) { + if (VERBOSE) System.err.println("JoglPipeline.hasDoubleBuffer()"); + if (VERBOSE) System.err.println(" Returning " + caps(cv).getDoubleBuffered()); + return caps(cv).getDoubleBuffered(); + } + + boolean hasStereo(Canvas3D cv) { + if (VERBOSE) System.err.println("JoglPipeline.hasStereo()"); + if (VERBOSE) System.err.println(" Returning " + caps(cv).getStereo()); + return caps(cv).getStereo(); + } + + int getStencilSize(Canvas3D cv) { + if (VERBOSE) System.err.println("JoglPipeline.getStencilSize()"); + if (VERBOSE) System.err.println(" Returning " + caps(cv).getStencilBits()); + return caps(cv).getStencilBits(); + } + + boolean hasSceneAntialiasingMultisample(Canvas3D cv) { + if (VERBOSE) System.err.println("JoglPipeline.hasSceneAntialiasingMultisample()"); + if (VERBOSE) System.err.println(" Returning " + caps(cv).getSampleBuffers()); + + return caps(cv).getSampleBuffers(); + } + + boolean hasSceneAntialiasingAccum(Canvas3D cv) { + if (VERBOSE) System.err.println("JoglPipeline.hasSceneAntialiasingAccum()"); + GLCapabilities caps = caps(cv); + if (VERBOSE) System.err.println(" Returning " + (caps.getAccumRedBits() > 0 && + caps.getAccumGreenBits() > 0 && + caps.getAccumBlueBits() > 0)); + return (caps.getAccumRedBits() > 0 && + caps.getAccumGreenBits() > 0 && + caps.getAccumBlueBits() > 0); + } + + // Methods to get native WS display and screen + long getDisplay() { + if (VERBOSE) System.err.println("JoglPipeline.getDisplay()"); + return 0L; // Dummy method in JOGL + } + + private boolean checkedForGetScreenMethod = false; + private Method getScreenMethod = null; + int getScreen(final GraphicsDevice graphicsDevice) { + if (VERBOSE) System.err.println("JoglPipeline.getScreen()"); + + if (!checkedForGetScreenMethod) { + // All of the Sun GraphicsDevice implementations have a method + // int getScreen(); + // which we want to call reflectively if it's available. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + getScreenMethod = graphicsDevice.getClass().getDeclaredMethod("getScreen", new Class[] {}); + getScreenMethod.setAccessible(true); + } catch (Exception e) { + } + checkedForGetScreenMethod = true; + return null; + } + }); + } + + if (getScreenMethod != null) { + try { + return ((Integer) getScreenMethod.invoke(graphicsDevice, (Object[]) null)).intValue(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + return 0; + } + + //---------------------------------------------------------------------- + // Helper classes and methods to support query context functionality + // and pixel format selection + + interface ExtendedCapabilitiesChooser extends GLCapabilitiesChooser { + public void init(GLContext context); + } + + // Canvas subclass to help with various query operations such as the + // "query context" mechanism and pixel format selection. + // Must defeat and simplify the single-threading behavior of JOGL's + // GLCanvas in order to be able to set up a temporary pixel format + // and OpenGL context. Apparently simply turning off the + // single-threaded mode isn't enough to do this. + class QueryCanvas extends Canvas { + private GLDrawable drawable; + private ExtendedCapabilitiesChooser chooser; + private boolean alreadyRan; + + public QueryCanvas(GLCapabilities capabilities, + ExtendedCapabilitiesChooser chooser, + GraphicsDevice device) { + // The platform-specific GLDrawableFactory will only provide a + // non-null GraphicsConfiguration on platforms where this is + // necessary (currently only X11, as Windows allows the pixel + // format of the window to be set later and Mac OS X seems to + // handle this very differently than all other platforms). On + // other platforms this method returns null; it is the case (at + // least in the Sun AWT implementation) that this will result in + // equivalent behavior to calling the no-arg super() constructor + // for Canvas. + super(unwrap((AWTGraphicsConfiguration) + GLDrawableFactory.getFactory().chooseGraphicsConfiguration(capabilities, + chooser, + new AWTGraphicsDevice(device)))); + drawable = GLDrawableFactory.getFactory().getGLDrawable(this, capabilities, chooser); + this.chooser = chooser; + } + + public void addNotify() { + super.addNotify(); + drawable.setRealized(true); + } + + // It seems that at least on Mac OS X we need to do the OpenGL + // context-related work outside of the addNotify call because the + // Canvas hasn't been resized to a non-zero size by that point + public void doQuery() { + if (alreadyRan) + return; + GLContext context = drawable.createContext(null); + int res = context.makeCurrent(); + if (res != GLContext.CONTEXT_NOT_CURRENT) { + try { + chooser.init(context); + } finally { + context.release(); + } + } + context.destroy(); + alreadyRan = true; + } + } + + private static GraphicsConfiguration unwrap(AWTGraphicsConfiguration config) { + if (config == null) { + return null; + } + return config.getGraphicsConfiguration(); + } + + // Used in conjunction with IndexCapabilitiesChooser in pixel format + // selection -- see getBestConfiguration + class CapabilitiesCapturer extends DefaultGLCapabilitiesChooser implements ExtendedCapabilitiesChooser { + private boolean done; + private GLCapabilities capabilities; + private int chosenIndex = -1; + + public boolean done() { + return done; + } + + public GLCapabilities getCapabilities() { + return capabilities; + } + + public int getChosenIndex() { + return chosenIndex; + } + + public int chooseCapabilities(GLCapabilities desired, + GLCapabilities[] available, + int windowSystemRecommendedChoice) { + int res = super.chooseCapabilities(desired, available, windowSystemRecommendedChoice); + capabilities = available[res]; + chosenIndex = res; + markDone(); + return res; + } + + public void init(GLContext context) { + // Avoid hanging things up for several seconds + kick(); + } + + private void markDone() { + synchronized (this) { + done = true; + notifyAll(); + } + } + + private void kick() { + synchronized (this) { + notifyAll(); + } + } + } + + // Used to support the query context mechanism -- needs to be more + // than just a GLCapabilitiesChooser + class ContextQuerier extends DefaultGLCapabilitiesChooser implements ExtendedCapabilitiesChooser { + private Canvas3D canvas; + private boolean glslLibraryAvailable; + private boolean cgLibraryAvailable; + private boolean done; + + public ContextQuerier(Canvas3D canvas, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + this.canvas = canvas; + this.glslLibraryAvailable = glslLibraryAvailable; + this.cgLibraryAvailable = cgLibraryAvailable; + } + + public boolean done() { + return done; + } + + public void init(GLContext context) { + // This is basically a temporary + JoglContext jctx = new JoglContext(context); + // Set up various properties + if (getPropertiesFromCurrentContext(jctx)) { + setupCanvasProperties(canvas, jctx, context.getGL(), + glslLibraryAvailable, + cgLibraryAvailable); + } + markDone(); + } + + private void markDone() { + synchronized (this) { + done = true; + notifyAll(); + } + } + } + + // Used in two phases of pixel format selection: transforming the + // JoglGraphicsConfiguration to a real AWT GraphicsConfiguration and + // during context creation to select exactly the same graphics + // configuration as was done during getBestConfiguration. + class IndexCapabilitiesChooser implements GLCapabilitiesChooser { + private int indexToChoose; + + IndexCapabilitiesChooser(int indexToChoose) { + this.indexToChoose = indexToChoose; + } + + public int chooseCapabilities(GLCapabilities desired, + GLCapabilities[] available, + int windowSystemRecommendedChoice) { + if (DEBUG_CONFIG) { + System.err.println("IndexCapabilitiesChooser returning index=" + indexToChoose); + } + return indexToChoose; + } + } + + private void disposeOnEDT(final Frame f) { + Runnable r = new Runnable() { + public void run() { + f.setVisible(false); + f.dispose(); + } + }; + if (!EventQueue.isDispatchThread()) { + EventQueue.invokeLater(r); + } else { + r.run(); + } + } + + + // --------------------------------------------------------------------- + + // + // DrawingSurfaceObject methods + // + + // Method to construct a new DrawingSurfaceObject + DrawingSurfaceObject createDrawingSurfaceObject(Canvas3D cv) { + if (VERBOSE) System.err.println("JoglPipeline.createDrawingSurfaceObject()"); + return new JoglDrawingSurfaceObject(cv); + } + + // Method to free the drawing surface object + void freeDrawingSurface(Canvas3D cv, DrawingSurfaceObject drawingSurfaceObject) { + if (VERBOSE) System.err.println("JoglPipeline.freeDrawingSurface()"); + // This method is a no-op + } + + // Method to free the native drawing surface object + void freeDrawingSurfaceNative(Object o) { + if (VERBOSE) System.err.println("JoglPipeline.freeDrawingSurfaceNative()"); + // This method is a no-op + } + + //---------------------------------------------------------------------- + // Context-related routines + // + + // Helper used everywhere + GLContext context(Context ctx) { + if (ctx == null) + return null; + return ((JoglContext) ctx).getGLContext(); + } + + // Helper used everywhere + GLDrawable drawable(Drawable drawable) { + if (drawable == null) + return null; + return ((JoglDrawable) drawable).getGLDrawable(); + } + + GLCapabilities caps(Canvas3D ctx) { + return ((JoglGraphicsConfiguration) ctx.graphicsConfiguration).getGLCapabilities(); + } + + //---------------------------------------------------------------------- + // General helper routines + // + + private static ThreadLocal nioVertexTemp = new ThreadLocal(); + private static ThreadLocal nioVertexDoubleTemp = new ThreadLocal(); + private static ThreadLocal nioColorTemp = new ThreadLocal(); + private static ThreadLocal nioColorByteTemp = new ThreadLocal(); + private static ThreadLocal nioNormalTemp = new ThreadLocal(); + private static ThreadLocal nioTexCoordSetTemp = new ThreadLocal(); + private static ThreadLocal nioVertexAttrSetTemp = new ThreadLocal(); + + private static FloatBuffer getVertexArrayBuffer(float[] vertexArray) { + return getVertexArrayBuffer(vertexArray, true); + } + + private static FloatBuffer getVertexArrayBuffer(float[] vertexArray, boolean copyData) { + return getNIOBuffer(vertexArray, nioVertexTemp, copyData); + } + + private static DoubleBuffer getVertexArrayBuffer(double[] vertexArray) { + return getVertexArrayBuffer(vertexArray, true); + } + + private static DoubleBuffer getVertexArrayBuffer(double[] vertexArray, boolean copyData) { + return getNIOBuffer(vertexArray, nioVertexDoubleTemp, true); + } + + private static FloatBuffer getColorArrayBuffer(float[] colorArray) { + return getColorArrayBuffer(colorArray, true); + } + + private static FloatBuffer getColorArrayBuffer(float[] colorArray, boolean copyData) { + return getNIOBuffer(colorArray, nioColorTemp, true); + } + + private static ByteBuffer getColorArrayBuffer(byte[] colorArray) { + return getColorArrayBuffer(colorArray, true); + } + + private static ByteBuffer getColorArrayBuffer(byte[] colorArray, boolean copyData) { + return getNIOBuffer(colorArray, nioColorByteTemp, true); + } + + private static FloatBuffer getNormalArrayBuffer(float[] normalArray) { + return getNormalArrayBuffer(normalArray, true); + } + + private static FloatBuffer getNormalArrayBuffer(float[] normalArray, boolean copyData) { + return getNIOBuffer(normalArray, nioNormalTemp, true); + } + + private static FloatBuffer[] getTexCoordSetBuffer(Object[] texCoordSet) { + return getNIOBuffer(texCoordSet, nioTexCoordSetTemp); + } + + private static FloatBuffer[] getVertexAttrSetBuffer(Object[] vertexAttrSet) { + return getNIOBuffer(vertexAttrSet, nioVertexAttrSetTemp); + } + + private static FloatBuffer getNIOBuffer(float[] array, ThreadLocal threadLocal, boolean copyData) { + if (array == null) { + return null; + } + FloatBuffer buf = (FloatBuffer) threadLocal.get(); + if (buf == null) { + buf = BufferUtil.newFloatBuffer(array.length); + threadLocal.set(buf); + } else { + buf.rewind(); + if (buf.remaining() < array.length) { + int newSize = Math.max(2 * buf.remaining(), array.length); + buf = BufferUtil.newFloatBuffer(newSize); + threadLocal.set(buf); + } + } + if (copyData) { + buf.put(array); + buf.rewind(); + } + return buf; + } + + private static DoubleBuffer getNIOBuffer(double[] array, ThreadLocal threadLocal, boolean copyData) { + if (array == null) { + return null; + } + DoubleBuffer buf = (DoubleBuffer) threadLocal.get(); + if (buf == null) { + buf = BufferUtil.newDoubleBuffer(array.length); + threadLocal.set(buf); + } else { + buf.rewind(); + if (buf.remaining() < array.length) { + int newSize = Math.max(2 * buf.remaining(), array.length); + buf = BufferUtil.newDoubleBuffer(newSize); + threadLocal.set(buf); + } + } + if (copyData) { + buf.put(array); + buf.rewind(); + } + return buf; + } + + private static ByteBuffer getNIOBuffer(byte[] array, ThreadLocal threadLocal, boolean copyData) { + if (array == null) { + return null; + } + ByteBuffer buf = (ByteBuffer) threadLocal.get(); + if (buf == null) { + buf = BufferUtil.newByteBuffer(array.length); + threadLocal.set(buf); + } else { + buf.rewind(); + if (buf.remaining() < array.length) { + int newSize = Math.max(2 * buf.remaining(), array.length); + buf = BufferUtil.newByteBuffer(newSize); + threadLocal.set(buf); + } + } + if (copyData) { + buf.put(array); + buf.rewind(); + } + return buf; + } + + private static FloatBuffer[] getNIOBuffer(Object[] array, ThreadLocal threadLocal) { + if (array == null) { + return null; + } + FloatBuffer[] bufs = (FloatBuffer[]) threadLocal.get(); + + // First resize array of FloatBuffers + if (bufs == null) { + bufs = new FloatBuffer[array.length]; + threadLocal.set(bufs); + } else if (bufs.length < array.length) { + FloatBuffer[] newBufs = new FloatBuffer[array.length]; + System.arraycopy(bufs, 0, newBufs, 0, bufs.length); + bufs = newBufs; + threadLocal.set(bufs); + } + + // Now go down array of arrays, converting each into a direct FloatBuffer + for (int i = 0; i < array.length; i++) { + float[] cur = (float[]) array[i]; + FloatBuffer buf = bufs[i]; + if (buf == null) { + buf = BufferUtil.newFloatBuffer(cur.length); + bufs[i] = buf; + } else { + buf.rewind(); + if (buf.remaining() < cur.length) { + int newSize = Math.max(2 * buf.remaining(), cur.length); + buf = BufferUtil.newFloatBuffer(newSize); + bufs[i] = buf; + } + } + buf.put(cur); + buf.rewind(); + } + + return bufs; + } +} diff --git a/src/classes/jogl/javax/media/j3d/JoglShaderObject.java b/src/classes/jogl/javax/media/j3d/JoglShaderObject.java new file mode 100755 index 0000000..d610857 --- /dev/null +++ b/src/classes/jogl/javax/media/j3d/JoglShaderObject.java @@ -0,0 +1,25 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +class JoglShaderObject implements ShaderProgramId, ShaderId, ShaderAttrLoc { + private int val; + + JoglShaderObject(int val) { + this.val = val; + } + + int getValue() { + return val; + } +} diff --git a/src/classes/linux/javax/media/j3d/J3dGraphicsConfig.java b/src/classes/linux/javax/media/j3d/J3dGraphicsConfig.java deleted file mode 100644 index 41673f2..0000000 --- a/src/classes/linux/javax/media/j3d/J3dGraphicsConfig.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -/* - * Portions of this code were derived from work done by the Blackdown - * group (www.blackdown.org), who did the initial Linux implementation - * of the Java 3D API. - */ - -package javax.media.j3d; - -import sun.awt.*; -import java.awt.*; - -class J3dGraphicsConfig { - - static native boolean isValidVisualID(long display, int vid); - - J3dGraphicsConfig(GraphicsDevice gd, int pixelFormat) { - // a dummy class which this constructor should - // never invoke under Linux - } - - static boolean isValidPixelFormat(GraphicsConfiguration gc) { - return isValidVisualID(NativeScreenInfo.getStaticDisplay(), - ((X11GraphicsConfig) gc).getVisual()); - } - - static boolean isValidConfig(GraphicsConfiguration gc) { - // Check to see if a valid FBConfig pointer has been cached. - Object fbConfigObject = Canvas3D.fbConfigTable.get(gc); - return ((fbConfigObject != null) && - (fbConfigObject instanceof GraphicsConfigInfo)); - } -} diff --git a/src/classes/linux/javax/media/j3d/NativeConfigTemplate3D.java b/src/classes/linux/javax/media/j3d/NativeConfigTemplate3D.java deleted file mode 100644 index 9f1059c..0000000 --- a/src/classes/linux/javax/media/j3d/NativeConfigTemplate3D.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -/* - * Portions of this code were derived from work done by the Blackdown - * group (www.blackdown.org), who did the initial Linux implementation - * of the Java 3D API. - */ - -package javax.media.j3d; - -import java.awt.GraphicsDevice; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsConfigTemplate; -import java.awt.Rectangle; -import sun.awt.X11GraphicsDevice; -import sun.awt.X11GraphicsConfig; - -class NativeConfigTemplate3D { - private final static boolean debug = false; - - NativeConfigTemplate3D() { - } - - /* - * This definition should match those in win32 NativeConfigTemplate3D.java - */ - final static int RED_SIZE = 0; - final static int GREEN_SIZE = 1; - final static int BLUE_SIZE = 2; - final static int ALPHA_SIZE = 3; - final static int ACCUM_BUFFER = 4; - final static int DEPTH_SIZE = 5; - final static int DOUBLEBUFFER = 6; - final static int STEREO = 7; - final static int ANTIALIASING = 8; - final static int STENCIL_SIZE = 9; - final static int NUM_ITEMS = 10; - - // Native method to get an OpenGL visual id and a pointer to the - // GLXFBConfig structure list itself. - native int chooseOglVisual(long display, int screen, - int[] attrList, long[] fbConfig); - - // Native method to free an GLXFBConfig struct. This is static since it - // may need to be called to clean up the Canvas3D fbConfigTable after the - // NativeConfigTemplate3D has been disposed of. - static native void freeFBConfig(long fbConfig); - - // Native methods to return whether a particular attribute is available - native boolean isStereoAvailable(long display, int screen, int vid); - native boolean isDoubleBufferAvailable(long display, int screen, int vid); - native boolean isSceneAntialiasingAccumAvailable(long display, int screen, int vid); - native boolean isSceneAntialiasingMultisampleAvailable(long display, int screen, int vid); - native int getStencilSize(long display, int screen, int vid); - - - /* - * Chooses the best FBConfig for Java 3D apps. - */ - GraphicsConfiguration - getBestConfiguration(GraphicsConfigTemplate3D template, - GraphicsConfiguration[] gc) { - - X11GraphicsDevice gd = - (X11GraphicsDevice)((X11GraphicsConfig)gc[0]).getDevice(); - - if (!NativeScreenInfo.isGLX13()) { - return null; - } - - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); - - if (debug) { - System.out.println(" NativeConfigTemplate3D: using device " + gd); - System.out.println(" display " + display + " screen " + screen); - System.out.println(" configuration count: " + gc.length); - for (int i = 0 ; i < gc.length ; i++) { - System.out.println(" visual id at index " + i + ": " + - ((X11GraphicsConfig)gc[i]).getVisual()); - } - } - - Rectangle bounds = gc[0].getBounds(); - if ((bounds.x != 0 || bounds.y != 0) && - (! VirtualUniverse.mc.xineramaDisabled)) { - // Xinerama is being used. The screen needs to be set to 0 since - // glxChooseFBConfig will not return a valid visual otherwise. - screen = 0; - if (debug) { - System.out.println(" Non-primary Xinerama screen:"); - System.out.println(" bounds = " + bounds); - System.out.println(" using screen 0 visual"); - } - } - - int[] attrList; // holds the list of attributes to be translated - // for glxChooseFBConfig call - - attrList = new int[NUM_ITEMS]; - - // assign template values to array - attrList[RED_SIZE] = template.getRedSize(); - attrList[GREEN_SIZE] = template.getGreenSize(); - attrList[BLUE_SIZE] = template.getBlueSize(); - - attrList[DEPTH_SIZE] = template.getDepthSize(); - attrList[DOUBLEBUFFER] = template.getDoubleBuffer(); - attrList[STEREO] = template.getStereo(); - attrList[ANTIALIASING] = template.getSceneAntialiasing(); - attrList[STENCIL_SIZE] = template.getStencilSize(); - // System.out.println("NativeConfigTemplate3D : getStencilSize " + - // attrList[STENCIL_SIZE]); - - long[] fbConfig = new long[1]; - int visID = chooseOglVisual(display, screen, attrList, fbConfig); - if (debug) { - System.out.println(" chooseOglVisual() returns " + visID); - System.out.println(" pointer to GLXFBConfig is " + fbConfig[0]); - System.out.println(); - } - - if (visID == 0 || fbConfig[0] == 0) { - return null; // no valid visual was found - } - - // search list of graphics configurations for config - // with matching visualId - GraphicsConfiguration gc1 = null; - for (int i = 0; i < gc.length; i++) - if (((X11GraphicsConfig)gc[i]).getVisual() == visID) { - gc1 = gc[i]; - break; - } - - // TODO: This may or may not be needed for Linux - // To support disabling Solaris OpenGL Xinerama mode, we need to cache - // the pointer to the actual GLXFBConfig that glXChooseFBConfig() - // returns, since this is not cached with X11GraphicsConfig and there - // are no public constructors to allow us to extend it. - synchronized (Canvas3D.fbConfigTable) { - if (Canvas3D.fbConfigTable.get(gc1) == null) { - GraphicsConfigInfo gcInfo = new GraphicsConfigInfo(); - gcInfo.setFBConfig(fbConfig[0]); - gcInfo.setRequestedStencilSize(attrList[STENCIL_SIZE]); - Canvas3D.fbConfigTable.put(gc1, gcInfo); - } else { - freeFBConfig(fbConfig[0]); - } - } - - return gc1; - } - - /* - * Determine if a given GraphicsConfiguration object can be used - * by Java 3D. - */ - boolean isGraphicsConfigSupported(GraphicsConfigTemplate3D template, - GraphicsConfiguration gc) { - - X11GraphicsDevice gd = - (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - - if (!NativeScreenInfo.isGLX13()) { - return false; - } - - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); - - int[] attrList; // holds the list of attributes to be tramslated - // for glxChooseVisual call - - attrList = new int[NUM_ITEMS]; - - // assign template values to array - attrList[RED_SIZE] = template.getRedSize(); - attrList[GREEN_SIZE] = template.getGreenSize(); - attrList[BLUE_SIZE] = template.getBlueSize(); - - attrList[DEPTH_SIZE] = template.getDepthSize(); - attrList[DOUBLEBUFFER] = template.getDoubleBuffer(); - attrList[STEREO] = template.getStereo(); - attrList[ANTIALIASING] = template.getSceneAntialiasing(); - attrList[STENCIL_SIZE] = template.getStencilSize(); - // System.out.println("NativeConfigTemplate3D : getStencilSize " + - // attrList[STENCIL_SIZE]); - - long[] fbConfig = new long[1]; - int visID = chooseOglVisual(display, screen, attrList, fbConfig); - - if (visID == 0 || fbConfig[0] == 0) - return false; // no valid visual was found - else - return true; - } - - - // Return whether stereo is available. - boolean hasStereo(Canvas3D c3d) { - GraphicsConfiguration gc = c3d.graphicsConfiguration; - - X11GraphicsDevice gd = - (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); - int vid = ((X11GraphicsConfig)gc).getVisual(); - - return isStereoAvailable(display, screen, vid); - } - - - // Return the stencil of this canvas. - int getStencilSize(Canvas3D c3d) { - GraphicsConfiguration gc = c3d.graphicsConfiguration; - - X11GraphicsDevice gd = - (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); - int vid = ((X11GraphicsConfig)gc).getVisual(); - - return getStencilSize(display, screen, vid); - } - - // Return whether a double buffer is available. - boolean hasDoubleBuffer(Canvas3D c3d) { - GraphicsConfiguration gc = c3d.graphicsConfiguration; - - X11GraphicsDevice gd = - (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); - int vid = ((X11GraphicsConfig)gc).getVisual(); - - return isDoubleBufferAvailable(display, screen, vid); - } - - // Return whether scene antialiasing is available. - boolean hasSceneAntialiasingAccum(Canvas3D c3d) { - GraphicsConfiguration gc = c3d.graphicsConfiguration; - - X11GraphicsDevice gd = - (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); - int vid = ((X11GraphicsConfig)gc).getVisual(); - - return isSceneAntialiasingAccumAvailable(display, screen, vid); - } - - - // Return whether scene antialiasing is available. - boolean hasSceneAntialiasingMultisample(Canvas3D c3d) { - GraphicsConfiguration gc = c3d.graphicsConfiguration; - - X11GraphicsDevice gd = - (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); - int vid = ((X11GraphicsConfig)gc).getVisual(); - - return isSceneAntialiasingMultisampleAvailable(display, screen, vid); - } - - // Ensure that the native libraries are loaded - static { - VirtualUniverse.loadLibraries(); - } -} diff --git a/src/classes/linux/javax/media/j3d/NativeScreenInfo.java b/src/classes/linux/javax/media/j3d/NativeScreenInfo.java deleted file mode 100644 index cbf44fe..0000000 --- a/src/classes/linux/javax/media/j3d/NativeScreenInfo.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -/* - * Portions of this code were derived from work done by the Blackdown - * group (www.blackdown.org), who did the initial Linux implementation - * of the Java 3D API. - */ - -package javax.media.j3d; - -import java.awt.GraphicsDevice; -import sun.awt.X11GraphicsDevice; - -class NativeScreenInfo { - private int screen; - private static long display = 0; - private static boolean glxChecked = false; - private static boolean isGLX13; - - private native static long openDisplay(); - private native static int getDefaultScreen(long display); - private native static boolean queryGLX13(long display); - - // Fix for issue 20. - // This method will return true if glx version is 1.3 or higher, - // else return false. - synchronized static boolean isGLX13() { - if (!glxChecked) { - // Open a new static display connection if one is not already opened. - getStaticDisplay(); - // Query for glx1.3 support. - isGLX13 = queryGLX13(display); - glxChecked = true; - } - - return isGLX13; - } - - - synchronized static long getStaticDisplay() { - if (display == 0) { - display = openDisplay(); - } - return display; - } - - NativeScreenInfo(GraphicsDevice graphicsDevice) { - // Open a new static display connection if one is not already opened - getStaticDisplay(); - - // Get the screen number - screen = ((X11GraphicsDevice)graphicsDevice).getScreen(); - } - - long getDisplay() { - return display; - } - - int getScreen() { - return screen; - } - - - // Ensure that the native libraries are loaded - static { - VirtualUniverse.loadLibraries(); - } -} diff --git a/src/classes/linux/javax/media/j3d/NativeWSInfo.java b/src/classes/linux/javax/media/j3d/NativeWSInfo.java deleted file mode 100644 index 894f2a8..0000000 --- a/src/classes/linux/javax/media/j3d/NativeWSInfo.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -/* - * Portions of this code were derived from work done by the Blackdown - * group (www.blackdown.org), who did the initial Linux implementation - * of the Java 3D API. - */ - -package javax.media.j3d; - -import java.awt.*; -import java.awt.event.*; -import sun.awt.*; -import java.lang.reflect.Method; - -class NativeWSInfo { - - //X11DrawingSurface xds; - Object xds; - - void getCanvasWSParameters(Canvas3D canvas) { - try { - Class x11DSclass = Class.forName("sun.awt.X11DrawingSurface"); - Method getDrawable = x11DSclass.getDeclaredMethod("getDrawable", null ); - Method getVisualID = x11DSclass.getDeclaredMethod("getVisualID", null ); - - //canvas.window = xds.getDrawable(); - //canvas.vid = xds.getVisualID(); - - canvas.window = ((Integer)getDrawable.invoke( xds, null )).intValue(); - canvas.vid = ((Integer)getVisualID.invoke( xds, null )).intValue(); - } catch( Exception e ) { - e.printStackTrace(); - } - } - - void getWSDrawingSurface( Object dsi) { - try { - //xds = (X11DrawingSurface)dsi.getSurface(); - Class drawingSurfaceInfoClass = Class.forName("sun.awt.DrawingSurfaceInfo"); - Method getSurface = drawingSurfaceInfoClass.getDeclaredMethod( "getSurface", null); - - //xds = dsi.getSurface(); - xds = getSurface.invoke( dsi, null ); - } catch( Exception e ) { - e.printStackTrace(); - } - } - - int getCanvasVid(GraphicsConfiguration gcfg) { - return (((X11GraphicsConfig)gcfg).getVisual()); - } -} - diff --git a/src/classes/share/javax/media/j3d/AlternateAppearanceRetained.java b/src/classes/share/javax/media/j3d/AlternateAppearanceRetained.java index 3e76132..d6f05b4 100644 --- a/src/classes/share/javax/media/j3d/AlternateAppearanceRetained.java +++ b/src/classes/share/javax/media/j3d/AlternateAppearanceRetained.java @@ -587,7 +587,7 @@ class AlternateAppearanceRetained extends LeafRetained { // Initialize the mirror object, this needs to be done, when // renderBin is not accessing any of the fields - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.universe = universe; createMessage.type = J3dMessage.ALTERNATEAPPEARANCE_CHANGED; @@ -721,7 +721,7 @@ class AlternateAppearanceRetained extends LeafRetained { if (scopes.size() > 0) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.universe = universe; createMessage.type = J3dMessage.ALTERNATEAPPEARANCE_CHANGED; @@ -759,7 +759,7 @@ class AlternateAppearanceRetained extends LeafRetained { } final void sendMessage(int attrMask, Object attr) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.universe = universe; createMessage.type = J3dMessage.ALTERNATEAPPEARANCE_CHANGED; diff --git a/src/classes/share/javax/media/j3d/AmbientLightRetained.java b/src/classes/share/javax/media/j3d/AmbientLightRetained.java index 8aaa65c..6f19e5b 100644 --- a/src/classes/share/javax/media/j3d/AmbientLightRetained.java +++ b/src/classes/share/javax/media/j3d/AmbientLightRetained.java @@ -34,6 +34,6 @@ class AmbientLightRetained extends LightRetained { VirtualUniverse.mc.processMessage(createMessage); } - void update(long ctx, int lightSlot, double scale) { + void update(Context ctx, int lightSlot, double scale) { } } diff --git a/src/classes/share/javax/media/j3d/Appearance.java b/src/classes/share/javax/media/j3d/Appearance.java index 5cfb429..ca60e41 100644 --- a/src/classes/share/javax/media/j3d/Appearance.java +++ b/src/classes/share/javax/media/j3d/Appearance.java @@ -535,12 +535,32 @@ public class Appearance extends NodeComponent { * @exception IllegalStateException if the specified texture * object is non-null and the texture unit state array in this * appearance object is already non-null. + * + * @exception IllegalSharingException if this Appearance is live and + * the specified texture refers to an ImageComponent2D that is being used + * by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this Appearance is + * being used by an immediate mode context and + * the specified texture refers to an ImageComponent2D that is being used + * by a Canvas3D as an off-screen buffer. */ public void setTexture(Texture texture) { if (isLiveOrCompiled()) if (!this.getCapability(ALLOW_TEXTURE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("Appearance2")); - ((AppearanceRetained)this.retained).setTexture(texture); + + // Do illegal sharing check + if(texture != null) { + ImageComponent[] images = ((TextureRetained)(texture.retained)).getImages(); + if(images != null) { + for(int i=0; i<images.length; i++) { + validateImageIllegalSharing(images[i]); + } + } + } + + ((AppearanceRetained)this.retained).setTexture(texture); } /** @@ -665,13 +685,35 @@ public class Appearance extends NodeComponent { * object, or texCoordGeneration object in this appearance object * is already non-null. * + * @exception IllegalSharingException if this Appearance is live and + * any of the specified textures refers to an ImageComponent2D that is + * being used by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this Appearance is + * being used by an immediate mode context and + * any of the specified textures refers to an ImageComponent2D that is + * being used by a Canvas3D as an off-screen buffer. + * * @since Java 3D 1.2 */ public void setTextureUnitState(TextureUnitState[] stateArray) { - if (isLiveOrCompiled()) - if (!this.getCapability(ALLOW_TEXTURE_UNIT_STATE_WRITE)) - throw new CapabilityNotSetException(J3dI18N.getString("Appearance20")); - + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_TEXTURE_UNIT_STATE_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("Appearance20")); + + // Do illegal sharing check + for(int j=0; j<stateArray.length; j++) { + TextureRetained texRetained = ((TextureUnitStateRetained)stateArray[j].retained).texture; + if(texRetained != null) { + ImageComponent[] images = texRetained.getImages(); + if(images != null) { + for(int i=0; i<images.length; i++) { + validateImageIllegalSharing(images[i]); + } + } + } + } + ((AppearanceRetained)this.retained).setTextureUnitState(stateArray); } @@ -693,6 +735,15 @@ public class Appearance extends NodeComponent { * @exception ArrayIndexOutOfBoundsException if <code>index >= * stateArray.length</code>. * + * @exception IllegalSharingException if this Appearance is live and + * the specified texture refers to an ImageComponent2D that is being used + * by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this Appearance is + * being used by an immediate mode context and + * the specified texture refers to an ImageComponent2D that is being used + * by a Canvas3D as an off-screen buffer. + * * @since Java 3D 1.2 */ public void setTextureUnitState(int index, TextureUnitState state) { @@ -700,6 +751,17 @@ public class Appearance extends NodeComponent { if (!this.getCapability(ALLOW_TEXTURE_UNIT_STATE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("Appearance20")); + // Do illegal sharing check + TextureRetained texRetained = ((TextureUnitStateRetained)state.retained).texture; + if(texRetained != null) { + ImageComponent[] images = texRetained.getImages(); + if(images != null) { + for(int i=0; i<images.length; i++) { + validateImageIllegalSharing(images[i]); + } + } + } + ((AppearanceRetained)this.retained).setTextureUnitState(index, state); } diff --git a/src/classes/share/javax/media/j3d/AppearanceRetained.java b/src/classes/share/javax/media/j3d/AppearanceRetained.java index 8f919da..904fb50 100644 --- a/src/classes/share/javax/media/j3d/AppearanceRetained.java +++ b/src/classes/share/javax/media/j3d/AppearanceRetained.java @@ -131,15 +131,13 @@ class AppearanceRetained extends NodeComponentRetained { Material getMaterial() { return (material == null ? null : (Material)material.source); } - + /** * Sets the texture object to the specified object. * @param texture object that specifies the desired texture * map and texture parameters */ void setTexture(Texture texture) { - - synchronized(liveStateLock) { if (source.isLive()) { @@ -528,7 +526,7 @@ class AppearanceRetained extends NodeComponentRetained { void setTextureUnitState(TextureUnitState[] stateArray) { int i; - + synchronized(liveStateLock) { if (source.isLive()) { @@ -604,8 +602,8 @@ class AppearanceRetained extends NodeComponentRetained { } void setTextureUnitState(int index, TextureUnitState state) { - - synchronized(liveStateLock) { + + synchronized(liveStateLock) { if (source.isLive()) { // remove the existing texture unit states from this appearance @@ -1038,7 +1036,8 @@ class AppearanceRetained extends NodeComponentRetained { return flag; } - /* + + // Issue 209 - enable this method (was previously commented out) // Simply pass along to the NodeComponents void compile(CompileState compState) { setCompiled(); @@ -1090,7 +1089,6 @@ class AppearanceRetained extends NodeComponentRetained { material.compile(compState); } } - */ /** * Returns the hashcode for this object. @@ -1244,7 +1242,7 @@ class AppearanceRetained extends NodeComponentRetained { ArrayList gaList = Shape3DRetained.getGeomAtomsList(mirror.users, univList); // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.APPEARANCE_CHANGED; createMessage.universe = null; @@ -1258,7 +1256,7 @@ class AppearanceRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.APPEARANCE_CHANGED; @@ -1294,7 +1292,7 @@ class AppearanceRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_GEOMETRY; createMessage.type = J3dMessage.RENDERINGATTRIBUTES_CHANGED; diff --git a/src/classes/share/javax/media/j3d/AttributeBin.java b/src/classes/share/javax/media/j3d/AttributeBin.java index dcfa24d..25b64b8 100644 --- a/src/classes/share/javax/media/j3d/AttributeBin.java +++ b/src/classes/share/javax/media/j3d/AttributeBin.java @@ -88,15 +88,17 @@ class AttributeBin extends Object implements ObjectUpdate { numEditingShaderBins = 0; renderingAttrs = renderingAttributes; - renderBin = rBin; + renderBin = rBin; - if (app != null) { - soleUser = ((app.changedFrequent & AppearanceRetained.RENDERING) != 0); - } - else { - soleUser = false; - } - //System.out.println("soleUser = "+soleUser+" renderingAttributes ="+renderingAttributes); + // Issue 249 - check for sole user only if property is set + soleUser = false; + if (VirtualUniverse.mc.allowSoleUser) { + if (app != null) { + soleUser = ((app.changedFrequent & AppearanceRetained.RENDERING) != 0); + } + } + + //System.out.println("soleUser = "+soleUser+" renderingAttributes ="+renderingAttributes); // Set the appearance only for soleUser case if (soleUser) this.app = app; @@ -272,7 +274,6 @@ class AttributeBin extends Object implements ObjectUpdate { } sb.clear(); - renderBin.shaderBinFreelist.add(sb); if (shaderBinList == null && addShaderBins.size() == 0 ) { // Note: Removal of this attributebin as a user of the rendering diff --git a/src/classes/share/javax/media/j3d/BHInternalNode.java b/src/classes/share/javax/media/j3d/BHInternalNode.java index 3a83a6e..0b59f33 100644 --- a/src/classes/share/javax/media/j3d/BHInternalNode.java +++ b/src/classes/share/javax/media/j3d/BHInternalNode.java @@ -188,9 +188,6 @@ class BHInternalNode extends BHNode { rChild = null; lChild = null; - - // add to free list ... - FreeListManager.freeObject(FreeListManager.BHINTERNAL, this); } } diff --git a/src/classes/share/javax/media/j3d/BHNode.java b/src/classes/share/javax/media/j3d/BHNode.java index 14456e7..f5b3985 100644 --- a/src/classes/share/javax/media/j3d/BHNode.java +++ b/src/classes/share/javax/media/j3d/BHNode.java @@ -153,9 +153,6 @@ abstract class BHNode { } } } - - // add to free list ... - VirtualUniverse.mc.addBHNodeToFreelists(this); } // delete all leaf nodes marked with DELETE_UPDATE and update the diff --git a/src/classes/share/javax/media/j3d/BHTree.java b/src/classes/share/javax/media/j3d/BHTree.java index 6cb997e..3d53667 100644 --- a/src/classes/share/javax/media/j3d/BHTree.java +++ b/src/classes/share/javax/media/j3d/BHTree.java @@ -632,7 +632,7 @@ class BHTree { } */ - root = VirtualUniverse.mc.getBHNode(BHNode.BH_TYPE_INTERNAL); + root = new BHInternalNode(); constructTree((BHInternalNode) root, bhArr, centerValues, centerValuesIndex); @@ -1045,7 +1045,7 @@ class BHTree { } if (rightSet.length != 1) { - parent.rChild = VirtualUniverse.mc.getBHNode(BHNode.BH_TYPE_INTERNAL); + parent.rChild = new BHInternalNode(); parent.rChild.setParent(parent); constructTree((BHInternalNode)(parent.rChild), rightSet, centerValues, centerValuesIndexR); @@ -1055,7 +1055,7 @@ class BHTree { } if (leftSet.length != 1) { - parent.lChild = VirtualUniverse.mc.getBHNode(BHNode.BH_TYPE_INTERNAL); + parent.lChild = new BHInternalNode(); parent.lChild.setParent(parent); constructTree((BHInternalNode)(parent.lChild), leftSet, centerValues, centerValuesIndexL); diff --git a/src/classes/share/javax/media/j3d/Background.java b/src/classes/share/javax/media/j3d/Background.java index 7a86d7e..335cbec 100644 --- a/src/classes/share/javax/media/j3d/Background.java +++ b/src/classes/share/javax/media/j3d/Background.java @@ -289,10 +289,18 @@ public class Background extends Leaf { * filled with the background color. * * @param image pixel array object used as the background image + * + * @exception IllegalArgumentException if the image class of the specified + * ImageComponent2D is ImageClass.NIO_IMAGE_BUFFER. */ public Background(ImageComponent2D image) { // set default read capabilities setDefaultReadCapabilities(readCapabilities); + + if((image != null) && + (image.getImageClass() == ImageComponent.ImageClass.NIO_IMAGE_BUFFER)) { + throw new IllegalArgumentException(J3dI18N.getString("Background14")); + } ((BackgroundRetained)this.retained).setImage(image); } @@ -379,19 +387,51 @@ public class Background extends Leaf { * than the window, * then that portion of the window not covered by the image is * filled with the background color. + * * @param image new pixel array object used as the background image + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * + * @exception IllegalSharingException if this Background is live and + * the specified image is being used by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this Background is + * being used by an immediate mode context and + * the specified image is being used by a Canvas3D as an off-screen buffer. + * + * @exception IllegalArgumentException if the image class of the specified + * ImageComponent2D is ImageClass.NIO_IMAGE_BUFFER. */ public void setImage(ImageComponent2D image) { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_IMAGE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("Background3")); + BackgroundRetained bgRetained = (BackgroundRetained)this.retained; + + if((image != null) && + (image.getImageClass() == ImageComponent.ImageClass.NIO_IMAGE_BUFFER)) { + throw new IllegalArgumentException(J3dI18N.getString("Background14")); + } + + // Do illegal sharing check + if(image != null) { + ImageComponent2DRetained imageRetained = (ImageComponent2DRetained) image.retained; + if(imageRetained.getUsedByOffScreen()) { + if(isLive()) { + throw new IllegalSharingException(J3dI18N.getString("Background12")); + } + if(bgRetained.getInImmCtx()) { + throw new IllegalSharingException(J3dI18N.getString("Background13")); + } + } + } + if (isLive()) - ((BackgroundRetained)this.retained).setImage(image); + bgRetained.setImage(image); else - ((BackgroundRetained)this.retained).initImage(image); + bgRetained.initImage(image); } /** diff --git a/src/classes/share/javax/media/j3d/BackgroundRetained.java b/src/classes/share/javax/media/j3d/BackgroundRetained.java index 92e01f3..d61a231 100644 --- a/src/classes/share/javax/media/j3d/BackgroundRetained.java +++ b/src/classes/share/javax/media/j3d/BackgroundRetained.java @@ -37,10 +37,11 @@ class BackgroundRetained extends LeafRetained { // color. Color3f color = new Color3f(0.0f, 0.0f, 0.0f); ImageComponent2DRetained image = null; - + Texture2DRetained texture = null; + // the image scale mode if image is used. int imageScaleMode = Background.SCALE_NONE; - + /** * The Boundary object defining the lights's application region. */ @@ -101,12 +102,7 @@ class BackgroundRetained extends LeafRetained { // Is true, if the background is viewScoped boolean isViewScoped = false; - - // for texture mapping the background - ImageComponent2DRetained texImage = null; - int xmax = 0; - int ymax = 0; - + BackgroundRetained () { this.nodeType = NodeRetained.BACKGROUND; localBounds = new BoundingBox(); @@ -114,7 +110,6 @@ class BackgroundRetained extends LeafRetained { ((BoundingBox)localBounds).setUpper(-1.0,-1.0,-1.0); } - /** * Initializes the background color to the specified color. * This color is used @@ -202,81 +197,46 @@ class BackgroundRetained extends LeafRetained { /** * Initializes the background image to the specified image. - * @param image new ImageCompoent3D object used as the background image + * @param image new ImageCompoent2D object used as the background image */ final void initImage(ImageComponent2D img) { - if (img != null) { - // scale to power of 2 for texture mapping - ImageComponent2DRetained rimage = (ImageComponent2DRetained) img.retained; - - if (!VirtualUniverse.mc.isBackgroundTexture) { - rimage.setRasterRef(); - } - else { -// rimage.setTextureRef(); - - xmax = rimage.width; - ymax = rimage.height; - int width = getClosestPowerOf2(xmax); - int height = getClosestPowerOf2(ymax); - float xScale = (float)width/(float)xmax; - float yScale = (float)height/(float)ymax; - - // scale if scales aren't 1.0 - if (!(xScale == 1.0f && yScale == 1.0f)) { - BufferedImage origImg = (BufferedImage) rimage.getImage(); - AffineTransform at = AffineTransform.getScaleInstance(xScale, - yScale); - AffineTransformOp atop = new AffineTransformOp(at, - AffineTransformOp.TYPE_BILINEAR); - BufferedImage scaledImg = atop.filter(origImg, null); - int format = rimage.getFormat(); - boolean yUp = rimage.isYUp(); - boolean byRef = rimage.isByReference(); - ImageComponent2D ic = new ImageComponent2D(format, - scaledImg, - byRef, yUp); - texImage = (ImageComponent2DRetained)ic.retained; - texImage.setTextureRef(); - //rimage.setTextureRef(); - //texImage.setRasterRef(); - } - else { - texImage = rimage; - texImage.setTextureRef(); - //rimage.setTextureRef(); - //texImage.setRasterRef(); - } - } - - this.image = rimage; - } else { - this.image = null; - this.texImage = null; - } - } + int texFormat; - private int getClosestPowerOf2(int value) { - - if (value < 1) - return value; - - int powerValue = 1; - for (;;) { - powerValue *= 2; - if (value < powerValue) { - // Found max bound of power, determine which is closest - int minBound = powerValue/2; - if ((powerValue - value) > - (value - minBound)) - return minBound; - else - return powerValue; - } - } - } + if (img == null) { + image = null; + texture = null; + return; + } + if (img.retained != image ) { + image = (ImageComponent2DRetained) img.retained; + image.setEnforceNonPowerOfTwoSupport(true); + switch(image.getNumberOfComponents()) { + case 1: + texFormat = Texture.INTENSITY; + break; + case 2: + texFormat = Texture.LUMINANCE_ALPHA; + break; + case 3: + texFormat = Texture.RGB; + break; + case 4: + texFormat = Texture.RGBA; + break; + default: + assert false; + return; + } + Texture2D tex2D = new Texture2D(Texture.BASE_LEVEL, texFormat, + img.getWidth(), img.getHeight()); + texture = (Texture2DRetained) tex2D.retained; + // Background is special case of Raster. + texture.setUseAsRaster(true); + texture.initImage(0,img); + } + } /** * Sets the background image to the specified image. @@ -284,19 +244,22 @@ class BackgroundRetained extends LeafRetained { */ final void setImage(ImageComponent2D img) { if (source.isLive()) { - if (this.image != null) { - this.image.clearLive(refCount); + if (texture != null) { + texture.clearLive(refCount); + texture.removeUser(this); } } initImage(img); - if (source.isLive()) { - if (img != null) { - ((ImageComponent2DRetained) - img.retained).setLive(inBackgroundGroup, refCount); - } - sendMessage(IMAGE_CHANGED, - (image != null ? image.clone() : null)); - } + if (source.isLive()) { + if (texture != null) { + texture.setLive(inBackgroundGroup, refCount); + texture.addUser(this); + } + + sendMessage(IMAGE_CHANGED, + (texture != null ? texture.mirror : null)); + + } } /** @@ -333,7 +296,7 @@ class BackgroundRetained extends LeafRetained { numMessages+=2; // INSERT_NODES, ORDERED_GROUP_INSERTED m = new J3dMessage[numMessages]; for (i=0; i<numMessages; i++) { - m[i] = VirtualUniverse.mc.getMessage(); + m[i] = new J3dMessage(); } i = 0; if (geometryBranch != null) { @@ -408,7 +371,7 @@ class BackgroundRetained extends LeafRetained { initApplicationBounds(region); // Don't send the message if there is a valid boundingleaf if (boundingLeaf == null) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads | J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.type = J3dMessage.BACKGROUND_CHANGED; @@ -456,7 +419,7 @@ class BackgroundRetained extends LeafRetained { } else { boundingLeaf = null; } - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads | J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.type = J3dMessage.BACKGROUND_CHANGED; @@ -539,7 +502,6 @@ class BackgroundRetained extends LeafRetained { } - /** * This setLive routine first calls the superclass's method, then * it adds itself to the list of lights @@ -637,8 +599,8 @@ class BackgroundRetained extends LeafRetained { s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER; - if (image != null) { - image.setLive(inBackgroundGroup, refCount); + if (texture != null) { + texture.setLive(inBackgroundGroup, refCount); } super.markAsLive(); @@ -680,17 +642,14 @@ class BackgroundRetained extends LeafRetained { fogs.clear(); } - if (image != null) { - image.clearLive(refCount); + if (texture != null) { + texture.clearLive(refCount); } s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER; } - - - // The update Object function. synchronized void updateImmediateMirrorObject(Object[] objs) { int component = ((Integer)objs[1]).intValue(); @@ -761,7 +720,7 @@ class BackgroundRetained extends LeafRetained { final void sendMessage(int attrMask, Object attr) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.universe = universe; createMessage.type = J3dMessage.BACKGROUND_CHANGED; diff --git a/src/classes/share/javax/media/j3d/BehaviorRetained.java b/src/classes/share/javax/media/j3d/BehaviorRetained.java index d292ba9..7b17f0e 100644 --- a/src/classes/share/javax/media/j3d/BehaviorRetained.java +++ b/src/classes/share/javax/media/j3d/BehaviorRetained.java @@ -346,11 +346,14 @@ class BehaviorRetained extends LeafRetained { ((Behavior)this.source).initialize(); } catch (RuntimeException e) { - inCallback = inCallbackSaved; - inInitCallback = inInitCallbackSaved; System.err.println("Exception occurred during Behavior initialization:"); e.printStackTrace(); } + catch (Error e) { + // Issue 264 - catch Error + System.err.println("Error occurred during Behavior initialization:"); + e.printStackTrace(); + } inCallback = inCallbackSaved; inInitCallback = inInitCallbackSaved; } @@ -482,7 +485,7 @@ class BehaviorRetained extends LeafRetained { void addWakeupCondition() {} final void sendMessage(int mtype, Object arg) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_BEHAVIOR; createMessage.type = mtype; createMessage.universe = universe; diff --git a/src/classes/share/javax/media/j3d/BehaviorScheduler.java b/src/classes/share/javax/media/j3d/BehaviorScheduler.java index fa9cf09..d9f31f1 100644 --- a/src/classes/share/javax/media/j3d/BehaviorScheduler.java +++ b/src/classes/share/javax/media/j3d/BehaviorScheduler.java @@ -178,6 +178,13 @@ class BehaviorScheduler extends J3dThread { System.err.println("Exception occurred during Behavior execution:"); e.printStackTrace(); } + catch (Error e) { + // Force behavior condition to be unset + // Fix for issue 264 + behavret.conditionSet = false; + System.err.println("Error occurred during Behavior execution:"); + e.printStackTrace(); + } univ.inBehavior = false; behavret.inCallback = false; } diff --git a/src/classes/share/javax/media/j3d/BehaviorStructure.java b/src/classes/share/javax/media/j3d/BehaviorStructure.java index 66a4780..a7db263 100644 --- a/src/classes/share/javax/media/j3d/BehaviorStructure.java +++ b/src/classes/share/javax/media/j3d/BehaviorStructure.java @@ -1530,7 +1530,7 @@ class BehaviorStructure extends J3dStructure { scheduleList.remove(behav); behav.active = false; if (behav.universe != universe) { - J3dMessage m = VirtualUniverse.mc.getMessage(); + J3dMessage m = new J3dMessage(); m.threads = J3dThread.UPDATE_BEHAVIOR; m.type = J3dMessage.BEHAVIOR_REEVALUATE; m.universe = behav.universe; diff --git a/src/classes/share/javax/media/j3d/Billboard.java b/src/classes/share/javax/media/j3d/Billboard.java index b76ad13..272e2da 100644 --- a/src/classes/share/javax/media/j3d/Billboard.java +++ b/src/classes/share/javax/media/j3d/Billboard.java @@ -312,9 +312,9 @@ public class Billboard extends Behavior { Canvas3D canvas = (Canvas3D)v.getCanvas3D(0); boolean status; - Transform3D xform = VirtualUniverse.mc.getTransform3D(null); - Transform3D bbXform = VirtualUniverse.mc.getTransform3D(null); - Transform3D prevTransform = VirtualUniverse.mc.getTransform3D(null); + Transform3D xform = new Transform3D(); + Transform3D bbXform = new Transform3D(); + Transform3D prevTransform = new Transform3D(); ((TransformGroupRetained) tg.retained).getTransform(prevTransform); @@ -400,7 +400,7 @@ public class Billboard extends Behavior { // Need to rotate Z axis to point to eye, and Y axis to be // parallel to view platform Y axis, rotating around rotation pt - Transform3D zRotate = VirtualUniverse.mc.getTransform3D(null); + Transform3D zRotate = new Transform3D(); // get the eye point canvas.getCenterEyeInImagePlate(viewPosition); @@ -534,15 +534,10 @@ public class Billboard extends Behavior { tg.setTransform(bbXform); } } - VirtualUniverse.mc.addToTransformFreeList(zRotate); } // Insert wakeup condition into queue wakeupOn(wakeupFrame); - - VirtualUniverse.mc.addToTransformFreeList(xform); - VirtualUniverse.mc.addToTransformFreeList(bbXform); - VirtualUniverse.mc.addToTransformFreeList(prevTransform); } private boolean projectToPlane(Vector3d projVec, Vector3d planeVec) { diff --git a/src/classes/share/javax/media/j3d/BoundingLeafRetained.java b/src/classes/share/javax/media/j3d/BoundingLeafRetained.java index 61555bd..584737c 100644 --- a/src/classes/share/javax/media/j3d/BoundingLeafRetained.java +++ b/src/classes/share/javax/media/j3d/BoundingLeafRetained.java @@ -78,7 +78,7 @@ class BoundingLeafRetained extends LeafRetained { */ void setRegion(Bounds region) { initRegion(region); - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = mirrorBoundingLeaf.targetThreads; createMessage.type = J3dMessage.BOUNDINGLEAF_CHANGED; createMessage.universe = universe; diff --git a/src/classes/share/javax/media/j3d/BoundingPolytope.java b/src/classes/share/javax/media/j3d/BoundingPolytope.java index c3f3408..30fa36f 100644 --- a/src/classes/share/javax/media/j3d/BoundingPolytope.java +++ b/src/classes/share/javax/media/j3d/BoundingPolytope.java @@ -816,7 +816,7 @@ public class BoundingPolytope extends Bounds { int i; double invMag; - Transform3D invTrans = VirtualUniverse.mc.getTransform3D(matrix); + Transform3D invTrans = new Transform3D(matrix); invTrans.invert(); invTrans.transpose(); @@ -828,8 +828,6 @@ public class BoundingPolytope extends Bounds { planes[i].w = planes[i].w * mag[i]; invTrans.transform( planes[i] ); } - - VirtualUniverse.mc.addToTransformFreeList(invTrans); for(i=0;i<planes.length;i++) { diff --git a/src/classes/share/javax/media/j3d/BranchGroupRetained.java b/src/classes/share/javax/media/j3d/BranchGroupRetained.java index ab68682..933800d 100644 --- a/src/classes/share/javax/media/j3d/BranchGroupRetained.java +++ b/src/classes/share/javax/media/j3d/BranchGroupRetained.java @@ -65,11 +65,13 @@ class BranchGroupRetained extends GroupRetained { GroupRetained oldParent = (GroupRetained)parent; do_detach(); universe.setLiveState.clear(); - if (isLive) - if (oldParent==null) + if (isLive) { + if (oldParent==null) { universe.notifyStructureChangeListeners(false,locale,(BranchGroup)this.source); - else + } else { universe.notifyStructureChangeListeners(false,oldParent.source, (BranchGroup)this.source); + } + } } universe.waitForMC(); } else { // Not live yet, just do it. diff --git a/src/classes/share/javax/media/j3d/Canvas3D.java b/src/classes/share/javax/media/j3d/Canvas3D.java index af9020b..1b85eed 100644 --- a/src/classes/share/javax/media/j3d/Canvas3D.java +++ b/src/classes/share/javax/media/j3d/Canvas3D.java @@ -14,12 +14,10 @@ package javax.media.j3d; import javax.vecmath.*; import java.awt.*; -import java.awt.event.*; import java.awt.image.BufferedImage; import java.util.*; - /** * The Canvas3D class provides a drawing canvas for 3D rendering. It * is used either for on-screen rendering or off-screen rendering. @@ -322,16 +320,23 @@ public class Canvas3D extends Canvas { // boolean offScreen = false; + // + // Issue 131: Flag that indicates whether this Canvas3D is a manually + // rendered Canvas3D (versus an automatically rendered Canvas3D). + // + // NOTE: manualRendering only applies to off-screen Canvas3Ds at this time. + // We have no plans to ever change this, but if we do, it might be necessary + // to determine which, if any, of the uses of "manualRendering" should be + // changed to "manualRendering&&offScreen" + // + boolean manualRendering = false; + // user specified offScreen Canvas location Point offScreenCanvasLoc; // user specified offScreen Canvas dimension Dimension offScreenCanvasSize; - // clipped offscreen canvas - Point offScreenCanvasClippedLoc; - Dimension offScreenCanvasClippedSize; - // // Flag that indicates whether off-screen rendering is in progress or not // @@ -348,9 +353,6 @@ public class Canvas3D extends Canvas { // ImageComponent2D offScreenBuffer = null; - // read buffer for reading off screen buffer - byte[] byteBuffer = new byte[1]; - // flag that indicates whether this canvas will use shared context boolean useSharedCtx = true; @@ -430,13 +432,6 @@ public class Canvas3D extends Canvas { // int textureColorTableSize; - // a mapping between underlying graphics library texture unit and - // texture unit state in j3d - // - // TODO: This mapping is now required to be 1-to-1, and it should be - // removed entirely in Java 3D 1.5 - int[] texUnitStateMap = null; - // number of active/enabled texture unit int numActiveTexUnit = 0; @@ -450,6 +445,9 @@ public class Canvas3D extends Canvas { // Query properties J3dQueryProps queryProps; + // Flag indicating a fatal rendering error of some sort + private boolean fatalError = false; + // // The positions of the manual left and right eyes in image-plate // coordinates. @@ -581,14 +579,9 @@ public class Canvas3D extends Canvas { // NOTE that this is *read-only* Transform3D vpcToEc; - // The window field when running Windows is the native HDC. With X11 it - // is the handle to the native X11 drawable. - int window = 0; - - // The vid field when running Windows is the pixel format. With X11 it is - // the visual id. - int vid = 0; - + // Opaque object representing the underlying drawable (window). This + // is defined by the Pipeline. + Drawable drawable = null; // fbConfig is a pointer to the fbConfig object that is associated with // the GraphicsConfiguration object used to create this Canvas. @@ -602,37 +595,35 @@ public class Canvas3D extends Canvas { // For Windows : Fix for issue 76. This is use as a holder of the // PixelFormat structure ( see also gldef.h ) to allow value such // as offScreen's pixelformat, and ARB function pointers to be stored. - long fbConfig = 0; - GraphicsConfigInfo gcInfo = null; - + long fbConfig = 0; + // offScreenBufferInfo is a pointer to additional information about the // offScreenBuffer in this Canvas. // // For Windows : Fix for issue 76. long offScreenBufferInfo = 0; - // fbConfigTable is a static hashtable which allows getBestConfiguration() + // graphicsConfigTable is a static hashtable which allows getBestConfiguration() // in NativeConfigTemplate3D to map a GraphicsConfiguration to the pointer // to the actual GLXFBConfig that glXChooseFBConfig() returns. The Canvas3D // doesn't exist at the time getBestConfiguration() is called, and // X11GraphicsConfig neither maintains this pointer nor provides a public // constructor to allow Java 3D to extend it. - // static Hashtable fbConfigInfoTable = new Hashtable(); -- Chien - static Hashtable fbConfigTable = new Hashtable(); + static Hashtable<GraphicsConfiguration,GraphicsConfigInfo> graphicsConfigTable = + new Hashtable<GraphicsConfiguration,GraphicsConfigInfo>(); // The native graphics version, vendor, and renderer information - private String nativeGraphicsVersion = "<UNKNOWN>"; - private String nativeGraphicsVendor = "<UNKNOWN>"; - private String nativeGraphicsRenderer = "<UNKNOWN>"; + String nativeGraphicsVersion = "<UNKNOWN>"; + String nativeGraphicsVendor = "<UNKNOWN>"; + String nativeGraphicsRenderer = "<UNKNOWN>"; - NativeWSInfo nativeWSobj = new NativeWSInfo(); boolean firstPaintCalled = false; // This reflects whether or not this canvas has seen an addNotify. boolean added = false; // This is the id for the underlying graphics context structure. - long ctx = 0; + Context ctx = null; // since the ctx id can be the same as the previous one, // we need to keep a time stamp to differentiate the contexts with the @@ -672,6 +663,7 @@ public class Canvas3D extends Canvas { TransparencyAttributesRetained transparency = null; ColoringAttributesRetained coloringAttributes = null; Transform3D modelMatrix = null; + Transform3D projTrans = null; TextureBin textureBin = null; @@ -687,13 +679,6 @@ public class Canvas3D extends Canvas { TextureUnitStateRetained[] texUnitState = null; /** - * cached View states for lazy native states update - */ - // - DVR support. - float cachedDvrFactor = 1.0f; - boolean cachedDvrResizeCompensation = true; - - /** * These cached values are only used in Pure Immediate and Mixed Mode rendering */ TextureRetained texture = null; @@ -779,22 +764,18 @@ public class Canvas3D extends Canvas { // Use by D3D to indicate using one pass Blend mode // if Texture interpolation mode is support. static final int TEXTURE_LERP = 0x4000; + static final int TEXTURE_NON_POWER_OF_TWO = 0x8000; int textureExtendedFeatures = 0; // Extensions supported by the underlying canvas - static final int SUN_GLOBAL_ALPHA = 0x1; - static final int EXT_ABGR = 0x2; - static final int EXT_BGR = 0x4; - static final int EXT_RESCALE_NORMAL = 0x8; - static final int EXT_MULTI_DRAW_ARRAYS = 0x10; - static final int SUN_MULTI_DRAW_ARRAYS = 0x20; - static final int SUN_CONSTANT_DATA = 0x40; - static final int EXT_SEPARATE_SPECULAR_COLOR = 0x80; - static final int ARB_TRANSPOSE_MATRIX = 0x100; - static final int ARB_MULTISAMPLE = 0x200; - static final int EXT_COMPILED_VERTEX_ARRAYS = 0x400; - static final int SUN_VIDEO_RESIZE = 0x800; + // + // NOTE: we should remove EXT_BGR and EXT_ABGR when the imaging code is + // rewritten + static final int SUN_GLOBAL_ALPHA = 0x1; + static final int EXT_ABGR = 0x2; + static final int EXT_BGR = 0x4; + static final int MULTISAMPLE = 0x8; // The following 10 variables are set by the native // createNewContext()/createQueryContext() methods @@ -876,93 +857,6 @@ public class Canvas3D extends Canvas { // specifies if each bin in this set is updated or not. Object curStateToUpdate[] = new Object[7]; - - // Native method for determining the texture color table size - // in the underlying API for this Canvas3D. - /* native int getTextureColorTableSize(long ctx); */ - - // This is the native method for creating the underlying graphics context. - private native long createNewContext(long display, int window, int vid, - long fbConfig, long shareCtx, boolean isSharedCtx, - boolean offScreen, - boolean glslLibraryAvailable, - boolean cgLibraryAvailable); - - private native void createQueryContext(long display, int window, int vid, - long fbConfig, boolean offScreen, int width, int height, - boolean glslLibraryAvailable, - boolean cgLibraryAvailable); - - native static void destroyContext(long display, int window, long context); - - // This is the native for creating offscreen buffer - native int createOffScreenBuffer(long ctx, long display, int vid, long fbConfig, int width, int height); - - native void destroyOffScreenBuffer(long ctx, long display, long fbConfig, int window); - - // This is the native for reading the image from the offscreen buffer - native void readOffScreenBuffer(long ctx, int format, int width, int height); - - // This is the native method for doing accumulation. - native void accum(long ctx, float value ); - - // This is the native method for doing accumulation return. - native void accumReturn(long ctx); - - // This is the native method for clearing the accumulation buffer. - native void clearAccum(long ctx); - - // This is the native method for getting the number of lights the underlying - // native library can support. - native int getNumCtxLights(long ctx); - - // Native method for decal 1st child setup - native boolean decal1stChildSetup(long ctx); - - // Native method for decal nth child setup - native void decalNthChildSetup(long ctx); - - // Native method for decal reset - native void decalReset(long ctx, boolean depthBufferEnable); - - // Native method for decal reset - native void ctxUpdateEyeLightingEnable(long ctx, boolean localEyeLightingEnable); - - // The following three methods are used in multi-pass case - - // native method for setting blend color - native void setBlendColor(long ctx, float red, float green, - float blue, float alpha); - - // native method for setting blend func - native void setBlendFunc(long ctx, int src, int dst); - - // native method for setting fog enable flag - native void setFogEnableFlag(long ctx, boolean enableFlag); - - // Setup the full scene antialising in D3D and ogl when GL_ARB_multisamle supported - native void setFullSceneAntialiasing(long ctx, boolean enable); - - // notify D3D that Canvas is resize - native int resizeD3DCanvas(long ctx); - - // notify D3D to toggle between FullScreen and window mode - native int toggleFullScreenMode(long ctx); - - native void setGlobalAlpha(long ctx, float alpha); - native void disableGlobalAlpha(long ctx); - - // Native method to update separate specular color control - native void updateSeparateSpecularColorEnable(long ctx, boolean control); - - // Initialization for D3D when scene begin - native void beginScene(long ctx); - native void endScene(long ctx); - - // True under Solaris, - // False under windows when display mode <= 8 bit - native boolean validGraphicsMode(); - /** * The list of lights that are currently being represented in the native * graphics context. @@ -1011,108 +905,62 @@ public class Canvas3D extends Canvas { // and canvas removeNotify() called while Renderer is running boolean ctxChanged = false; - // native method for setting light enables - native void setLightEnables(long ctx, long enableMask, int maxLights); - - // native method for setting scene ambient - native void setSceneAmbient(long ctx, float red, float green, float blue); - - // native method for disabling fog - native void disableFog(long ctx); - - // native method for disabling modelClip - native void disableModelClip(long ctx); - - // native method for setting default RenderingAttributes - native void resetRenderingAttributes(long ctx, - boolean depthBufferWriteEnableOverride, - boolean depthBufferEnableOverride); - - // native method for setting default texture - native void resetTextureNative(long ctx, int texUnitIndex); - - // native method for activating a particular texture unit - native void activeTextureUnit(long ctx, int texUnitIndex); - - // native method for setting default TexCoordGeneration - native void resetTexCoordGeneration(long ctx); - - // native method for setting default TextureAttributes - native void resetTextureAttributes(long ctx); - - // native method for setting default PolygonAttributes - native void resetPolygonAttributes(long ctx); - - // native method for setting default LineAttributes - native void resetLineAttributes(long ctx); - - // native method for setting default PointAttributes - native void resetPointAttributes(long ctx); - - // native method for setting default TransparencyAttributes - native void resetTransparency(long ctx, int geometryType, - int polygonMode, boolean lineAA, - boolean pointAA); - - // native method for setting default ColoringAttributes - native void resetColoringAttributes(long ctx, - float r, float g, - float b, float a, - boolean enableLight); - - // native method for setting Material when no material is present - native void updateMaterial(long ctx, float r, float g, float b, float a); - - - // native method for updating the texture unit state map - private native void updateTexUnitStateMap(long ctx, int numActiveTexUnit, - int[] texUnitStateMap); - - /** - * This native method makes sure that the rendering for this canvas - * gets done now. - */ - native void syncRender(long ctx, boolean wait); - // Default graphics configuration private static GraphicsConfiguration defaultGcfg = null; // Returns default graphics configuration if user passes null // into the Canvas3D constructor private static synchronized GraphicsConfiguration defaultGraphicsConfiguration() { - if (defaultGcfg == null) { - GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D(); - defaultGcfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getBestConfiguration(template); - } - return defaultGcfg; + if (defaultGcfg == null) { + GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D(); + defaultGcfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getBestConfiguration(template); + } + return defaultGcfg; } + // Returns true if this is a valid graphics configuration, obtained + // via a GraphicsConfigTemplate3D. + private static boolean isValidConfig(GraphicsConfiguration gconfig) { + // If this is a valid GraphicsConfiguration object, then it will + // be in the graphicsConfigTable + return graphicsConfigTable.containsKey(gconfig); + } + + // Checks the given graphics configuration, and throws an exception if + // the config is null or invalid. private static synchronized GraphicsConfiguration - checkForValidGraphicsConfig(GraphicsConfiguration gconfig) { - - if (gconfig == null) { - // Print out warning if Canvas3D is called with a - // null GraphicsConfiguration - System.err.println("************************************************************************"); - System.err.println(J3dI18N.getString("Canvas3D7")); - System.err.println(J3dI18N.getString("Canvas3D18")); - System.err.println("************************************************************************"); - return defaultGraphicsConfiguration(); - } + checkForValidGraphicsConfig(GraphicsConfiguration gconfig, boolean offScreen) { + + // Issue 266 - for backwards compatibility with legacy applications, + // we will accept a null GraphicsConfiguration for an on-screen Canvas3D + // only if the "allowNullGraphicsConfig" system property is set to true. + if (!offScreen && VirtualUniverse.mc.allowNullGraphicsConfig) { + if (gconfig == null) { + // Print out warning if Canvas3D is called with a + // null GraphicsConfiguration + System.err.println(J3dI18N.getString("Canvas3D7")); + System.err.println(" " + J3dI18N.getString("Canvas3D18")); + + // Use a default graphics config + gconfig = defaultGraphicsConfiguration(); + } + } - if (!J3dGraphicsConfig.isValidConfig(gconfig)) { - // Print out warning if Canvas3D is called with a - // GraphicsConfiguration that wasn't created from a - // GraphicsConfigTemplate3D (Solaris only). - System.err.println("************************************************************************"); - System.err.println(J3dI18N.getString("Canvas3D21")); - System.err.println(J3dI18N.getString("Canvas3D22")); - System.err.println("************************************************************************"); - return defaultGraphicsConfiguration(); - } + // Validate input graphics config + if (gconfig == null) { + throw new NullPointerException(J3dI18N.getString("Canvas3D19")); + } else if (!isValidConfig(gconfig)) { + throw new IllegalArgumentException(J3dI18N.getString("Canvas3D17")); + } + + return gconfig; + } - return gconfig; + // Return the actual graphics config that will be used to construct + // the AWT Canvas. This is permitted to be non-unique or null. + private static GraphicsConfiguration getGraphicsConfig(GraphicsConfiguration gconfig) { + return Pipeline.getPipeline().getGraphicsConfig(gconfig); } /** @@ -1144,11 +992,7 @@ public class Canvas3D extends Canvas { * GraphicsConfiguration does not support 3D rendering */ public Canvas3D(GraphicsConfiguration graphicsConfiguration) { - this(checkForValidGraphicsConfig(graphicsConfiguration), false); - - // XXXX: ENHANCEMENT -- remove call to checkForValidGraphicsConfig. - // Call should then be: - // this(graphicsConfiguration, false); + this(null, checkForValidGraphicsConfig(graphicsConfiguration, false), false); } /** @@ -1173,64 +1017,71 @@ public class Canvas3D extends Canvas { * * @since Java 3D 1.2 */ - public Canvas3D(GraphicsConfiguration graphicsConfiguration, - boolean offScreen) { + public Canvas3D(GraphicsConfiguration graphicsConfiguration, boolean offScreen) { + this(null, checkForValidGraphicsConfig(graphicsConfiguration, offScreen), offScreen); + } - super(graphicsConfiguration); + // Private constructor only called by the two public constructors after + // they have validated the graphics config (and possibly constructed a new + // default config). + // The graphics config must be valid, unique, and non-null. + private Canvas3D(Object dummyObj1, + GraphicsConfiguration graphicsConfiguration, + boolean offScreen) { + this(dummyObj1, + graphicsConfiguration, + getGraphicsConfig(graphicsConfiguration), + offScreen); + } - if (graphicsConfiguration == null) { - throw new NullPointerException - (J3dI18N.getString("Canvas3D19")); - } + // Private constructor only called by the previous private constructor. + // The graphicsConfiguration parameter is used by Canvas3D to lookup the + // graphics device and graphics template. The graphicsConfiguration2 + // parameter is generated by the Pipeline from graphicsConfiguration and + // is only used to initialize the java.awt.Canvas. + private Canvas3D(Object dummyObj1, + GraphicsConfiguration graphicsConfiguration, + GraphicsConfiguration graphicsConfiguration2, + boolean offScreen) { - if (!J3dGraphicsConfig.isValidConfig(graphicsConfiguration)) { - throw new IllegalArgumentException - (J3dI18N.getString("Canvas3D17")); - } - - if (!J3dGraphicsConfig.isValidPixelFormat(graphicsConfiguration)) { - throw new IllegalArgumentException - (J3dI18N.getString("Canvas3D17")); - } + super(graphicsConfiguration2); this.offScreen = offScreen; this.graphicsConfiguration = graphicsConfiguration; - // Needed for Win32-D3D only. - vid = nativeWSobj.getCanvasVid(graphicsConfiguration); + // Issue 131: Set the autoOffScreen variable based on whether this + // canvas3d implements the AutoOffScreenCanvas3D tagging interface. + // Eventually, we may replace this with an actual API. + boolean autoOffScreenCanvas3D = false; + if (this instanceof com.sun.j3d.exp.swing.impl.AutoOffScreenCanvas3D) { + autoOffScreenCanvas3D = true; + } + + // Throw an illegal argument exception if an on-screen canvas is tagged + // as an auto-off-screen canvas + if (autoOffScreenCanvas3D && !offScreen) { + throw new IllegalArgumentException(J3dI18N.getString("Canvas3D25")); + } // Issue 163 : Set dirty bits for both Renderer and RenderBin cvDirtyMask[0] = VIEW_INFO_DIRTY; cvDirtyMask[1] = VIEW_INFO_DIRTY; - // Fix for issue 20. - // Needed for Linux and Solaris. - GraphicsConfigInfo gcInfo; - gcInfo = (GraphicsConfigInfo) fbConfigTable.get(graphicsConfiguration); - if (gcInfo != null) { - fbConfig = gcInfo.getFBConfig(); - requestedStencilSize = gcInfo.getRequestedStencilSize(); - - /* - System.out.println("Canvas3D : requestedStencilSize is " + - requestedStencilSize); - System.out.println("Canvas3D creation FBConfig = " + fbConfig + - " offScreen is " + offScreen ); - */ - // This check is needed for Unix and Win-ogl only. fbConfig should - // remain as -1, default value, for D3D case. - if (fbConfig == 0) { - throw new IllegalArgumentException - (J3dI18N.getString("Canvas3D23")); - } - } - + GraphicsConfigInfo gcInfo = graphicsConfigTable.get(graphicsConfiguration); + requestedStencilSize = gcInfo.getGraphicsConfigTemplate3D().getStencilSize(); + + fbConfig = Pipeline.getPipeline().getFbConfig(gcInfo); + if (offScreen) { - screen = new Screen3D(graphicsConfiguration, offScreen); - // TODO: keep a list of off-screen Screen3D objects? - // Does this list need to be grouped by GraphicsDevice? + // Issue 131: set manual rendering flag based on whether this is + // an auto-off-screen Canvas3D. + manualRendering = !autoOffScreenCanvas3D; + + screen = new Screen3D(graphicsConfiguration, offScreen); + // QUESTION: keep a list of off-screen Screen3D objects? + // Does this list need to be grouped by GraphicsDevice? // since this canvas will not receive the addNotify // callback from AWT, set the added flag here @@ -1243,22 +1094,26 @@ public class Canvas3D extends Canvas { // this canvas will not receive the paint callback either, // so set the necessary flags here as well firstPaintCalled = true; - ctx = 0; + ctx = null; evaluateActive(); // create the rendererStructure object //rendererStructure = new RendererStructure(); offScreenCanvasLoc = new Point(0, 0); offScreenCanvasSize = new Dimension(0, 0); - offScreenCanvasClippedLoc = new Point(0, 0); - offScreenCanvasClippedSize = new Dimension(0, 0); this.setLocation(offScreenCanvasLoc); this.setSize(offScreenCanvasSize); newSize = offScreenCanvasSize; newPosition = offScreenCanvasLoc; + // Issue 131: create event catchers for auto-offScreen + if (!manualRendering) { + eventCatcher = new EventCatcher(this); + canvasViewEventCatcher = new CanvasViewEventCatcher(this); + } } else { + GraphicsDevice graphicsDevice; graphicsDevice = graphicsConfiguration.getDevice(); @@ -1278,24 +1133,30 @@ public class Canvas3D extends Canvas { } - drawingSurfaceObject = new DrawingSurfaceObjectAWT - (this, VirtualUniverse.mc.awt, screen.display, screen.screen, - VirtualUniverse.mc.xineramaDisabled); - lights = new LightRetained[VirtualUniverse.mc.maxLights]; frameCount = new int[VirtualUniverse.mc.maxLights]; for (int i=0; i<frameCount.length;i++) { frameCount[i] = -1; } + // Construct the drawing surface object for this Canvas3D + drawingSurfaceObject = + Pipeline.getPipeline().createDrawingSurfaceObject(this); + // Get double buffer, stereo available, scene antialiasing - // flags from template. + // flags from graphics config GraphicsConfigTemplate3D.getGraphicsConfigFeatures(this); useDoubleBuffer = doubleBufferEnable && doubleBufferAvailable; useStereo = stereoEnable && stereoAvailable; useSharedCtx = VirtualUniverse.mc.isSharedCtx; + // Issue 131: assert that only an off-screen canvas can be demand-driven + assert (!offScreen && manualRendering) == false; + + // Assert that offScreen is *not* double-buffered or stereo + assert (offScreen && useDoubleBuffer) == false; + assert (offScreen && useStereo) == false; } /** @@ -1364,6 +1225,14 @@ public class Canvas3D extends Canvas { * to function properly. */ public void addNotify() { + + // Issue 131: This method is now being called by JCanvas3D for its + // off-screen Canvas3D, so we need to handle off-screen properly here. + // Do nothing for manually-rendered off-screen canvases + if (manualRendering) { + return; + } + Renderer rdr = null; if (isRunning && (screen != null)) { @@ -1378,9 +1247,11 @@ public class Canvas3D extends Canvas { } } } - - super.addNotify(); + // Issue 131: Don't call super for off-screen Canvas3D + if (!offScreen) { + super.addNotify(); + } screen.addUser(this); parent = this.getParent(); @@ -1394,26 +1265,24 @@ public class Canvas3D extends Canvas { ((Window)parent).addComponentListener(eventCatcher); } - if (!offScreen) { - if(canvasViewEventCatcher.parentList.size() > 0) { - Component comp; - //Release and clear. - for(int i=0; i<canvasViewEventCatcher.parentList.size(); i++) { - comp = (Component)canvasViewEventCatcher.parentList.get(i); - comp.removeComponentListener(canvasViewEventCatcher); - } - canvasViewEventCatcher.parentList.clear(); - } - - Component parent = (Component) this.getParent(); - while(parent != null) { - parent.addComponentListener(canvasViewEventCatcher); - canvasViewEventCatcher.parentList.add(parent); - parent = parent.getParent(); - } - // Need to traverse up the parent and add listener. - this.addComponentListener(canvasViewEventCatcher); - } + if(canvasViewEventCatcher.parentList.size() > 0) { + Component comp; + //Release and clear. + for(int i=0; i<canvasViewEventCatcher.parentList.size(); i++) { + comp = (Component)canvasViewEventCatcher.parentList.get(i); + comp.removeComponentListener(canvasViewEventCatcher); + } + canvasViewEventCatcher.parentList.clear(); + } + + Component parent = (Component) this.getParent(); + while(parent != null) { + parent.addComponentListener(canvasViewEventCatcher); + canvasViewEventCatcher.parentList.add(parent); + parent = parent.getParent(); + } + // Need to traverse up the parent and add listener. + this.addComponentListener(canvasViewEventCatcher); synchronized(dirtyMaskLock) { cvDirtyMask[0] |= MOVED_OR_RESIZED_DIRTY; @@ -1426,9 +1295,16 @@ public class Canvas3D extends Canvas { validCanvas = true; added = true; + // Since we won't get a paint call for off-screen canvases, we need + // to set the first paint and visible flags here + if (offScreen) { + firstPaintCalled = true; + visible = true; + } + // In case the same canvas is removed and add back, // we have to change isRunningStatus back to true; - if (isRunning) { + if (isRunning && !fatalError) { isRunningStatus = true; } @@ -1440,7 +1316,7 @@ public class Canvas3D extends Canvas { if ((view != null) && (view.universe != null)) { view.universe.checkForEnableEvents(); } - + } // When this canvas is removed a frame, this notification gets called. We @@ -1452,9 +1328,13 @@ public class Canvas3D extends Canvas { * method need to call super.removeNotify() in their removeNotify() * method for Java 3D to function properly. */ - public void removeNotify() { + // Do nothing for manually-rendered off-screen canvases + if (manualRendering) { + return; + } + Renderer rdr = null; if (isRunning && (screen != null)) { @@ -1470,11 +1350,6 @@ public class Canvas3D extends Canvas { } } - if (!offScreen) { - firstPaintCalled = false; - } - - // Note that although renderer userStop is true, // MasterControl can still schedule renderer to run through // runMonotor(RUN_RENDERER_CLEANUP) which skip userStop @@ -1490,23 +1365,10 @@ public class Canvas3D extends Canvas { removeCtx(); - synchronized (drawingSurfaceObject) { - - DrawingSurfaceObjectAWT dso = - (DrawingSurfaceObjectAWT)drawingSurfaceObject; - // get nativeDS before it is set to 0 in invalidate() - long ds = dso.getDS(); - long ds_struct[] = {ds, dso.getDSI()}; - if (ds != 0) { - VirtualUniverse.mc.postRequest( - MasterControl.FREE_DRAWING_SURFACE, - ds_struct); - } - - drawingSurfaceObject.invalidate(); - - } + Pipeline.getPipeline().freeDrawingSurface(this, drawingSurfaceObject); + // Clear first paint and visible flags + firstPaintCalled = false; visible = false; screen.removeUser(this); @@ -1519,7 +1381,7 @@ public class Canvas3D extends Canvas { ra = null; graphicsContext3D = null; - ctx = 0; + ctx = null; // must be after removeCtx() because // it will free graphics2D textureID graphics2D = null; @@ -1566,9 +1428,7 @@ public class Canvas3D extends Canvas { parent.requestFocus(); } - if (!offScreen) { - added = false; - } + added = false; if (rdr != null) { rdr.userStop = false; @@ -1587,10 +1447,10 @@ public class Canvas3D extends Canvas { // Also we can't use this as lock, otherwise there is a // deadlock where updateViewCache get a lock of this and // get a lock of this component. But Container - // remove will get a lock of this componet follows by evaluateActive. + // remove will get a lock of this component follows by evaluateActive. synchronized (evaluateLock) { - if ((visible || offScreen) && firstPaintCalled) { + if ((visible || manualRendering) && firstPaintCalled) { if (!active) { active = true; @@ -1771,7 +1631,9 @@ public class Canvas3D extends Canvas { * off-screen mode. */ public final void stopRenderer() { - if (offScreen) + // Issue 131: renderer can't be stopped only if it is an offscreen, + // manual canvas. Otherwise, it has to be seen as an onscreen canvas. + if (manualRendering) throw new IllegalStateException(J3dI18N.getString("Canvas3D14")); if (isRunning) { @@ -1791,6 +1653,11 @@ public class Canvas3D extends Canvas { * render the scene graph to the canvas. */ public final void startRenderer() { + // Issue 260 : ignore attempt to start renderer if fatal error + if (fatalError) { + return; + } + if (!isRunning) { VirtualUniverse.mc.postRequest(MasterControl.START_RENDERER, this); isRunning = true; @@ -1808,6 +1675,24 @@ public class Canvas3D extends Canvas { return isRunning; } + // Returns the state of the fatal error flag + boolean isFatalError() { + return fatalError; + } + + // Sets the fatal error flag to true; stop the renderer for this canvas + void setFatalError() { + fatalError = true; + + if (isRunning) { + isRunning = false; + + if (!manualRendering) { + VirtualUniverse.mc.postRequest(MasterControl.STOP_RENDERER, this); + } + } + } + /** * Retrieves a flag indicating whether this Canvas3D is an @@ -1835,18 +1720,36 @@ public class Canvas3D extends Canvas { * <p> * * @param buffer the image component that will be rendered into by - * subsequent calls to renderOffScreenBuffer. + * subsequent calls to renderOffScreenBuffer. The image component must not + * be part of a live scene graph, nor may it subsequently be made part of a + * live scene graph while being used as an off-screen buffer; an + * IllegalSharingException is thrown in such cases. The buffer may be null, + * indicating that the previous off-screen buffer is released without a new + * buffer being set. * * @exception IllegalStateException if this Canvas3D is not in * off-screen mode. + * * @exception RestrictedAccessException if an off-screen rendering * is in process for this Canvas3D. - * @exception IllegalSharingException if the specified - * ImageComponent2D is used by more than one Canvas3D. + * + * @exception IllegalSharingException if the specified ImageComponent2D + * is part of a live scene graph + * + * @exception IllegalSharingException if the specified ImageComponent2D is + * being used by an immediate mode context, or by another Canvas3D as + * an off-screen buffer. + * + * @exception IllegalArgumentException if the image class of the specified + * ImageComponent2D is <i>not</i> ImageClass.BUFFERED_IMAGE. + * * @exception IllegalArgumentException if the specified * ImageComponent2D is in by-reference mode and its - * RenderedImage is not an instance of a BufferedImage or - * if the ImageComponent2D format is FORMAT_CHANNEL8. + * RenderedImage is null. + * + * @exception IllegalArgumentException if the ImageComponent2D format + * is <i>not</i> a 3-component format (e.g., FORMAT_RGB) + * or a 4-component format (e.g., FORMAT_RGBA). * * @see #renderOffScreenBuffer * @see Screen3D#setSize(int, int) @@ -1867,38 +1770,73 @@ public class Canvas3D extends Canvas { // Check that offScreenBufferPending is not already set J3dDebug.doAssert(!offScreenBufferPending, "!offScreenBufferPending"); + + if (offScreenBuffer != null && offScreenBuffer != buffer) { + ImageComponent2DRetained i2dRetained = + (ImageComponent2DRetained)offScreenBuffer.retained; + i2dRetained.setUsedByOffScreen(false); + } if (buffer != null) { ImageComponent2DRetained bufferRetained = (ImageComponent2DRetained)buffer.retained; if (bufferRetained.byReference && - !(bufferRetained.bImage[0] instanceof BufferedImage)) { + !(bufferRetained.getRefImage(0) instanceof BufferedImage)) { throw new IllegalArgumentException(J3dI18N.getString("Canvas3D15")); } - if (bufferRetained.format == ImageComponent.FORMAT_CHANNEL8) { + if (bufferRetained.getNumberOfComponents() < 3 ) { throw new IllegalArgumentException(J3dI18N.getString("Canvas3D16")); } + if (buffer.isLive()) { + throw new IllegalSharingException(J3dI18N.getString("Canvas3D26")); + } + + if (bufferRetained.getInImmCtx()) { + throw new IllegalSharingException(J3dI18N.getString("Canvas3D27")); + } + + if (buffer != offScreenBuffer && bufferRetained.getUsedByOffScreen()) { + throw new IllegalSharingException(J3dI18N.getString("Canvas3D28")); + } + + bufferRetained.setUsedByOffScreen(true); + width = bufferRetained.width; height = bufferRetained.height; - } + + // Issues 347, 348 - assign a canvasId for off-screen Canvas3D + if (manualRendering) { + if (canvasBit == 0) { + canvasId = VirtualUniverse.mc.getCanvasId(); + canvasBit = 1 << canvasId; + } + } + } else { width = height = 0; - } - // XXXX: illegalSharing - + // Issues 347, 348 - release canvasId for off-screen Canvas3D + if (manualRendering) { + if (canvasBit != 0) { + VirtualUniverse.mc.freeCanvasId(canvasId); + canvasBit = 0; + canvasId = 0; + } + } + } + if ((offScreenCanvasSize.width != width) || (offScreenCanvasSize.height != height)) { - if (window != 0) { + if (drawable != null) { // Fix for Issue 18 and Issue 175 // Will do destroyOffScreenBuffer in the Renderer thread. sendDestroyCtxAndOffScreenBuffer(); - window = 0; + drawable = null; } // set the canvas dimension according to the buffer dimension @@ -1908,9 +1846,9 @@ public class Canvas3D extends Canvas { if (width > 0 && height > 0) { sendCreateOffScreenBuffer(); } - ctx = 0; + ctx = null; } - else if (ctx != 0) { + else if (ctx != null) { removeCtx(); } @@ -1922,7 +1860,6 @@ public class Canvas3D extends Canvas { } } - /** * Retrieves the off-screen buffer for this Canvas3D. * @@ -1974,10 +1911,18 @@ public class Canvas3D extends Canvas { */ public void renderOffScreenBuffer() { - if (!offScreen) throw new IllegalStateException(J3dI18N.getString("Canvas3D1")); + // Issue 131: Cannot manually render to an automatic canvas. + if (!manualRendering) + throw new IllegalStateException(J3dI18N.getString("Canvas3D24")); + + // Issue 260 : Cannot render if we already have a fatal error + if (fatalError) { + throw new IllegalRenderingStateException(J3dI18N.getString("Canvas3D30")); + } + if (offScreenBuffer == null) throw new NullPointerException(J3dI18N.getString("Canvas3D10")); @@ -2008,44 +1953,8 @@ public class Canvas3D extends Canvas { return; } - // determine the offScreen boundary - // do the boundary determination here because setCanvasLocation can - // be done at any time. - - if ((offScreenCanvasLoc.x >= screenSize.width) || - (offScreenCanvasLoc.y >= screenSize.height)) - return; - - if (offScreenCanvasLoc.x < 0) { - offScreenCanvasClippedLoc.x = 0 - offScreenCanvasLoc.x; - offScreenCanvasClippedSize.width = - offScreenCanvasSize.width - offScreenCanvasClippedLoc.x; - if (offScreenCanvasClippedSize.width > screenSize.width) - offScreenCanvasClippedSize.width = screenSize.width; - } else { - offScreenCanvasClippedLoc.x = 0; - offScreenCanvasClippedSize.width = offScreenCanvasSize.width; - if ((offScreenCanvasLoc.x + offScreenCanvasClippedSize.width) - > screenSize.width) - offScreenCanvasClippedSize.width = - screenSize.width - offScreenCanvasLoc.x; - } - - - int lly = offScreenCanvasLoc.y + offScreenCanvasSize.height; - if (lly < 0) { - return; - } else if (lly <= screenSize.height) { - offScreenCanvasClippedLoc.y = 0; - if (offScreenCanvasLoc.y < 0) - offScreenCanvasClippedSize.height = lly; - else - offScreenCanvasClippedSize.height = offScreenCanvasSize.height; - } else if (lly > screenSize.height) { - offScreenCanvasClippedSize.height = - screenSize.height - offScreenCanvasLoc.y; - offScreenCanvasClippedLoc.y = lly - screenSize.height; - } + // Issue 131: moved code that determines off-screen boundary to separate + // method that is called from the renderer offScreenRendering = true; @@ -2085,7 +1994,7 @@ public class Canvas3D extends Canvas { // to do the offscreen rendering now if (Thread.currentThread() == screen.renderer) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.RENDER_THREAD; createMessage.type = J3dMessage.RENDER_OFFSCREEN; createMessage.universe = this.view.universe; @@ -2112,7 +2021,7 @@ public class Canvas3D extends Canvas { // XXXX: // Now we are in trouble, this will cause deadlock if // waitForOffScreenRendering() is invoked - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.RENDER_THREAD; createMessage.type = J3dMessage.RENDER_OFFSCREEN; createMessage.universe = this.view.universe; @@ -2130,7 +2039,7 @@ public class Canvas3D extends Canvas { // currentThread() == view.universe.behaviorScheduler // since the caller may be another universe Behavior // scheduler. - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.RENDER_THREAD; createMessage.type = J3dMessage.RENDER_OFFSCREEN; createMessage.universe = this.view.universe; @@ -2143,7 +2052,7 @@ public class Canvas3D extends Canvas { // send a message to renderBin // Fix for issue 66 : Since view might not been set yet, // we have to use pendingView instead. - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.RENDER_OFFSCREEN; createMessage.universe = this.pendingView.universe; @@ -2174,6 +2083,10 @@ public class Canvas3D extends Canvas { * @since Java 3D 1.2 */ public void waitForOffScreenRendering() { + // TODO KCR : throw exception if !offScreen + + // TODO KCR Issue 131: throw exception if !manualRendering + while (offScreenRendering) { MasterControl.threadYield(); } @@ -2297,46 +2210,54 @@ public class Canvas3D extends Canvas { } void endOffScreenRendering() { - - - - - // Evaluate what the stored format is before reading to offscreen buffer - if (((ImageComponent2DRetained)offScreenBuffer.retained).isByReference()) { - ((ImageComponent2DRetained)offScreenBuffer.retained).geomLock.getLock(); - ((ImageComponent2DRetained)offScreenBuffer.retained).evaluateExtensions(extensionsSupported); - ((ImageComponent2DRetained)offScreenBuffer.retained).geomLock.unLock(); - } - - - - int bytesPerPixel = ((ImageComponent2DRetained)offScreenBuffer.retained).getEffectiveBytesPerPixel(); - int format = ((ImageComponent2DRetained)offScreenBuffer.retained).getEffectiveFormat(); - - - // allocate read buffer space - - int size = - offScreenCanvasSize.width * offScreenCanvasSize.height * bytesPerPixel; - if (byteBuffer.length < size) - byteBuffer = new byte[size]; - - - // read the image from the offscreen buffer - - readOffScreenBuffer(ctx, - format, - offScreenCanvasSize.width, offScreenCanvasSize.height); - - - // copy it into the ImageComponent - - ((ImageComponent2DRetained)offScreenBuffer.retained).retrieveImage( - byteBuffer, offScreenCanvasClippedLoc.x, offScreenCanvasClippedLoc.y, - offScreenCanvasClippedSize.width, offScreenCanvasClippedSize.height); + + ImageComponent2DRetained icRetained = (ImageComponent2DRetained)offScreenBuffer.retained; + boolean isByRef = icRetained.isByReference(); + boolean isYUp = icRetained.isYUp(); + ImageComponentRetained.ImageData imageData = icRetained.getImageData(false); + + if(!isByRef) { + // If icRetained has a null image ( BufferedImage) + if (imageData == null) { + assert (!isByRef); + icRetained.createBlankImageData(); + imageData = icRetained.getImageData(false); + } + // Check for possible format conversion in imageData + else { + // Format convert imageData if format is unsupported. + icRetained.evaluateExtensions(this); + } + // read the image from the offscreen buffer + readOffScreenBuffer(ctx, icRetained.getImageFormatTypeIntValue(false), + icRetained.getImageDataTypeIntValue(), imageData.get(), + offScreenCanvasSize.width, offScreenCanvasSize.height); + + } else { + icRetained.geomLock.getLock(); + // Create a copy of format converted image in imageData if format is unsupported. + icRetained.evaluateExtensions(this); + + // read the image from the offscreen buffer + readOffScreenBuffer(ctx, icRetained.getImageFormatTypeIntValue(false), + icRetained.getImageDataTypeIntValue(), imageData.get(), + offScreenCanvasSize.width, offScreenCanvasSize.height); + + // For byRef, we might have to copy buffer back into + // the user's referenced ImageComponent2D + if(!imageData.isDataByRef()) { + if(icRetained.isImageTypeSupported()) { + icRetained.copyToRefImage(0); + } else { + // This method only handle RGBA conversion. + icRetained.copyToRefImageWithFormatConversion(0); + } + } + + icRetained.geomLock.unLock(); + } } - /** * Synchronize and swap buffers on a double buffered canvas for * this Canvas3D object. This method should only be called if the @@ -2380,7 +2301,7 @@ public class Canvas3D extends Canvas { if (firstPaintCalled && useDoubleBuffer) { try { - if (validCtx && (ctx != 0) && (view != null)) { + if (validCtx && (ctx != null) && (view != null)) { synchronized (drawingSurfaceObject) { if (validCtx) { if (!drawingSurfaceObject.renderLock()) { @@ -2388,7 +2309,7 @@ public class Canvas3D extends Canvas { return; } this.syncRender(ctx, true); - int status = swapBuffers(ctx, screen.display, window); + int status = swapBuffers(ctx, screen.display, drawable); if (status != NOCHANGE) { resetImmediateRendering(status); } @@ -2409,6 +2330,7 @@ public class Canvas3D extends Canvas { antialiasingSet = false; if (reEvaluateCanvasCmd == RESIZE) { + assert VirtualUniverse.mc.isD3D(); status = resizeD3DCanvas(ctx); } else { status = toggleFullScreenMode(ctx); @@ -2425,10 +2347,9 @@ public class Canvas3D extends Canvas { /** * Wrapper for native createNewContext method. */ - long createNewContext(long shareCtx, boolean isSharedCtx) { - long retVal = createNewContext(this.screen.display, - this.window, - this.vid, + Context createNewContext(Context shareCtx, boolean isSharedCtx) { + Context retVal = createNewContext(this.screen.display, + this.drawable, this.fbConfig, shareCtx, isSharedCtx, this.offScreen, @@ -2436,6 +2357,7 @@ public class Canvas3D extends Canvas { VirtualUniverse.mc.cgLibraryAvailable); // compute the max available texture units maxAvailableTextureUnits = Math.max(maxTextureUnits, maxTextureImageUnits); + return retVal; } @@ -2443,86 +2365,47 @@ public class Canvas3D extends Canvas { * Make the context associated with the specified canvas current. */ final void makeCtxCurrent() { - makeCtxCurrent(ctx, screen.display, window); + makeCtxCurrent(ctx, screen.display, drawable); } /** * Make the specified context current. */ - final void makeCtxCurrent(long ctx) { - makeCtxCurrent(ctx, screen.display, window); + final void makeCtxCurrent(Context ctx) { + makeCtxCurrent(ctx, screen.display, drawable); } - final void makeCtxCurrent(long ctx, long dpy, int win) { - if (ctx != screen.renderer.currentCtx || win != screen.renderer.currentWindow) { + final void makeCtxCurrent(Context ctx, long dpy, Drawable drawable) { + if (ctx != screen.renderer.currentCtx || drawable != screen.renderer.currentDrawable) { if (!drawingSurfaceObject.isLocked()) { drawingSurfaceObject.renderLock(); - useCtx(ctx, dpy, win); + useCtx(ctx, dpy, drawable); drawingSurfaceObject.unLock(); } else { - useCtx(ctx, dpy, win); + useCtx(ctx, dpy, drawable); } screen.renderer.currentCtx = ctx; - screen.renderer.currentWindow = win; + screen.renderer.currentDrawable = drawable; } } - - // The native method that sets this ctx to be the current one - static native boolean useCtx(long ctx, long display, int window); - - native void clear(long ctx, float r, float g, float b, int winWidth, int winHeight, - ImageComponent2DRetained image, int imageScaleMode, byte[] imageYdown); - native void textureclear(long ctx, int maxX, int maxY, - float r, float g, float b, - int winWidth, int winHeight, - int objectId, int scalemode, - ImageComponent2DRetained image, - boolean update); - - - // The native method for swapBuffers - native int swapBuffers(long ctx, long dpy, int win); - - // The native method for videoResize. -- Support DVR. - native void videoResize(long ctx, long dpy, int win, float dvrFactor); - - // The native method for videoResizeCompensation. -- Support DVR. - native void videoResizeCompensation( long ctx, boolean enable); - - // The native method for setting the ModelView matrix. - native void setModelViewMatrix(long ctx, double[] viewMatrix, double[] modelMatrix); - - // The native method for setting the Projection matrix. - native void setProjectionMatrix(long ctx, double[] projMatrix); - - // The native method for setting the Viewport. - native void setViewport(long ctx, int x, int y, int width, int height); - - // used for display Lists - native void newDisplayList(long ctx, int displayListId); - native void endDisplayList(long ctx); - native void callDisplayList(long ctx, int id, boolean isNonUniformScale); - - native static void freeDisplayList(long ctx, int id); - native static void freeTexture(long ctx, int id); - - native void composite(long ctx, int px, int py, - int xmin, int ymin, int xmax, int ymax, - int rasWidth, byte[] image, - int winWidth, int winHeight); - - native void texturemapping(long ctx, - int px, int py, - int xmin, int ymin, int xmax, int ymax, - int texWidth, int texHeight, - int rasWidth, - int format, int objectId, - byte[] image, - int winWidth, int winHeight); - - native boolean initTexturemapping(long ctx, int texWidth, - int texHeight, int objectId); + // Give the pipeline a chance to release the context; the Pipeline may + // or may not ignore this call. + void releaseCtx() { + if (screen.renderer.currentCtx != null) { + boolean needLock = !drawingSurfaceObject.isLocked(); + if (needLock) { + drawingSurfaceObject.renderLock(); + } + if (releaseCtx(screen.renderer.currentCtx, screen.display)) { + screen.renderer.currentCtx = null; + screen.renderer.currentDrawable = null; + } + if (needLock) { + drawingSurfaceObject.unLock(); + } + } + } /** @@ -3301,6 +3184,10 @@ public class Canvas3D extends Canvas { * <td>Float</td> * </tr> * <tr> + * <td><code>textureNonPowerOfTwoAvailable</code></td> + * <td>Boolean</td> + * </tr> + * <tr> * <td><code>vertexAttrsMax</code></td> * <td>Integer</td> * </tr> @@ -3584,6 +3471,7 @@ public class Canvas3D extends Canvas { * LINEAR_DETAIL_RGB as the texture magnification filter mode will * be ignored. The texture magnification filter mode in effect will * be BASE_LEVEL_LINEAR. + * As of Java 3D 1.5, this property is always false. * </ul> * </li> * @@ -3621,6 +3509,18 @@ public class Canvas3D extends Canvas { * layer, and an attempt to set anisotropic filter degree will be ignored. * </ul> * </li> + + * <li> + * <code>textureNonPowerOfTwoAvailable</code> + * <ul> + * A Boolean indicating whether or not texture dimensions that are + * not powers of two are supported for + * for this Canvas3D. If it indicates false, then textures with + * non power of two sizes will be ignored. Set the property + * j3d.textureEnforcePowerOfTwo to revert to the pre-1.5 behavior + * of throwing exceptions for non power of two textures. + * </ul> + * </li> * * <li> * <code>vertexAttrsMax</code> @@ -3661,18 +3561,23 @@ public class Canvas3D extends Canvas { boolean createDummyCtx = false; synchronized (VirtualUniverse.mc.contextCreationLock) { - if (ctx == 0) { + if (ctx == null) { createDummyCtx = true; } } - + if (createDummyCtx) { GraphicsConfigTemplate3D.setQueryProps(this); - } + //create query Properties createQueryProps(); } + + if (fatalError) { + throw new IllegalStateException(J3dI18N.getString("Canvas3D29")); + } + return queryProps; } @@ -3681,7 +3586,7 @@ public class Canvas3D extends Canvas { // extensions, the context will destroy immediately // inside the native code after setting the various // fields in this object - createQueryContext(screen.display, window, vid, + createQueryContext(screen.display, drawable, fbConfig, offScreen, 1, 1, VirtualUniverse.mc.glslLibraryAvailable, VirtualUniverse.mc.cgLibraryAvailable); @@ -3717,8 +3622,13 @@ public class Canvas3D extends Canvas { values.add(new Integer(pass)); keys.add("stencilSize"); - // Return the actual stencil size. - values.add(new Integer(actualStencilSize)); + // Return the actual stencil size if the user owns it, otherwise + // return 0 + if (userStencilAvailable) { + values.add(new Integer(actualStencilSize)); + } else { + values.add(new Integer(0)); + } keys.add("compressedGeometry.majorVersionNumber"); values.add(new Integer(GeometryDecompressor.majorVersionNumber)); @@ -3791,6 +3701,14 @@ public class Canvas3D extends Canvas { values.add(new Boolean( (textureExtendedFeatures & TEXTURE_LOD_OFFSET) != 0)); + keys.add("textureNonPowerOfTwoAvailable"); + if (VirtualUniverse.mc.enforcePowerOfTwo) { + values.add(Boolean.FALSE); + } else { + values.add(new Boolean( + (textureExtendedFeatures & TEXTURE_NON_POWER_OF_TWO) != 0)); + } + keys.add("textureCoordSetsMax"); values.add(new Integer(maxTexCoordSets)); @@ -3831,16 +3749,6 @@ public class Canvas3D extends Canvas { } - // Set internal render mode to one of FIELD_ALL, FIELD_LEFT or - // FIELD_RIGHT. Note that it is up to the caller to ensure that - // stereo is available before setting the mode to FIELD_LEFT or - // FIELD_RIGHT. The boolean isTRUE for double buffered mode, FALSE - // foe single buffering. - native void setRenderMode(long ctx, int mode, boolean doubleBuffer); - - // Set glDepthMask. - native void setDepthBufferWriteEnable(long ctx, boolean mode); - /** * Update the view cache associated with this canvas. */ @@ -3885,7 +3793,7 @@ public class Canvas3D extends Canvas { } - void resetTexture(long ctx, int texUnitIndex) { + void resetTexture(Context ctx, int texUnitIndex) { // D3D also need to reset texture attributes this.resetTextureNative(ctx, texUnitIndex); @@ -3906,7 +3814,6 @@ public class Canvas3D extends Canvas { void resetTextureBin() { Object obj; TextureRetained tex; - DetailTextureImage detailTex; // We don't use rdr.objectId for background texture in D3D // so there is no need to handle rdr.objectId @@ -3923,18 +3830,14 @@ public class Canvas3D extends Canvas { if (obj instanceof TextureRetained) { tex = (TextureRetained) obj; tex.resourceCreationMask &= ~canvasBit; - } else { - detailTex = (DetailTextureImage) obj; - for (int i=0; i < detailTex.resourceCreationMask.length; i++) { - detailTex.resourceCreationMask[i] &= ~canvasBit; - } - } + } } } } void d3dResize() { + assert VirtualUniverse.mc.isD3D(); int status = resizeD3DCanvas(ctx); antialiasingSet = false; @@ -3947,6 +3850,7 @@ public class Canvas3D extends Canvas { } void d3dToggle() { + assert VirtualUniverse.mc.isD3D(); int status = toggleFullScreenMode(ctx); antialiasingSet = false; @@ -3957,6 +3861,7 @@ public class Canvas3D extends Canvas { // use by D3D only void notifyD3DPeer(int cmd) { + assert VirtualUniverse.mc.isD3D(); if (active) { if (isRunning) { if ((view != null) && @@ -3969,7 +3874,7 @@ public class Canvas3D extends Canvas { while (isRunningStatus) { MasterControl.threadYield(); } - J3dMessage renderMessage = VirtualUniverse.mc.getMessage(); + J3dMessage renderMessage = new J3dMessage(); renderMessage.threads = J3dThread.RENDER_THREAD; if (cmd == RESIZE) { renderMessage.type = J3dMessage.RESIZE_CANVAS; @@ -4017,8 +3922,6 @@ public class Canvas3D extends Canvas { void reset() { int i; - - byteBuffer = new byte[1]; currentAppear = new AppearanceRetained(); currentMaterial = new MaterialRetained(); viewFrustum = new CachedFrustum(); @@ -4247,12 +4150,20 @@ public class Canvas3D extends Canvas { } } } - - void setModelViewMatrix(long ctx, double[] viewMatrix, Transform3D mTrans) { + + void setProjectionMatrix(Context ctx, Transform3D projTrans) { + this.projTrans = projTrans; + setProjectionMatrix(ctx, projTrans.mat); + } + + void setModelViewMatrix(Context ctx, double[] viewMatrix, Transform3D mTrans) { setModelViewMatrix(ctx, viewMatrix, mTrans.mat); if (!useStereo) { this.modelMatrix = mTrans; } else { + // TODO : This seems wrong to do only for the right eye. + // A possible approach is to invalidate the cache at begin of + // each eye. if (rightStereoPass) { // Only set cache in right stereo pass, otherwise // if the left stereo pass set the cache value, @@ -4294,41 +4205,17 @@ public class Canvas3D extends Canvas { } } - // Create the texture unit state map - void createTexUnitStateMap() { - // Create the texture unit state map array, which is a mapping from - // texture unit state to the actual underlying texture unit - // NOTE: since this is now required to be a 1-to-1 mapping, we will - // initialize it as such - - texUnitStateMap = new int[maxAvailableTextureUnits]; - for (int t = 0; t < maxAvailableTextureUnits; t++) { - texUnitStateMap[t] = t; - } - } - - // update the underlying layer of the current texture unit state map - void updateTexUnitStateMap() { - updateTexUnitStateMap(ctx, numActiveTexUnit, texUnitStateMap); - } - boolean supportGlobalAlpha() { return ((extensionsSupported & SUN_GLOBAL_ALPHA) != 0); } - boolean supportVideoResize() { - return ((extensionsSupported & SUN_VIDEO_RESIZE) != 0); - } - - /** enable separate specular color if the functionality - * is availabe for this canvas and it is not overriden by the - * property j3d.disableSeparateSpecular. + /** + * Enable separate specular color if it is not overriden by the + * property j3d.disableSeparateSpecular. */ void enableSeparateSpecularColor() { - if (((extensionsSupported & EXT_SEPARATE_SPECULAR_COLOR) != 0) && - !VirtualUniverse.mc.disableSeparateSpecularColor) { - updateSeparateSpecularColorEnable(ctx, true); - } + boolean enable = !VirtualUniverse.mc.disableSeparateSpecularColor; + updateSeparateSpecularColorEnable(ctx, enable); } final void beginScene() { @@ -4387,12 +4274,12 @@ public class Canvas3D extends Canvas { if ((screen != null) && (screen.renderer != null) && - (ctx != 0)) { + (ctx != null)) { VirtualUniverse.mc.postRequest(MasterControl.FREE_CONTEXT, new Object[]{this, new Long(screen.display), - new Integer(window), - new Long(ctx)}); + drawable, + ctx}); // Fix for Issue 19 // Wait for the context to be freed unless called from // a Behavior or from a Rendering thread @@ -4402,9 +4289,8 @@ public class Canvas3D extends Canvas { while (ctxTimeStamp != 0) { MasterControl.threadYield(); } - } - ctx = 0; + ctx = null; } } @@ -4491,7 +4377,7 @@ public class Canvas3D extends Canvas { /** * update state if neccessary according to the stateUpdatedMask */ - void updateState(int pass, int dirtyBits) { + void updateState( int dirtyBits) { if (stateUpdateMask == 0) @@ -4501,7 +4387,7 @@ public class Canvas3D extends Canvas { if ((stateUpdateMask & (1 << TEXTUREBIN_BIT)) != 0) { ((TextureBin) - curStateToUpdate[TEXTUREBIN_BIT]).updateAttributes(this, pass); + curStateToUpdate[TEXTUREBIN_BIT]).updateAttributes(this); } if ((stateUpdateMask & (1 << RENDERMOLECULE_BIT)) != 0) { @@ -4520,6 +4406,245 @@ public class Canvas3D extends Canvas { stateUpdateMask = 0; } + + // This method updates this Texture2D for raster. + // Note : No multi-texture is not used. + void updateTextureForRaster(Texture2DRetained texture) { + + // Setup texture and texture attributes for texture unit 0. + Pipeline.getPipeline().updateTextureUnitState(ctx, 0, true); + setLastActiveTexUnit(0); + setNumActiveTexUnit(1); + + texture.updateNative(this); + resetTextureAttributes(ctx); + + for(int i=1; i < maxTextureUnits; i++) { + resetTexture(ctx, i); + } + + // set the active texture unit back to 0 + activeTextureUnit(ctx, 0); + + // Force the next textureBin to reload. + canvasDirty |= Canvas3D.TEXTUREBIN_DIRTY | Canvas3D.TEXTUREATTRIBUTES_DIRTY; + } + + void restoreTextureBin() { + + // Need to check TextureBin's shaderBin for null + // TextureBin can get clear() if there isn't any RM under it. + if((textureBin != null) && (textureBin.shaderBin != null)) { + textureBin.updateAttributes(this); + } + } + + void textureFill(RasterRetained raster, Point2d winCoord, + float mapZ, float alpha) { + + int winWidth = canvasViewCache.getCanvasWidth(); + int winHeight = canvasViewCache.getCanvasHeight(); + + int rasterImageWidth = raster.image.width; + int rasterImageHeight = raster.image.height; + + float texMinU = 0, texMinV = 0, texMaxU = 0, texMaxV = 0; + float mapMinX = 0, mapMinY = 0, mapMaxX = 0, mapMaxY = 0; + + Point rasterSrcOffset = new Point(); + raster.getSrcOffset(rasterSrcOffset); + + Dimension rasterSize = new Dimension(); + raster.getSize(rasterSize); + + // System.err.println("rasterSrcOffset " + rasterSrcOffset + " rasterSize " + rasterSize); + + int rasterMinX = rasterSrcOffset.x; + int rasterMaxX = rasterSrcOffset.x + rasterSize.width; + int rasterMinY = rasterSrcOffset.y; + int rasterMaxY = rasterSrcOffset.y + rasterSize.height; + + if ((rasterMinX >= rasterImageWidth) || (rasterMinY >= rasterImageHeight) || + (rasterMaxX <= 0) || (rasterMaxY <= 0)) { + return; + } + + if (rasterMinX < 0) { + rasterMinX = 0; + } + if (rasterMinY < 0) { + rasterMinY = 0; + } + + if (rasterMaxX > rasterImageWidth) { + rasterMaxX = rasterImageWidth; + } + + if (rasterMaxY > rasterImageHeight) { + rasterMaxY = rasterImageHeight; + } + + texMinU = (float) rasterMinX / (float) rasterImageWidth; + texMaxU = (float) rasterMaxX / (float) rasterImageWidth; + mapMinX = (float) winCoord.x / (float) winWidth; + mapMaxX = (float) (winCoord.x + (rasterMaxX - rasterMinX)) / (float) winWidth; + + if (raster.image.isYUp()) { + texMinV = (float) rasterMinY / (float) rasterImageHeight; + texMaxV = (float) rasterMaxY / (float) rasterImageHeight; + } else { + // System.err.println("In yUp is false case"); + texMinV = 1.0f - (float) rasterMaxY / (float) rasterImageHeight; + texMaxV = 1.0f - (float) rasterMinY / (float) rasterImageHeight; + } + + mapMinY = 1.0f - ((float) (winCoord.y + (rasterMaxY - rasterMinY)) / (float) winHeight); + mapMaxY = 1.0f - ((float) winCoord.y / (float) winHeight); + + textureFillRaster(ctx, texMinU, texMaxU, texMinV, texMaxV, + mapMinX, mapMaxX, mapMinY, mapMaxY, mapZ, alpha); + + } + + void textureFill(BackgroundRetained bg, int winWidth, int winHeight) { + + ImageComponentRetained.ImageData imageData = + bg.image.getImageData(bg.texture.isUseAsRaster()); + + int maxX = imageData.getWidth(); + int maxY = imageData.getHeight(); + int width = bg.image.width; + int height = bg.image.height; + + float xzoom = (float)winWidth / maxX; + float yzoom = (float)winHeight / maxY; + float zoom = 0; + float texMinU = 0, texMinV = 0, texMaxU = 0, texMaxV = 0, adjustV = 0; + float mapMinX = 0, mapMinY = 0, mapMaxX = 0, mapMaxY = 0; + float halfWidth = 0, halfHeight = 0; + int i = 0, j = 0; + switch (bg.imageScaleMode) { + case Background.SCALE_NONE: + texMinU = 0.0f; + texMinV = 0.0f; + texMaxU = 1.0f; + texMaxV = 1.0f; + halfWidth = (float)winWidth/2.0f; + halfHeight = (float)winHeight/2.0f; + mapMinX = (float) ((0 - halfWidth)/halfWidth); + mapMinY = (float) ((0 - halfHeight)/halfHeight); + mapMaxX = (float) ((maxX - halfWidth)/halfWidth); + mapMaxY = (float) ((maxY - halfHeight)/halfHeight); + adjustV = ((float)winHeight - (float)maxY)/halfHeight; + mapMinY += adjustV; + mapMaxY += adjustV; + break; + case Background.SCALE_FIT_MIN: + zoom = Math.min(xzoom, yzoom); + texMinU = 0.0f; + texMinV = 0.0f; + texMaxU = 1.0f; + texMaxV = 1.0f; + mapMinX = -1.0f; + mapMaxY = 1.0f; + if (xzoom < yzoom) { + mapMaxX = 1.0f; + mapMinY = -1.0f + 2.0f * ( 1.0f - zoom * (float)maxY/(float) winHeight ); + } else { + mapMaxX = -1.0f + zoom * (float)maxX/winWidth * 2; + mapMinY = -1.0f; + } + break; + case Background.SCALE_FIT_MAX: + zoom = Math.max(xzoom, yzoom); + mapMinX = -1.0f; + mapMinY = -1.0f; + mapMaxX = 1.0f; + mapMaxY = 1.0f; + if (xzoom < yzoom) { + texMinU = 0.0f; + texMinV = 0.0f; + texMaxU = (float)winWidth/maxX/zoom; + texMaxV = 1.0f; + } else { + texMinU = 0.0f; + texMinV = 1.0f - (float)winHeight/maxY/zoom; + texMaxU = 1.0f; + texMaxV = 1.0f; + } + break; + case Background.SCALE_FIT_ALL: + texMinU = 0.0f; + texMinV = 0.0f; + texMaxU = 1.0f; + texMaxV = 1.0f; + mapMinX = -1.0f; + mapMinY = -1.0f; + mapMaxX = 1.0f; + mapMaxY = 1.0f; + break; + case Background.SCALE_REPEAT: + i = winWidth/width; + j = winHeight/height; + texMinU = 0.0f; + texMinV = (float)(j + 1) - yzoom; + texMaxU = xzoom; + texMaxV = (float)(j + 1); + mapMinX = -1.0f; + mapMinY = -1.0f; + mapMaxX = 1.0f; + mapMaxY = 1.0f; + break; + case Background.SCALE_NONE_CENTER: + // TODO : Why is there a zoom ? + if(xzoom >= 1.0f){ + texMinU = 0.0f; + texMaxU = 1.0f; + mapMinX = -(float)maxX/winWidth; + mapMaxX = (float)maxX/winWidth; + } else { + texMinU = 0.5f - (float)winWidth/maxX/2; + texMaxU = 0.5f + (float)winWidth/maxX/2; + mapMinX = -1.0f; + mapMaxX = 1.0f; + } + if (yzoom >= 1.0f) { + texMinV = 0.0f; + texMaxV = 1.0f; + mapMinY = -(float)maxY/winHeight; + mapMaxY = (float)maxY/winHeight; + } else { + texMinV = 0.5f - (float)winHeight/maxY/2; + texMaxV = 0.5f + (float)winHeight/maxY/2; + mapMinY = -1.0f; + mapMaxY = 1.0f; + } + break; + } + + textureFillBackground(ctx, texMinU, texMaxU, texMinV, texMaxV, + mapMinX, mapMaxX, mapMinY, mapMaxY); + + } + + + void clear(BackgroundRetained bg, int winWidth, int winHeight) { + + clear( ctx, bg.color.x, bg.color.y, bg.color.z); + + // TODO : This is a bug on not mirror bg. Will fix this as a bug after 1.5 beta. + // For now, as a workaround, we will check bg.image and bg.image.imageData not null. + if((bg.image != null) && (bg.image.imageData != null)) { + // setup Texture pipe. + updateTextureForRaster(bg.texture); + + textureFill(bg, winWidth, winHeight); + + // Restore texture pipe. + restoreTextureBin(); + } + } + /** * obj is either TextureRetained or DetailTextureImage * if obj is DetailTextureImage then we just clear @@ -4554,7 +4679,7 @@ public class Canvas3D extends Canvas { } // handle free resource in the FreeList - void freeResourcesInFreeList(long ctx) { + void freeResourcesInFreeList(Context ctx) { Iterator it; ArrayList list; int i, val; @@ -4573,64 +4698,61 @@ public class Canvas3D extends Canvas { displayListResourceFreeList.clear(); } - if (textureIdResourceFreeList.size() > 0) { - for (it = textureIdResourceFreeList.iterator(); it.hasNext();) { - val = ((Integer) it.next()).intValue(); - if (val <= 0) { - continue; - } - if (val >= textureIDResourceTable.size()) { - System.out.println("Error in freeResourcesInFreeList : ResourceIDTableSize = " + - textureIDResourceTable.size() + - " val = " + val); - } else { - textureIDResourceTable.set(val, null); - } - freeTexture(ctx, val); - } - textureIdResourceFreeList.clear(); - } + if (textureIdResourceFreeList.size() > 0) { + for (it = textureIdResourceFreeList.iterator(); it.hasNext();) { + val = ((Integer) it.next()).intValue(); + if (val <= 0) { + continue; + } + if (val >= textureIDResourceTable.size()) { + System.out.println("Error in freeResourcesInFreeList : ResourceIDTableSize = " + + textureIDResourceTable.size() + + " val = " + val); + } else { + Object obj = textureIDResourceTable.get(val); + if (obj instanceof TextureRetained) { + TextureRetained tex = (TextureRetained) obj; + synchronized (tex.resourceLock) { + tex.resourceCreationMask &= ~canvasBit; + if (tex.resourceCreationMask == 0) { + tex.freeTextureId(val); + } + } + } + + textureIDResourceTable.set(val, null); + } + freeTexture(ctx, val); + } + textureIdResourceFreeList.clear(); + } } void freeContextResources(Renderer rdr, boolean freeBackground, - long ctx) { + Context ctx) { Object obj; TextureRetained tex; - DetailTextureImage detailTex; // Just return if we don't have a valid renderer or context - if (rdr == null || ctx == 0) { + if (rdr == null || ctx == null) { return; } if (freeBackground) { - // Free Background Texture - // Note that we use non-shared ctx to create - // it so there is no need to do so in - // Renderer.freeContextResources() - if (rdr.objectId > 0) { - freeTexture(ctx, rdr.objectId); - VirtualUniverse.mc.freeTexture2DId(rdr.objectId); - rdr.objectId = -1; - - } - // Free Graphics2D Texture - if ((graphics2D != null) && - (graphics2D.objectId != -1)) { - freeTexture(ctx, graphics2D.objectId); - VirtualUniverse.mc.freeTexture2DId(graphics2D.objectId); - graphics2D.objectId = -1; - } + // Dispose of Graphics2D Texture + if (graphics2D != null) { + graphics2D.dispose(); + } } - for (int id = textureIDResourceTable.size()-1; id > 0; id--) { obj = textureIDResourceTable.get(id); if (obj == null) { continue; } + assert id == ((TextureRetained)obj).objectId; freeTexture(ctx, id); if (obj instanceof TextureRetained) { tex = (TextureRetained) obj; @@ -4641,19 +4763,16 @@ public class Canvas3D extends Canvas { tex.freeTextureId(id); } } - } else if (obj instanceof DetailTextureImage) { - detailTex = ((DetailTextureImage) obj); - detailTex.freeDetailTextureId(id, canvasBit); } } textureIDResourceTable.clear(); - freeAllDisplayListResources(); + freeAllDisplayListResources(ctx); } - void freeAllDisplayListResources() { + void freeAllDisplayListResources(Context ctx) { if ((view != null) && (view.renderBin != null)) { - view.renderBin.freeAllDisplayListResources(this); + view.renderBin.freeAllDisplayListResources(this, ctx); if (useSharedCtx) { // We need to rebuild all other Canvas3D resource // shared by this Canvas3D. Since we didn't @@ -4665,4 +4784,383 @@ public class Canvas3D extends Canvas { } } + + + // ***************************************************************** + // Wrappers for native methods go below here + // ***************************************************************** + + // This is the native method for creating the underlying graphics context. + private Context createNewContext(long display, Drawable drawable, + long fbConfig, Context shareCtx, boolean isSharedCtx, + boolean offScreen, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + return Pipeline.getPipeline().createNewContext(this, display, drawable, + fbConfig, shareCtx, isSharedCtx, + offScreen, + glslLibraryAvailable, + cgLibraryAvailable); + } + + private void createQueryContext(long display, Drawable drawable, + long fbConfig, boolean offScreen, int width, int height, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + Pipeline.getPipeline().createQueryContext(this, display, drawable, + fbConfig, offScreen, width, height, + glslLibraryAvailable, + cgLibraryAvailable); + } + + // This is the native for creating offscreen buffer + Drawable createOffScreenBuffer(Context ctx, long display, long fbConfig, int width, int height) { + return Pipeline.getPipeline().createOffScreenBuffer(this, + ctx, display, fbConfig, width, height); + } + + void destroyOffScreenBuffer(Context ctx, long display, long fbConfig, Drawable drawable) { + assert drawable != null; + Pipeline.getPipeline().destroyOffScreenBuffer(this, ctx, display, fbConfig, drawable); + } + + // This is the native for reading the image from the offscreen buffer + private void readOffScreenBuffer(Context ctx, int format, int type, Object data, int width, int height) { + Pipeline.getPipeline().readOffScreenBuffer(this, ctx, format, type, data, width, height); + } + + // The native method for swapBuffers + int swapBuffers(Context ctx, long dpy, Drawable drawable) { + return Pipeline.getPipeline().swapBuffers(this, ctx, dpy, drawable); + } + + // notify D3D that Canvas is resize + private int resizeD3DCanvas(Context ctx) { + return Pipeline.getPipeline().resizeD3DCanvas(this, ctx); + } + + // notify D3D to toggle between FullScreen and window mode + private int toggleFullScreenMode(Context ctx) { + return Pipeline.getPipeline().toggleFullScreenMode(this, ctx); + } + + // ----------------------------------------------------------------------------- + + // native method for setting Material when no material is present + void updateMaterial(Context ctx, float r, float g, float b, float a) { + Pipeline.getPipeline().updateMaterialColor(ctx, r, g, b, a); + } + + static void destroyContext(long display, Drawable drawable, Context ctx) { + Pipeline.getPipeline().destroyContext(display, drawable, ctx); + } + + // This is the native method for doing accumulation. + void accum(Context ctx, float value) { + Pipeline.getPipeline().accum(ctx, value); + } + + // This is the native method for doing accumulation return. + void accumReturn(Context ctx) { + Pipeline.getPipeline().accumReturn(ctx); + } + + // This is the native method for clearing the accumulation buffer. + void clearAccum(Context ctx) { + Pipeline.getPipeline().clearAccum(ctx); + } + + // This is the native method for getting the number of lights the underlying + // native library can support. + int getNumCtxLights(Context ctx) { + return Pipeline.getPipeline().getNumCtxLights(ctx); + } + + // Native method for decal 1st child setup + boolean decal1stChildSetup(Context ctx) { + return Pipeline.getPipeline().decal1stChildSetup(ctx); + } + + // Native method for decal nth child setup + void decalNthChildSetup(Context ctx) { + Pipeline.getPipeline().decalNthChildSetup(ctx); + } + + // Native method for decal reset + void decalReset(Context ctx, boolean depthBufferEnable) { + Pipeline.getPipeline().decalReset(ctx, depthBufferEnable); + } + + // Native method for decal reset + void ctxUpdateEyeLightingEnable(Context ctx, boolean localEyeLightingEnable) { + Pipeline.getPipeline().ctxUpdateEyeLightingEnable(ctx, localEyeLightingEnable); + } + + // The following three methods are used in multi-pass case + + // native method for setting blend color + void setBlendColor(Context ctx, float red, float green, + float blue, float alpha) { + Pipeline.getPipeline().setBlendColor(ctx, red, green, + blue, alpha); + } + + // native method for setting blend func + void setBlendFunc(Context ctx, int src, int dst) { + Pipeline.getPipeline().setBlendFunc(ctx, src, dst); + } + + // native method for setting fog enable flag + void setFogEnableFlag(Context ctx, boolean enableFlag) { + Pipeline.getPipeline().setFogEnableFlag(ctx, enableFlag); + } + + // Setup the full scene antialising in D3D and ogl when GL_ARB_multisamle supported + void setFullSceneAntialiasing(Context ctx, boolean enable) { + Pipeline.getPipeline().setFullSceneAntialiasing(ctx, enable); + } + + void setGlobalAlpha(Context ctx, float alpha) { + Pipeline.getPipeline().setGlobalAlpha(ctx, alpha); + } + + // Native method to update separate specular color control + void updateSeparateSpecularColorEnable(Context ctx, boolean control) { + Pipeline.getPipeline().updateSeparateSpecularColorEnable(ctx, control); + } + + // Initialization for D3D when scene begin + private void beginScene(Context ctx) { + Pipeline.getPipeline().beginScene(ctx); + } + private void endScene(Context ctx) { + Pipeline.getPipeline().endScene(ctx); + } + + // True under Solaris, + // False under windows when display mode <= 8 bit + private boolean validGraphicsMode() { + return Pipeline.getPipeline().validGraphicsMode(); + } + + // native method for setting light enables + void setLightEnables(Context ctx, long enableMask, int maxLights) { + Pipeline.getPipeline().setLightEnables(ctx, enableMask, maxLights); + } + + // native method for setting scene ambient + void setSceneAmbient(Context ctx, float red, float green, float blue) { + Pipeline.getPipeline().setSceneAmbient(ctx, red, green, blue); + } + + // native method for disabling fog + void disableFog(Context ctx) { + Pipeline.getPipeline().disableFog(ctx); + } + + // native method for disabling modelClip + void disableModelClip(Context ctx) { + Pipeline.getPipeline().disableModelClip(ctx); + } + + // native method for setting default RenderingAttributes + void resetRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride) { + Pipeline.getPipeline().resetRenderingAttributes(ctx, + depthBufferWriteEnableOverride, + depthBufferEnableOverride); + } + + // native method for setting default texture + void resetTextureNative(Context ctx, int texUnitIndex) { + Pipeline.getPipeline().resetTextureNative(ctx, texUnitIndex); + } + + // native method for activating a particular texture unit + void activeTextureUnit(Context ctx, int texUnitIndex) { + Pipeline.getPipeline().activeTextureUnit(ctx, texUnitIndex); + } + + // native method for setting default TexCoordGeneration + void resetTexCoordGeneration(Context ctx) { + Pipeline.getPipeline().resetTexCoordGeneration(ctx); + } + + // native method for setting default TextureAttributes + void resetTextureAttributes(Context ctx) { + Pipeline.getPipeline().resetTextureAttributes(ctx); + } + + // native method for setting default PolygonAttributes + void resetPolygonAttributes(Context ctx) { + Pipeline.getPipeline().resetPolygonAttributes(ctx); + } + + // native method for setting default LineAttributes + void resetLineAttributes(Context ctx) { + Pipeline.getPipeline().resetLineAttributes(ctx); + } + + // native method for setting default PointAttributes + void resetPointAttributes(Context ctx) { + Pipeline.getPipeline().resetPointAttributes(ctx); + } + + // native method for setting default TransparencyAttributes + void resetTransparency(Context ctx, int geometryType, + int polygonMode, boolean lineAA, + boolean pointAA) { + Pipeline.getPipeline().resetTransparency(ctx, geometryType, + polygonMode, lineAA, + pointAA); + } + + // native method for setting default ColoringAttributes + void resetColoringAttributes(Context ctx, + float r, float g, + float b, float a, + boolean enableLight) { + Pipeline.getPipeline().resetColoringAttributes(ctx, + r, g, + b, a, + enableLight); + } + + /** + * This native method makes sure that the rendering for this canvas + * gets done now. + */ + void syncRender(Context ctx, boolean wait) { + Pipeline.getPipeline().syncRender(ctx, wait); + } + + // The native method that sets this ctx to be the current one + static boolean useCtx(Context ctx, long display, Drawable drawable) { + return Pipeline.getPipeline().useCtx(ctx, display, drawable); + } + + // Give the Pipeline a chance to release the context. The return + // value indicates whether the context was released. + private boolean releaseCtx(Context ctx, long dpy) { + return Pipeline.getPipeline().releaseCtx(ctx, dpy); + } + + void clear(Context ctx, float r, float g, float b) { + Pipeline.getPipeline().clear(ctx, r, g, b); + } + + void textureFillBackground(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY) { + Pipeline.getPipeline().textureFillBackground(ctx, texMinU, texMaxU, texMinV, texMaxV, + mapMinX, mapMaxX, mapMinY, mapMaxY); + } + + void textureFillRaster(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY, float mapZ, float alpha) { + Pipeline.getPipeline().textureFillRaster(ctx, texMinU, texMaxU, texMinV, texMaxV, + mapMinX, mapMaxX, mapMinY, mapMaxY, mapZ, alpha); + } + + void executeRasterDepth(Context ctx, float posX, float posY, float posZ, + int srcOffsetX, int srcOffsetY, int rasterWidth, int rasterHeight, + int depthWidth, int depthHeight, int depthType, Object depthData) { + Pipeline.getPipeline().executeRasterDepth(ctx, posX, posY, posZ, + srcOffsetX, srcOffsetY, rasterWidth, rasterHeight, depthWidth, depthHeight, depthType, depthData); + } + + // The native method for setting the ModelView matrix. + void setModelViewMatrix(Context ctx, double[] viewMatrix, double[] modelMatrix) { + Pipeline.getPipeline().setModelViewMatrix(ctx, viewMatrix, modelMatrix); + } + + // The native method for setting the Projection matrix. + void setProjectionMatrix(Context ctx, double[] projMatrix) { + Pipeline.getPipeline().setProjectionMatrix(ctx, projMatrix); + } + + // The native method for setting the Viewport. + void setViewport(Context ctx, int x, int y, int width, int height) { + Pipeline.getPipeline().setViewport(ctx, x, y, width, height); + } + + // used for display Lists + void newDisplayList(Context ctx, int displayListId) { + Pipeline.getPipeline().newDisplayList(ctx, displayListId); + } + void endDisplayList(Context ctx) { + Pipeline.getPipeline().endDisplayList(ctx); + } + void callDisplayList(Context ctx, int id, boolean isNonUniformScale) { + Pipeline.getPipeline().callDisplayList(ctx, id, isNonUniformScale); + } + + static void freeDisplayList(Context ctx, int id) { + Pipeline.getPipeline().freeDisplayList(ctx, id); + } + static void freeTexture(Context ctx, int id) { + Pipeline.getPipeline().freeTexture(ctx, id); + } + + void texturemapping(Context ctx, + int px, int py, + int xmin, int ymin, int xmax, int ymax, + int texWidth, int texHeight, + int rasWidth, + int format, int objectId, + byte[] image, + int winWidth, int winHeight) { + Pipeline.getPipeline().texturemapping(ctx, + px, py, + xmin, ymin, xmax, ymax, + texWidth, texHeight, + rasWidth, + format, objectId, + image, + winWidth, winHeight); + } + + boolean initTexturemapping(Context ctx, int texWidth, + int texHeight, int objectId) { + return Pipeline.getPipeline().initTexturemapping(ctx, texWidth, + texHeight, objectId); + } + + + // Set internal render mode to one of FIELD_ALL, FIELD_LEFT or + // FIELD_RIGHT. Note that it is up to the caller to ensure that + // stereo is available before setting the mode to FIELD_LEFT or + // FIELD_RIGHT. The boolean isTRUE for double buffered mode, FALSE + // foe single buffering. + void setRenderMode(Context ctx, int mode, boolean doubleBuffer) { + Pipeline.getPipeline().setRenderMode(ctx, mode, doubleBuffer); + } + + // Set glDepthMask. + void setDepthBufferWriteEnable(Context ctx, boolean mode) { + Pipeline.getPipeline().setDepthBufferWriteEnable(ctx, mode); + } + + // Methods to get actual capabilities from Canvas3D + + boolean hasDoubleBuffer() { + return Pipeline.getPipeline().hasDoubleBuffer(this); + } + + boolean hasStereo() { + return Pipeline.getPipeline().hasStereo(this); + } + + int getStencilSize() { + return Pipeline.getPipeline().getStencilSize(this); + } + + boolean hasSceneAntialiasingMultisample() { + return Pipeline.getPipeline().hasSceneAntialiasingMultisample(this); + } + + boolean hasSceneAntialiasingAccum() { + return Pipeline.getPipeline().hasSceneAntialiasingAccum(this); + } + } diff --git a/src/classes/share/javax/media/j3d/CanvasViewCache.java b/src/classes/share/javax/media/j3d/CanvasViewCache.java index 53e2b58..935dbb2 100644 --- a/src/classes/share/javax/media/j3d/CanvasViewCache.java +++ b/src/classes/share/javax/media/j3d/CanvasViewCache.java @@ -434,7 +434,8 @@ class CanvasViewCache extends Object { // XXXX: Peeking at the dirty flag is a hack. Need to revisit this. boolean vprNotDirty = (viewCache.vpRetained.vprDirtyMask == 0); - if(!canvas.offScreen && + // Issue 131: If not manual, it has to be considered as an onscreen canvas. + if(!canvas.manualRendering && (vprNotDirty) && (cvcDirtyMask == 0) && (scrvcDirtyMask == 0) && diff --git a/src/classes/share/javax/media/j3d/CgShaderProgramRetained.java b/src/classes/share/javax/media/j3d/CgShaderProgramRetained.java index 0eceed3..90893b1 100644 --- a/src/classes/share/javax/media/j3d/CgShaderProgramRetained.java +++ b/src/classes/share/javax/media/j3d/CgShaderProgramRetained.java @@ -35,138 +35,250 @@ class CgShaderProgramRetained extends ShaderProgramRetained { initMirrorObject(); } - // ShaderAttributeValue methods + // ShaderAttributeValue methods - native ShaderError setUniform1i(long ctx, - long shaderProgramId, - long uniformLocation, - int value); - - native ShaderError setUniform1f(long ctx, - long shaderProgramId, - long uniformLocation, - float value); - - native ShaderError setUniform2i(long ctx, - long shaderProgramId, - long uniformLocation, - int[] value); - - native ShaderError setUniform2f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); - - native ShaderError setUniform3i(long ctx, - long shaderProgramId, - long uniformLocation, - int[] value); - - native ShaderError setUniform3f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); - - native ShaderError setUniform4i(long ctx, - long shaderProgramId, - long uniformLocation, - int[] value); - - native ShaderError setUniform4f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); - - native ShaderError setUniformMatrix3f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); + ShaderError setUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value) { + + return Pipeline.getPipeline().setCgUniform1i(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value) { + + return Pipeline.getPipeline().setCgUniform1f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + + return Pipeline.getPipeline().setCgUniform2i(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setCgUniform2f(ctx, + shaderProgramId, + uniformLocation, + value); + } - native ShaderError setUniformMatrix4f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); + ShaderError setUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + + return Pipeline.getPipeline().setCgUniform3i(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setCgUniform3f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + + return Pipeline.getPipeline().setCgUniform4i(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setCgUniform4f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setCgUniformMatrix3f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setCgUniformMatrix4f(ctx, + shaderProgramId, + uniformLocation, + value); + } // ShaderAttributeArray methods - native ShaderError setUniform1iArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - int[] value); - - native ShaderError setUniform1fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniform2iArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - int[] value); - - native ShaderError setUniform2fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniform3iArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - int[] value); - - native ShaderError setUniform3fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniform4iArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - int[] value); - - native ShaderError setUniform4fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniformMatrix3fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); + ShaderError setUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { - native ShaderError setUniformMatrix4fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); + return Pipeline.getPipeline().setCgUniform1iArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + ShaderError setUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setCgUniform1fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + + return Pipeline.getPipeline().setCgUniform2iArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setCgUniform2fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + + return Pipeline.getPipeline().setCgUniform3iArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setCgUniform3fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + + return Pipeline.getPipeline().setCgUniform4iArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setCgUniform4fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setCgUniformMatrix3fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setCgUniformMatrix4fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } - - /* New native interfaces */ - private native ShaderError createNativeShader(long ctx, int shaderType, long[] shaderId); - private native ShaderError destroyNativeShader(long ctx, long shaderId); - private native ShaderError compileNativeShader(long ctx, long shaderId, String program); - - private native ShaderError createNativeShaderProgram(long ctx, long[] shaderProgramId); - private native ShaderError destroyNativeShaderProgram(long ctx, long shaderProgramId); - private native ShaderError linkNativeShaderProgram(long ctx, long shaderProgramId, - long[] shaderId); - private native void lookupNativeVertexAttrNames(long ctx, long shaderProgramId, - int numAttrNames, String[] attrNames, boolean[] errArr); - private native void lookupNativeShaderAttrNames(long ctx, long shaderProgramId, - int numAttrNames, String[] attrNames, long[] locArr, - int[] typeArr, int[] sizeArr, boolean[] isArrayArr); - - private native ShaderError useShaderProgram(long ctx, long shaderProgramId); /** * Method to return a flag indicating whether this @@ -179,70 +291,65 @@ class CgShaderProgramRetained extends ShaderProgramRetained { /** * Method to create the native shader. */ - ShaderError createShader(long ctx, ShaderRetained shader, long[] shaderIdArr) { - return createNativeShader(ctx, shader.shaderType, shaderIdArr); + ShaderError createShader(Context ctx, ShaderRetained shader, ShaderId[] shaderIdArr) { + return Pipeline.getPipeline().createCgShader(ctx, shader.shaderType, shaderIdArr); } /** * Method to destroy the native shader. */ - ShaderError destroyShader(long ctx, long shaderId) { - return destroyNativeShader(ctx, shaderId); + ShaderError destroyShader(Context ctx, ShaderId shaderId) { + return Pipeline.getPipeline().destroyCgShader(ctx, shaderId); } /** * Method to compile the native shader. */ - ShaderError compileShader(long ctx, long shaderId, String source) { - return compileNativeShader(ctx, shaderId, source ); + ShaderError compileShader(Context ctx, ShaderId shaderId, String source) { + return Pipeline.getPipeline().compileCgShader(ctx, shaderId, source ); } /** * Method to create the native shader program. */ - ShaderError createShaderProgram(long ctx, long[] shaderProgramIdArr) { - return createNativeShaderProgram(ctx, shaderProgramIdArr); + ShaderError createShaderProgram(Context ctx, ShaderProgramId[] shaderProgramIdArr) { + return Pipeline.getPipeline().createCgShaderProgram(ctx, shaderProgramIdArr); } /** * Method to destroy the native shader program. */ - ShaderError destroyShaderProgram(long ctx, long shaderProgramId) { - return destroyNativeShaderProgram(ctx, shaderProgramId); + ShaderError destroyShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return Pipeline.getPipeline().destroyCgShaderProgram(ctx, shaderProgramId); } /** * Method to link the native shader program. */ - ShaderError linkShaderProgram(long ctx, long shaderProgramId, long[] shaderIds) { - return linkNativeShaderProgram(ctx, shaderProgramId, shaderIds); + ShaderError linkShaderProgram(Context ctx, ShaderProgramId shaderProgramId, ShaderId[] shaderIds) { + return Pipeline.getPipeline().linkCgShaderProgram(ctx, shaderProgramId, shaderIds); } - ShaderError bindVertexAttrName(long ctx, long shaderProgramId, String attrName, int attrIndex) { + ShaderError bindVertexAttrName(Context ctx, ShaderProgramId shaderProgramId, String attrName, int attrIndex) { // This is a no-op for Cg return null; } - void lookupVertexAttrNames(long ctx, long shaderProgramId, String[] attrNames, boolean[] errArr) { - lookupNativeVertexAttrNames(ctx, shaderProgramId, attrNames.length, attrNames, errArr); + void lookupVertexAttrNames(Context ctx, ShaderProgramId shaderProgramId, String[] attrNames, boolean[] errArr) { + Pipeline.getPipeline().lookupCgVertexAttrNames(ctx, shaderProgramId, attrNames.length, attrNames, errArr); } - void lookupShaderAttrNames(long ctx, long shaderProgramId, + void lookupShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, String[] attrNames, AttrNameInfo[] attrNameInfoArr) { int numAttrNames = attrNames.length; - long[] locArr = new long[numAttrNames]; + ShaderAttrLoc[] locArr = new ShaderAttrLoc[numAttrNames]; int[] typeArr = new int[numAttrNames]; int[] sizeArr = new int[numAttrNames]; // currently unused boolean[] isArrayArr = new boolean[numAttrNames]; - // Initialize loc array to -1 (indicating no location) - for (int i = 0; i < numAttrNames; i++) { - locArr[i] = -1; - } - - lookupNativeShaderAttrNames(ctx, shaderProgramId, + Pipeline.getPipeline().lookupCgShaderAttrNames(ctx, shaderProgramId, numAttrNames, attrNames, locArr, typeArr, sizeArr, isArrayArr); for (int i = 0; i < numAttrNames; i++) { @@ -263,15 +370,15 @@ class CgShaderProgramRetained extends ShaderProgramRetained { /** * Method to enable the native shader program. */ - ShaderError enableShaderProgram(long ctx, long shaderProgramId) { - return useShaderProgram(ctx, shaderProgramId); + ShaderError enableShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return Pipeline.getPipeline().useCgShaderProgram(ctx, shaderProgramId); } /** * Method to disable the native shader program. */ - ShaderError disableShaderProgram(long ctx) { - return useShaderProgram(ctx, 0); + ShaderError disableShaderProgram(Context ctx) { + return Pipeline.getPipeline().useCgShaderProgram(ctx, null); } diff --git a/src/classes/share/javax/media/j3d/ClipRetained.java b/src/classes/share/javax/media/j3d/ClipRetained.java index 73a0385..ee18e8b 100644 --- a/src/classes/share/javax/media/j3d/ClipRetained.java +++ b/src/classes/share/javax/media/j3d/ClipRetained.java @@ -361,7 +361,7 @@ class ClipRetained extends LeafRetained { } final void sendMessage(int attrMask, Object attr, Object attr2) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.CLIP_CHANGED; createMessage.universe = universe; diff --git a/src/classes/share/javax/media/j3d/ColoringAttributesRetained.java b/src/classes/share/javax/media/j3d/ColoringAttributesRetained.java index 4507f9c..d21e01d 100644 --- a/src/classes/share/javax/media/j3d/ColoringAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/ColoringAttributesRetained.java @@ -141,22 +141,14 @@ class ColoringAttributesRetained extends NodeComponentRetained { ((ColoringAttributesRetained) mirror).set(this); } } - /** - * These two native methods update the native context - */ - native void updateNative(long ctx, - float dRed, float dGreen, float dBlue, - float red, float green, float blue, - float alpha, - boolean lEnable, - int shadeModel); - - void updateNative(long ctx, + + void updateNative(Context ctx, float dRed, float dGreen, float dBlue, float alpha, boolean lEnable) { - updateNative(ctx, dRed, dBlue, dGreen, color.x, color.y, - color.z, alpha, - lEnable, shadeModel); + Pipeline.getPipeline().updateColoringAttributes(ctx, + dRed, dBlue, dGreen, color.x, color.y, + color.z, alpha, + lEnable, shadeModel); } /** @@ -213,7 +205,7 @@ class ColoringAttributesRetained extends NodeComponentRetained { ArrayList gaList = Shape3DRetained.getGeomAtomsList(mirror.users, univList); // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.COLORINGATTRIBUTES_CHANGED; createMessage.universe = null; @@ -226,7 +218,7 @@ class ColoringAttributesRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.COLORINGATTRIBUTES_CHANGED; diff --git a/src/classes/share/javax/media/j3d/CompressedGeometryRenderMethod.java b/src/classes/share/javax/media/j3d/CompressedGeometryRenderMethod.java index 64a72ce..3e53c20 100644 --- a/src/classes/share/javax/media/j3d/CompressedGeometryRenderMethod.java +++ b/src/classes/share/javax/media/j3d/CompressedGeometryRenderMethod.java @@ -22,14 +22,13 @@ class CompressedGeometryRenderMethod implements RenderMethod { /** * The actual rendering code for this RenderMethod. */ - public boolean render(RenderMolecule rm, Canvas3D cv, int pass, + public boolean render(RenderMolecule rm, Canvas3D cv, RenderAtomListInfo ra, int dirtyBits) { CompressedGeometryRetained cgr ; - if (rm.doInfinite) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); while (ra != null) { renderCompressedGeo(ra, rm, cv); ra = ra.next; @@ -42,7 +41,7 @@ class CompressedGeometryRenderMethod implements RenderMethod { while (ra != null) { if (cv.ra == ra.renderAtom) { if (cv.raIsVisible) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); renderCompressedGeo(ra, rm, cv); isVisible = true; } @@ -50,7 +49,7 @@ class CompressedGeometryRenderMethod implements RenderMethod { else { if (!VirtualUniverse.mc.viewFrustumCulling || ra.renderAtom.localeVwcBounds.intersect(cv.viewFrustum)) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.raIsVisible = true; renderCompressedGeo(ra, rm, cv); isVisible = true; @@ -93,12 +92,9 @@ class CompressedGeometryRenderMethod implements RenderMethod { return ; } - cgr.mirrorGeometry.execute - (cv, ra.renderAtom, rm.isNonUniformScale, + cgr.mirrorGeometry.execute(cv, ra.renderAtom, rm.isNonUniformScale, (useAlpha && ra.geometry().noAlpha), rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, - rm.textureBin.attributeBin.ignoreVertexColors, - -1) ; + rm.textureBin.attributeBin.ignoreVertexColors); } } diff --git a/src/classes/share/javax/media/j3d/CompressedGeometryRetained.java b/src/classes/share/javax/media/j3d/CompressedGeometryRetained.java index fe48f0f..dac05f7 100644 --- a/src/classes/share/javax/media/j3d/CompressedGeometryRetained.java +++ b/src/classes/share/javax/media/j3d/CompressedGeometryRetained.java @@ -84,7 +84,7 @@ class CompressedGeometryRetained extends GeometryRetained { * Formerly native method that returns availability of a native by-reference * rendering API for compressed geometry. */ - private boolean decompressByRef(long ctx) { + private boolean decompressByRef(Context ctx) { return false; } @@ -93,14 +93,14 @@ class CompressedGeometryRetained extends GeometryRetained { * rendering (and acceleration) for compressed geometry of the * given version. */ - private boolean decompressHW(long ctx, int majorVersion, int minorVersion) { + private boolean decompressHW(Context ctx, int majorVersion, int minorVersion) { return false; } /** * Formerly native method that does HW compressed geometry rendering */ - private void execute(long ctx, int version, int bufferType, + private void execute(Context ctx, int version, int bufferType, int bufferContents, int renderFlags, int offset, int size, byte[] geometry) { @@ -112,8 +112,7 @@ class CompressedGeometryRetained extends GeometryRetained { */ void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, - boolean multiScreen, int screen, - boolean ignoreVertexColors, int pass) { + int screen, boolean ignoreVertexColors) { // XXXX: alpha udpate execute(cv.ctx, packedVersion, bufferType, bufferContents, diff --git a/src/classes/share/javax/media/j3d/Context.java b/src/classes/share/javax/media/j3d/Context.java new file mode 100644 index 0000000..85ff927 --- /dev/null +++ b/src/classes/share/javax/media/j3d/Context.java @@ -0,0 +1,22 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Tagging interface for graphics context objects. The rendering pipelines + * will define concrete classes that implement this interface. All code that + * uses the tagged objects will be in the pipelines. + */ +interface Context { + // No methods or constants defined at this time +} diff --git a/src/classes/share/javax/media/j3d/DefaultRenderMethod.java b/src/classes/share/javax/media/j3d/DefaultRenderMethod.java index b45d865..4b96d7b 100644 --- a/src/classes/share/javax/media/j3d/DefaultRenderMethod.java +++ b/src/classes/share/javax/media/j3d/DefaultRenderMethod.java @@ -24,23 +24,21 @@ class DefaultRenderMethod implements RenderMethod { /** * The actual rendering code for this RenderMethod */ - public boolean render(RenderMolecule rm, Canvas3D cv, int pass, + public boolean render(RenderMolecule rm, Canvas3D cv, RenderAtomListInfo ra, int dirtyBits) { - + boolean isVisible = false; // True if any of the RAs is visible. while (ra != null) { if (cv.ra == ra.renderAtom) { if (cv.raIsVisible) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); ra.geometry().execute(cv, ra.renderAtom, rm.isNonUniformScale, rm.useAlpha, rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, rm.textureBin.attributeBin. - ignoreVertexColors, - pass); + ignoreVertexColors); isVisible = true; } } @@ -48,14 +46,12 @@ class DefaultRenderMethod implements RenderMethod { if (!VirtualUniverse.mc.viewFrustumCulling || ra.renderAtom.localeVwcBounds.intersect(cv.viewFrustum)) { cv.raIsVisible = true; - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); ra.geometry().execute(cv, ra.renderAtom, rm.isNonUniformScale, rm.useAlpha, rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, rm.textureBin.attributeBin. - ignoreVertexColors, - pass); + ignoreVertexColors); isVisible = true; } else { diff --git a/src/classes/share/javax/media/j3d/DetailTextureImage.java b/src/classes/share/javax/media/j3d/DetailTextureImage.java deleted file mode 100644 index 1c48e23..0000000 --- a/src/classes/share/javax/media/j3d/DetailTextureImage.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -package javax.media.j3d; - -import javax.vecmath.*; -import java.util.*; - - -class DetailTextureImage extends Object { - - final static int NFORMAT = 7; // number of texture format - - int objectIds[]; // texture object id, one per format - int refCount[]; // texture bin reference count, - // to keep track of if the texture - // object id is still being referenced - // by an active texture. If it - // goes to 0 for a particular format, - // the associated texture object - // will be destroyed. - - int resourceCreationMask[]; // one creation mask per format - - ImageComponent2DRetained image = null; // the image itself - - Object resourceLock = new Object(); - - DetailTextureImage(ImageComponent2DRetained img) { - image = img; - } - - native void bindTexture(long ctx, int objectId); - - native void updateTextureImage(long ctx, - int numLevels, int level, - int format, int storedFormat, - int width, int height, - int boundaryWidth, byte[] data); - - - synchronized void incTextureBinRefCount(int format, TextureBin tb) { - if (refCount == null) { - refCount = new int[NFORMAT]; - } - if (resourceCreationMask == null) { - resourceCreationMask = new int[NFORMAT]; - } - refCount[format]++; - - if (image != null && - (image.isByReference() || - image.source.getCapability(ImageComponent.ALLOW_IMAGE_WRITE))) { - tb.renderBin.addNodeComponent(image); - } - } - - synchronized void decTextureBinRefCount(int format, TextureBin tb) { - - if (refCount != null) { - refCount[format]--; - } - if (image != null && - (image.isByReference() || - image.source.getCapability(ImageComponent.ALLOW_IMAGE_WRITE))) { - tb.renderBin.removeNodeComponent(image); - } - } - - - synchronized void freeDetailTextureId(int id, int bitMask) { - synchronized(resourceLock) { - if (objectIds != null) { - for (int i=0; i < resourceCreationMask.length; i++) { - resourceCreationMask[i] &= ~bitMask; - if (resourceCreationMask[i] == 0) { - if (objectIds[i] == id) { - objectIds[i] = -1; - VirtualUniverse.mc.freeTexture2DId(id); - break; - } - } - } - } - - } - } - - synchronized void freeTextureId(int format, int id) { - synchronized(resourceLock) { - if ((objectIds != null) && (objectIds[format] == id)) { - objectIds[format] = -1; - VirtualUniverse.mc.freeTexture2DId(objectIds[format]); - } - } - } - - protected void finalize() { - if (objectIds != null) { - // memory not yet free - // send a message to the request renderer - synchronized (VirtualUniverse.mc.contextCreationLock) { - boolean found = false; - for (int i=0; i < objectIds.length; i++) { - if (objectIds[i] > 0) { - for (Enumeration e = Screen3D.deviceRendererMap.elements(); - e.hasMoreElements(); ) { - Renderer rdr = (Renderer) e.nextElement(); - J3dMessage renderMessage = VirtualUniverse.mc.getMessage(); - renderMessage.threads = J3dThread.RENDER_THREAD; - renderMessage.type = J3dMessage.RENDER_IMMEDIATE; - renderMessage.universe = null; - renderMessage.view = null; - renderMessage.args[0] = null; - renderMessage.args[1] = new Integer(objectIds[i]); - renderMessage.args[2] = "2D"; - rdr.rendererStructure.addMessage(renderMessage); - } - objectIds[i] = -1; - found = true; - } - } - if (found) { - VirtualUniverse.mc.setWorkForRequestRenderer(); - } - } - } - } - - void notifyImageComponentImageChanged(ImageComponentRetained image, - Object value) { - if (resourceCreationMask != null) { - synchronized(resourceLock) { - for (int i = 0; i < NFORMAT; i++) { - resourceCreationMask[i] = 0; - } - } - } - } - - void bindTexture(Canvas3D cv, int format) { - synchronized(resourceLock) { - if (objectIds == null) { - objectIds = new int[NFORMAT]; - for (int i = 0; i < NFORMAT; i++) { - objectIds[i] = -1; - } - } - - if (objectIds[format] == -1) { - objectIds[format] = VirtualUniverse.mc.getTexture2DId(); - } - cv.addTextureResource(objectIds[format], this); - } - - bindTexture(cv.ctx, objectIds[format]); - } - - - void updateNative(Canvas3D cv, int format) { - if ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_DETAIL) == 0) { - return; - } - - boolean reloadTexture = false; - - // bind the detail texture - - bindTexture(cv, format); - - if (cv.useSharedCtx && cv.screen.renderer.sharedCtx != 0) { - if ((resourceCreationMask[format] & cv.screen.renderer.rendererBit) - == 0) { - reloadTexture = true; - cv.makeCtxCurrent(cv.screen.renderer.sharedCtx); - bindTexture(cv, format); - } - } else { - if ((resourceCreationMask[format] & cv.canvasBit) == 0) { - reloadTexture = true; - } - } - - // No D3D support yet - - if (reloadTexture) { - - updateTextureImage(cv.ctx, 1, 0, format, image.storedYupFormat, - image.width, image.height, 0, image.imageYup); - - - // Rendered image - - } - - if (cv.useSharedCtx) { - cv.makeCtxCurrent(cv.ctx); - synchronized(resourceLock) { - resourceCreationMask[format] |= cv.screen.renderer.rendererBit; - } - } else { - synchronized(resourceLock) { - resourceCreationMask[format] |= cv.canvasBit; - } - } - } -} - - - diff --git a/src/classes/share/javax/media/j3d/DirectionalLightRetained.java b/src/classes/share/javax/media/j3d/DirectionalLightRetained.java index 79c7bf6..9c3f681 100644 --- a/src/classes/share/javax/media/j3d/DirectionalLightRetained.java +++ b/src/classes/share/javax/media/j3d/DirectionalLightRetained.java @@ -55,7 +55,7 @@ class DirectionalLightRetained extends LightRetained */ void setDirection(Vector3f direction) { initDirection(direction); - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.LIGHT_CHANGED; createMessage.universe = universe; @@ -168,13 +168,11 @@ class DirectionalLightRetained extends LightRetained } - native void updateLight(long ctx, - int lightSlot, float red, float green, - float blue, float x, float y, float z); - void update(long ctx, int lightSlot, double scale) { - updateLight(ctx, lightSlot, color.x, color.y, color.z, - xformDirection.x, xformDirection.y, - xformDirection.z); + void update(Context ctx, int lightSlot, double scale) { + Pipeline.getPipeline().updateDirectionalLight(ctx, + lightSlot, color.x, color.y, color.z, + xformDirection.x, xformDirection.y, + xformDirection.z); } // Clones only the retained side, internal use only diff --git a/src/classes/share/javax/media/j3d/DisplayListRenderMethod.java b/src/classes/share/javax/media/j3d/DisplayListRenderMethod.java index b452528..d6aeb76 100644 --- a/src/classes/share/javax/media/j3d/DisplayListRenderMethod.java +++ b/src/classes/share/javax/media/j3d/DisplayListRenderMethod.java @@ -29,19 +29,17 @@ class DisplayListRenderMethod implements RenderMethod { */ int[] buffer = new int[bufferSize]; - native void callDisplayLists(int size, int[] buffer); - /** * The actual rendering code for this RenderMethod */ - public boolean render(RenderMolecule rm, Canvas3D cv, int pass, + public boolean render(RenderMolecule rm, Canvas3D cv, RenderAtomListInfo ra, int dirtyBits) { if (rm.doInfinite || !VirtualUniverse.mc.viewFrustumCulling || rm.vwcBounds.intersect(cv.viewFrustum)) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.callDisplayList(cv.ctx, rm.displayListId, rm.isNonUniformScale); return true; @@ -51,11 +49,10 @@ class DisplayListRenderMethod implements RenderMethod { public boolean renderSeparateDlists(RenderMolecule rm, Canvas3D cv, - int pass, RenderAtomListInfo r, int dirtyBits) { if (rm.doInfinite) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); while (r != null) { cv.callDisplayList(cv.ctx, ((GeometryArrayRetained)r.geometry()).dlistId, @@ -70,7 +67,7 @@ class DisplayListRenderMethod implements RenderMethod { while (r != null) { if (cv.ra == r.renderAtom) { if (cv.raIsVisible) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.callDisplayList(cv.ctx, ((GeometryArrayRetained)r.geometry()).dlistId, rm.isNonUniformScale); @@ -79,7 +76,7 @@ class DisplayListRenderMethod implements RenderMethod { } else { if (r.renderAtom.localeVwcBounds.intersect(cv.viewFrustum)) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.raIsVisible = true; cv.callDisplayList(cv.ctx, ((GeometryArrayRetained)r.geometry()).dlistId, @@ -101,12 +98,11 @@ class DisplayListRenderMethod implements RenderMethod { public boolean renderSeparateDlistPerRinfo(RenderMolecule rm, Canvas3D cv, - int pass, RenderAtomListInfo r, int dirtyBits) { if (rm.doInfinite) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); while (r != null) { cv.callDisplayList(cv.ctx,r.renderAtom.dlistIds[r.index], rm.isNonUniformScale); @@ -118,7 +114,7 @@ class DisplayListRenderMethod implements RenderMethod { while (r != null) { if (cv.ra == r.renderAtom) { if (cv.raIsVisible) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.callDisplayList(cv.ctx, r.renderAtom.dlistIds[r.index], rm.isNonUniformScale); isVisible = true; @@ -126,7 +122,7 @@ class DisplayListRenderMethod implements RenderMethod { } else { if (r.renderAtom.localeVwcBounds.intersect(cv.viewFrustum)) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.raIsVisible = true; cv.callDisplayList(cv.ctx, r.renderAtom.dlistIds[r.index], rm.isNonUniformScale); @@ -190,7 +186,7 @@ class DisplayListRenderMethod implements RenderMethod { } void buildIndividualDisplayList(RenderAtomListInfo ra, Canvas3D cv, - long ctx) { + Context ctx) { GeometryArrayRetained geo; geo = (GeometryArrayRetained)ra.geometry(); diff --git a/src/classes/share/javax/media/j3d/DistanceLOD.java b/src/classes/share/javax/media/j3d/DistanceLOD.java index 2598eb8..948558b 100644 --- a/src/classes/share/javax/media/j3d/DistanceLOD.java +++ b/src/classes/share/javax/media/j3d/DistanceLOD.java @@ -177,7 +177,7 @@ public class DistanceLOD extends LOD { double viewDistance = 0.0; int nSwitches,i,index=0; - Transform3D localToWorldTrans = VirtualUniverse.mc.getTransform3D(null); + Transform3D localToWorldTrans = new Transform3D(); localToWorldTrans.set(((NodeRetained)this.retained).getCurrentLocalToVworld()); @@ -220,9 +220,6 @@ public class DistanceLOD extends LOD { sw.setWhichChild(index); } } - - VirtualUniverse.mc.addToTransformFreeList(localToWorldTrans); - // Insert wakeup condition into queue wakeupOn(wakeupFrame); diff --git a/src/classes/share/javax/media/j3d/Drawable.java b/src/classes/share/javax/media/j3d/Drawable.java new file mode 100644 index 0000000..77e9f5a --- /dev/null +++ b/src/classes/share/javax/media/j3d/Drawable.java @@ -0,0 +1,22 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Tagging interface for drawable (window) objects. The rendering pipelines + * will define concrete classes that implement this interface. All code that + * uses the tagged objects will be in the pipelines. + */ +interface Drawable { + // No methods or constants defined at this time +} diff --git a/src/classes/share/javax/media/j3d/DrawingSurfaceObjectAWT.java b/src/classes/share/javax/media/j3d/DrawingSurfaceObjectAWT.java index d4dfa23..71d8167 100644 --- a/src/classes/share/javax/media/j3d/DrawingSurfaceObjectAWT.java +++ b/src/classes/share/javax/media/j3d/DrawingSurfaceObjectAWT.java @@ -21,27 +21,29 @@ import java.awt.Point; class DrawingSurfaceObjectAWT extends DrawingSurfaceObject { // drawing surface - long nativeDS = 0; - long dsi = 0; + private long nativeDS = 0; + private long dsi = 0; - boolean doLastUnlock = false; - boolean xineramaDisabled = false; + private boolean doLastUnlock = false; + private boolean xineramaDisabled = false; - long display = 0; - int screenID = 0; + private long display = 0; + private int screenID = 0; - static long nativeAWT = 0; + private static long nativeAWT = 0; - native boolean lockAWT(long ds); - native void unlockAWT(long ds); - static native void lockGlobal(long awt); - static native void unlockGlobal(long awt); - native long getDrawingSurfaceAWT(Canvas3D cv, long awt); - native long getDrawingSurfaceInfo(long ds); - static native void freeResource(long awt, long ds, long dsi); - native int getDrawingSurfaceWindowIdAWT(Canvas3D cv, long ds, long dsi, - long display, int screenID, - boolean xineramaDisabled); + private native boolean lockAWT(long ds); + private native void unlockAWT(long ds); + private static native void lockGlobal(long awt); + private static native void unlockGlobal(long awt); + private native long getDrawingSurfaceAWT(Canvas3D cv, long awt); + private native long getDrawingSurfaceInfo(long ds); + private static native void freeResource(long awt, long ds, long dsi); + + // TODO: long window + private native int getDrawingSurfaceWindowIdAWT(Canvas3D cv, long ds, long dsi, + long display, int screenID, + boolean xineramaDisabled); DrawingSurfaceObjectAWT(Canvas3D cv, long awt, long display, int screenID, @@ -110,9 +112,10 @@ class DrawingSurfaceObjectAWT extends DrawingSurfaceObject { if (nativeDS != 0) { dsi = getDrawingSurfaceInfo(nativeDS); if (dsi != 0) { - canvas.window = getDrawingSurfaceWindowIdAWT + long nativeDrawable = getDrawingSurfaceWindowIdAWT (canvas, nativeDS, dsi, display, screenID, xineramaDisabled); + canvas.drawable = new NativeDrawable(nativeDrawable); } } } diff --git a/src/classes/share/javax/media/j3d/EnvironmentSet.java b/src/classes/share/javax/media/j3d/EnvironmentSet.java index 200c1ae..35c6cac 100644 --- a/src/classes/share/javax/media/j3d/EnvironmentSet.java +++ b/src/classes/share/javax/media/j3d/EnvironmentSet.java @@ -366,9 +366,6 @@ class EnvironmentSet extends Object implements ObjectUpdate{ a.definingRenderingAttributes = null; a.onUpdateList &= ~AttributeBin.ON_CHANGED_FREQUENT_UPDATE_LIST; - // Add this attributebin to the free list - renderBin.attrBinFreelist.add(a); - if (attributeBinList == null && addAttributeBins.size() == 0) { // Now remove this environment set from all the lights and fogs // that use this diff --git a/src/classes/share/javax/media/j3d/ExceptionStrings.properties b/src/classes/share/javax/media/j3d/ExceptionStrings.properties index b1541ba..8d13787 100644 --- a/src/classes/share/javax/media/j3d/ExceptionStrings.properties +++ b/src/classes/share/javax/media/j3d/ExceptionStrings.properties @@ -42,6 +42,8 @@ Background8=Background: no capability to get application bounds Background9=Background: no capability to set image scale mode Background10=Background: no capability to get image scale mode Background11=Background: illegal image scale mode +Background12=Background: Live Background with an ImageComponent2D that is being used by a Canvas3D as an off-screen buffer. +Background13=Background: In Immediate mode context with an ImageComponent2D that is being used by a Canvas3D as an off-screen buffer. AlternateAppearance0=AlternateAppearance: no capability to write appearance AlternateAppearance2=AlternateAppearance: no capability to read appearance AlternateAppearance3=AlternateAppearance: no capability to write influencing bounds @@ -121,7 +123,7 @@ Canvas3D0=Canvas3D: Cannot swap buffers when the renderer is running Canvas3D1=Canvas3D: Not in off-screen mode Canvas3D2=Canvas3D: Off-screening rendering is in progress Canvas3D3=Canvas3D: The specified ImageComponent2D is used by more than on Canvas3D -Canvas3D7=*** ERROR: Canvas3D constructed with a null GraphicsConfiguration +Canvas3D7=WARNING: Canvas3D constructed with null GraphicsConfiguration; Canvas3D8=Canvas3D: The width of the associated Screen3D's size is <= 0 Canvas3D9=Canvas3D: The height of the associated Screen3D's size is <= 0 Canvas3D10=Canvas3D: Off-screen buffer is null @@ -130,14 +132,19 @@ Canvas3D12=Canvas3D: The physical width of the associated Screen3D is <= 0 Canvas3D13=Canvas3D: The physical height of the associated Screen3D is <= 0 Canvas3D14=Canvas3D: Illegal operation in off-screen mode Canvas3D15=Canvas3D: For offscreen rendering, byReference image should be an instance of BufferedImage -Canvas3D16=Canvas3D: Offscreen rendering does not support FORMAT_CHANNEL8 +Canvas3D16=Canvas3D: Offscreen rendering has to be a 3-component or 4-component format. Canvas3D17=Canvas3D: GraphicsConfiguration is not compatible with Canvas3D -Canvas3D18=*** This will cause a NullPointerException in a subsequent release +Canvas3D18=will attempt to use a default GraphicsConfiguration Canvas3D19=Canvas3D: null GraphicsConfiguration Canvas3D20=Canvas3D does not support serialization -Canvas3D21=*** ERROR: GraphicsConfiguration not created with GraphicsConfigTemplate3D -Canvas3D22=*** This will cause an IllegalArgumentException in a subsequent release Canvas3D23=Unable to get FBConfig from GraphicsConfiguration +Canvas3D24=Canvas3D: Can't force render of offscreen buffer because it is an automatic one. +Canvas3D25=Canvas3D: AutoOffscreenCanvas3D must be used as off-screen Canvas3D. +Canvas3D26=Canvas3D: ImageComponent2D is already part of a live scene graph. +Canvas3D27=Canvas3D: ImageComponent2D is already being used by an immediate mode context. +Canvas3D28=Canvas3D: ImageComponent2D is already being used by by another Canvas3D as an off-screen buffer. +Canvas3D29=Canvas3D: Non-recoverable graphics configuration error +Canvas3D30=Canvas3D: Non-recoverable off-screen rendering error BoundingPolytope0=BoundingPolytope( Bounds) unrecognized bounds object BoundingPolytope1=BoundingPolytope( Bounds) unrecognized bounds type BoundingPolytope2=set( Bounds) unrecognized bounds type @@ -303,6 +310,9 @@ GeometryArray132=GeometryArray: vertexAttrCount != vertexAttrSizes.length GeometryArray133=GeometryArray: vertexAttrSize value out of range GeometryArray134=GeometryArray: vertexAttrSize invalid for this method GeometryArray135=GeometryArray: USE_COORD_INDEX_ONLY bit cannot be set for non-indexed geometry +GeometryArray136=GeometryArray: BY_REFERENCE_INDICES bit can be set only for indexed geometry +GeometryArray137=GeometryArray: BY_REFERENCE_INDICES bit can be set only if BY_REFERENCE bit is also set +GeometryArray138=GeometryArray: BY_REFERENCE_INDICES bit can be set only if USE_COORD_INDEX_ONLY bit is also set GeometryDecompressor0=GeometryDecompressor: start+length > data array size GeometryDecompressor1=GeometryDecompressor: bad delta normal in compressed buffer GeometryDecompressorRetained0=GeometryDecompressorRetained: bad buffer data type @@ -328,6 +338,7 @@ Light8=Light: no capability to read scopes Light9=Light: no capability to append scope Light11=Light: no capability to write influencing bounds Light12=Light: no capability to read influencing bounds +GeometryStripArrayRetained0=Illegal stripVertexCounts GeometryStripArray0=GeometryStripArray: no capability to get number of strips GeometryStripArray1=GeometryStripArray: no capability to get strip vertex counts GeometryStripArray2=GeometryStripArray: no capability to set strip vertex counts @@ -349,16 +360,30 @@ GraphicsContext3D25=ModelClip: Scene Graph ModelClip may not be in immediate mod GraphicsContext3D26=Shape3D: Scene Graph Shape3D may not be in immediate mode GraphicsContext3D27=ImageComponent2D size is smaller than read Raster size GraphicsContext3D28=DepthComponent size is smaller than read Raster size +GraphicsContext3D29=GraphicsContext3D: For readRaster, byReference image should be an instance of BufferedImage +GraphicsContext3D30=GraphicsContext3D: Appearance has an ImageComponent2D used by an OffScreen Canvas3D. +GraphicsContext3D31=GraphicsContext3D: Background's ImageComponent2D is already being used as an OffScreen Canvas3D. +GraphicsContext3D32=GraphicsContext3D: Raster's ImageComponent2D is already being used as an OffScreen Canvas3D. +GraphicsContext3D33=GraphicsContext3D: Raster's ImageComponent2D is not of ImageClass.BUFFERED_IMAGE. +GraphicsContext3D34=GraphicsContext3D: Raster's ImageComponent2D is in by-reference mode and its RenderedImage is null. +GraphicsContext3D35=GraphicsContext3D: Raster's ImageComponent2D format is not a 3-component format or a 4-component format. +GraphicsContext3D36=GraphicsContext3D: Raster and Raster's ImageComponent2D are part of a live scene graph. +GraphicsContext3D37=GraphicsContext3D: Raster's ImageComponent2D is being used by an immediate mode context, or by a Canvas3D as an off-screen buffer. ImageComponent0=ImageComponent: no capability to get width ImageComponent1=ImageComponent: no capability to get height ImageComponent2=ImageComponent: no capability to get format -GeometryStripArrayRetained0=Illegal stripVertexCounts +ImageComponent3=ImageComponent: This image is being used by a Canvas3D as an off-screen buffer. +ImageComponent4=ImageComponent: The image class of this object is ImageClass.NIO_IMAGE_BUFFER. ImageComponent2D0=ImageComponent2D: no capability to get image ImageComponent2D1=ImageComponent2D: no capability to set image ImageComponent2D2=ImageComponent2D: must be in BY_REFERENCE mode to use this method ImageComponent2D3=ImageComponent2D: illegal dimension ImageComponent2D4=ImageComponent2D: must be in BY_COPY mode to use this method ImageComponent2D5=ImageComponent2D: image is not an instanceof of BufferedImage +ImageComponent2D6=ImageComponent2D: type mismatch between sub-image and existing image. +ImageComponent2D7=ImageComponent2D: Nio buffer image must be byReference is true. +ImageComponent2D8=ImageComponent2D: Nio buffer image must be yUp is true. +ImageComponent2D9=ImageComponent2D: The image class is not ImageClass.NIO_IMAGE_BUFFER. ImageComponent3D0=ImageComponent3D: no capability to get depth ImageComponent3D1=ImageComponent3D - incompatible depth ImageComponent3D2=ImageComponent3D - incompatible width @@ -408,6 +433,9 @@ IndexedGeometryArray27=IndexedGeometryArray: index value less than zero IndexedGeometryArray28=IndexedGeometryArray: no capability to set vertex attribute index IndexedGeometryArray29=IndexedGeometryArray: no capability to get vertex attribute index IndexedGeometryArray30=IndexedGeometryArray: index vertexAttr value greater than the array length +IndexedGeometryArray31=IndexedGeometryArray: cannot access indices directly in BY_REFERENCE_INDICES mode +IndexedGeometryArray32=IndexedGeometryArray: can access indices by reference only in BY_REFERENCE_INDICES mode +IndexedGeometryArray33=IndexedGeometryArray: coordIndices array length < initial index index + valid index count IndexedLineArray0=IndexedLineArray: illegal vertexCount IndexedLineArray1=IndexedLineArray: illegal indexCount IndexedGeometryStripArray0=IndexedGeometryStripArray: no capability to get number of strips @@ -490,6 +518,12 @@ MorphRetained5=Invalid SceneGraphPath encountered : localToVworld is null. MorphRetained7=Morph: number of weights not same as number of GeometryArrays MorphRetained8=Morph: sum of all weights is NOT 1.0 MorphRetained9=Morph: vertex attributes are not supported +NioImageBuffer0=NioImageBuffer: image width is not positive +NioImageBuffer1=NioImageBuffer: image height is not positive +NioImageBuffer2=NioImageBuffer: unsupported image type +NioImageBuffer3=NioImageBuffer: NIO buffer limit is incorrect +NioImageBuffer4=NioImageBuffer: NIO buffer type does not match image type +NioImageBuffer5=NioImageBuffer: NIO buffer does not match native byte order of underlying platform Node0=Node: no capability to read parent Node1=Node: no capability to set bounds Node2=Node: no capability to read user bounds @@ -518,6 +552,8 @@ Picking0=Cannot call picking under a SharedGroup node Picking2=Picking: Node has no parent and locale. This is illegal! NodeComponent0=NodeComponent:cloneNodeComponent must be defined in subclass NodeComponent1=Cannot duplicate a Compiled NodeComponent object +NodeComponent2=Live NodeComponent with an ImageComponent2D that is being used by a Canvas3D as an off-screen buffer. +NodeComponent3=In Immediate mode context with an ImageComponent2D that is being used by a Canvas3D as an off-screen buffer. NodeRetained0=Not supported in a Shared Graph NodeRetained1=Only supported in a Shared Graph NodeRetained2=invalid scene graph path @@ -570,6 +606,7 @@ Raster8=Raster: no capability to get offset Raster9=Raster: no capability to set size Raster10=Raster: no capability to set clip mode Raster11=Raster: no capability to get clip mode +Raster12=Raster: Live Raster with an ImageComponent2D that is being used by a Canvas3D as an off-screen buffer. PointArrayRetained0=PickPoint doesn't make sense for geometry-based picking. Java 3D doesn't have spatial information of the surface. Should use PickBounds with BoundingSphere and set radius to a epsilon tolerance. PointAttributes0=PointAttributes: no capability to set point size PointAttributes1=PointAttributes: no capability to get point size @@ -590,6 +627,15 @@ PolygonAttributes12=PolygonAttributes: illegal cull face QuadArray0=QuadArray: illegal vertexCount QuadArrayRetained0=PickPoint doesn't make sense for geometry-based picking. Java 3D doesn't have spatial information of the surface. Should use PickBounds with BoundingSphere and set radius to a epsilon tolerance. PositionPathInterpolator0=PositionPathInterpolator: length of knots and positions must be equal +Renderer0=Renderer: Unexpected RuntimeException caught during buffer swap +Renderer1=Renderer: Error initializing GraphicsConfiguration properties +Renderer2=Renderer: Error creating Canvas3D graphics context for queryProperties() +Renderer3=Renderer: Error in GraphicsConfigTemplate3D.getBestConfiguration() +Renderer4=Renderer: Error in GraphicsConfigTemplate3D.isConfigSupported() +Renderer5=Renderer: Error creating Canvas3D off-screen buffer +Renderer6=Renderer: Error creating immediate mode Canvas3D graphics context +Renderer7=Renderer: Error creating Canvas3D graphics context +Renderer8=Renderer: Unexpected RuntimeException caught during rendering RenderingAttributes0=RenderingAttributes: no capability to set depth buffer mode RenderingAttributes1=RenderingAttributes: no capability to get depth buffer mode RenderingAttributes2=RenderingAttributes: no capability to set depth buffer write mode @@ -748,7 +794,7 @@ Texture26=Texture: no capability to get anisotropic filter information Texture27=Texture: Illegal anisotropic filter degree Texture28=Texture: Illegal minification filter Texture29=Texture: Illegal magnification filter -Texture30=Texture: boundary width < 0 +Texture30=Texture: illegal boundary width Texture31=Texture: illegal boundary mode value Texture32=Texture: no capability to set base level Texture33=Texture: no capability to set maximum level @@ -764,6 +810,8 @@ Texture42=Texture: minimumLOD > maximumLOD Texture43=Texture: maximumLOD < minimumLOD Texture44=Texture: no capability to set lod offset Texture45=Texture: no capability to get lod offset +Texture46=Texture: illegal width < 1 +Texture47=Texture: illegal height < 1 Texture2D0=Texture: no capability to get detail texture information Texture2D1=Texture: Illegal detail texture mode value Texture2D2=Texture: Illegal detail texture level @@ -926,12 +974,12 @@ ModelClip13=ModelClip: no capability to write influencing bounding leaf ModelClip14=ModelClip: no capability to read influencing bounding leaf ModelClipRetained1=ModelClip: illegal node under SharedGroup Branch MasterControl0=OpenGL is not MT safe -MasterControl1=Green threads are not supported MasterControl2=NOTE: simulated multi-texture will not work for programmable shaders MasterControl3=and will be removed entirely in the next release of Java 3D J3DBuffer0=Native access to NIO buffer not supported J3DBuffer1=NIO buffer must be a direct buffer J3DBuffer2=NIO buffer must match native byte order of underlying platform +J3DGraphics2D0=Cannot use Graphics2D object after dispose() is called GLSLShaderProgram0=GLSLShaderProgram: no capability to read names GLSLShaderProgram1=GLSLShaderProgram: no capability to read shaders GLSLShaderProgram2=GLSLShaderProgram: Shader has incompatible shading language diff --git a/src/classes/share/javax/media/j3d/ExponentialFogRetained.java b/src/classes/share/javax/media/j3d/ExponentialFogRetained.java index 48d9a64..367929c 100644 --- a/src/classes/share/javax/media/j3d/ExponentialFogRetained.java +++ b/src/classes/share/javax/media/j3d/ExponentialFogRetained.java @@ -46,7 +46,7 @@ class ExponentialFogRetained extends FogRetained { */ void setDensity(float density){ this.density = density; - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.FOG_CHANGED; createMessage.universe = universe; @@ -70,7 +70,7 @@ class ExponentialFogRetained extends FogRetained { // Initialize the mirror object, this needs to be done, when // renderBin is not accessing any of the fields - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.universe = universe; createMessage.type = J3dMessage.FOG_CHANGED; @@ -108,12 +108,10 @@ class ExponentialFogRetained extends FogRetained { * This method and its native counterpart update the native context * fog values. */ - native void update(long ctx, float red, float green, float blue, float density); - - void update(long ctx, double scale) { + void update(Context ctx, double scale) { // Issue 144: recompute the density in EC, and send it to native code validateDistancesInEc(scale); - update(ctx, color.x, color.y, color.z, densityInEc); + Pipeline.getPipeline().updateExponentialFog(ctx, color.x, color.y, color.z, densityInEc); } diff --git a/src/classes/share/javax/media/j3d/FogRetained.java b/src/classes/share/javax/media/j3d/FogRetained.java index 75ce250..ab1350e 100644 --- a/src/classes/share/javax/media/j3d/FogRetained.java +++ b/src/classes/share/javax/media/j3d/FogRetained.java @@ -452,7 +452,7 @@ abstract class FogRetained extends LeafRetained{ * This abstract method is used to update the current native * context fog values. */ - abstract void update(long ctx, double scale); + abstract void update(Context ctx, double scale); void updateImmediateMirrorObject(Object[] objs) { @@ -715,7 +715,7 @@ abstract class FogRetained extends LeafRetained{ if (scopes.size() > 0) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.universe = universe; createMessage.type = J3dMessage.FOG_CHANGED; @@ -771,7 +771,7 @@ abstract class FogRetained extends LeafRetained{ } final void sendMessage(int attrMask, Object attr) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.universe = universe; createMessage.type = J3dMessage.FOG_CHANGED; diff --git a/src/classes/share/javax/media/j3d/FreeListManager.java b/src/classes/share/javax/media/j3d/FreeListManager.java index 15fa177..3c8df81 100644 --- a/src/classes/share/javax/media/j3d/FreeListManager.java +++ b/src/classes/share/javax/media/j3d/FreeListManager.java @@ -18,46 +18,26 @@ class FreeListManager { private static final boolean DEBUG = false; // constants that represent the freelists managed by the Manager - static final int MESSAGE = 0; - static final int BHLEAF = 1; - static final int TRANSFORM3D = 2; - static final int BHINTERNAL = 3; - static final int DISPLAYLIST = 4; - static final int TEXTURE2D = 5; - static final int TEXTURE3D = 6; - static final int VECTOR3D = 7; - static final int POINT3D = 8; - static int MAXINT = 8; + static final int DISPLAYLIST = 0; + static final int TEXTURE2D = 1; + static final int TEXTURE3D = 2; + + private static int maxFreeListNum = 2; // what list we are going to shrink next private static int currlist = 0; - // the freelists managed by the manager - static MemoryFreeList[] freelist = new MemoryFreeList[MAXINT+1]; - + static MemoryFreeList[] freelist = null; + static void createFreeLists() { - freelist[MESSAGE] = new MemoryFreeList("javax.media.j3d.J3dMessage"); - freelist[BHLEAF] = new MemoryFreeList("javax.media.j3d.BHLeafNode"); - freelist[TRANSFORM3D] = new MemoryFreeList("javax.media.j3d.Transform3D"); - freelist[BHINTERNAL] = new MemoryFreeList("javax.media.j3d.BHInternalNode"); - freelist[DISPLAYLIST] = new IntegerFreeList(); - freelist[TEXTURE2D] = new IntegerFreeList(); - freelist[TEXTURE3D] = new IntegerFreeList(); - freelist[POINT3D] = new MemoryFreeList("javax.vecmath.Point3d"); - freelist[VECTOR3D] = new MemoryFreeList("javax.vecmath.Vector3d"); + maxFreeListNum = 2; + freelist = new MemoryFreeList[maxFreeListNum+1]; + freelist[DISPLAYLIST] = new IntegerFreeList(); + freelist[TEXTURE2D] = new IntegerFreeList(); + freelist[TEXTURE3D] = new IntegerFreeList(); + } - // allows list to be created. The listId for the new list is returned. - static int createNewFreeList(String className) { - MAXINT++; - MemoryFreeList[] temp = freelist; - freelist = new MemoryFreeList[MAXINT+1]; - System.arraycopy(temp, 0, freelist, 0, MAXINT+1); - freelist[MAXINT] = new MemoryFreeList(className); - return MAXINT; - } - - // see if the current list can be shrunk static void manageLists() { // System.out.println("manageLists"); @@ -66,12 +46,12 @@ class FreeListManager { } currlist++; - if (currlist > MAXINT) currlist = 0; + if (currlist > maxFreeListNum) currlist = 0; } // return the freelist specified by the list param static MemoryFreeList getFreeList(int list) { - if (list < 0 || list > MAXINT) { + if (list < 0 || list > maxFreeListNum) { if (DEBUG) System.out.println("illegal list"); return null; } @@ -92,5 +72,4 @@ class FreeListManager { freelist[listId].clear(); } - } diff --git a/src/classes/share/javax/media/j3d/GLSLShaderProgramRetained.java b/src/classes/share/javax/media/j3d/GLSLShaderProgramRetained.java index 651d15d..81e7a44 100644 --- a/src/classes/share/javax/media/j3d/GLSLShaderProgramRetained.java +++ b/src/classes/share/javax/media/j3d/GLSLShaderProgramRetained.java @@ -29,8 +29,8 @@ class GLSLShaderProgramRetained extends ShaderProgramRetained { // System.out.println("GLSLShaderProgramRetained : createMirrorObject"); // This method should only call by setLive(). if (mirror == null) { - GLSLShaderProgramRetained mirrorGLSLSP = new GLSLShaderProgramRetained(); - mirror = mirrorGLSLSP; + GLSLShaderProgramRetained mirrorGLSLSP = new GLSLShaderProgramRetained(); + mirror = mirrorGLSLSP; mirror.source = source; } initMirrorObject(); @@ -38,134 +38,247 @@ class GLSLShaderProgramRetained extends ShaderProgramRetained { // ShaderAttributeValue methods - native ShaderError setUniform1i(long ctx, - long shaderProgramId, - long uniformLocation, - int value); - - native ShaderError setUniform1f(long ctx, - long shaderProgramId, - long uniformLocation, - float value); - - native ShaderError setUniform2i(long ctx, - long shaderProgramId, - long uniformLocation, - int[] value); - - native ShaderError setUniform2f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); - - native ShaderError setUniform3i(long ctx, - long shaderProgramId, - long uniformLocation, - int[] value); - - native ShaderError setUniform3f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); - - native ShaderError setUniform4i(long ctx, - long shaderProgramId, - long uniformLocation, - int[] value); - - native ShaderError setUniform4f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); - - native ShaderError setUniformMatrix3f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); - - native ShaderError setUniformMatrix4f(long ctx, - long shaderProgramId, - long uniformLocation, - float[] value); - + ShaderError setUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value) { + + return Pipeline.getPipeline().setGLSLUniform1i(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value) { + + return Pipeline.getPipeline().setGLSLUniform1f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + + return Pipeline.getPipeline().setGLSLUniform2i(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniform2f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + + return Pipeline.getPipeline().setGLSLUniform3i(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniform3f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + + return Pipeline.getPipeline().setGLSLUniform4i(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniform4f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniformMatrix3f(ctx, + shaderProgramId, + uniformLocation, + value); + } + + ShaderError setUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniformMatrix4f(ctx, + shaderProgramId, + uniformLocation, + value); + } + // ShaderAttributeArray methods - native ShaderError setUniform1iArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - int[] value); - - native ShaderError setUniform1fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniform2iArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - int[] value); - - native ShaderError setUniform2fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniform3iArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - int[] value); - - native ShaderError setUniform3fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniform4iArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - int[] value); - - native ShaderError setUniform4fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniformMatrix3fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - native ShaderError setUniformMatrix4fArray(long ctx, - long shaderProgramId, - long uniformLocation, - int numElements, - float[] value); - - /* New native interfaces */ - private native ShaderError createNativeShader(long ctx, int shaderType, long[] shaderId); - private native ShaderError destroyNativeShader(long ctx, long shaderId); - private native ShaderError compileNativeShader(long ctx, long shaderId, String program); - - private native ShaderError createNativeShaderProgram(long ctx, long[] shaderProgramId); - private native ShaderError destroyNativeShaderProgram(long ctx, long shaderProgramId); - private native ShaderError linkNativeShaderProgram(long ctx, long shaderProgramId, - long[] shaderId); - private native ShaderError bindNativeVertexAttrName(long ctx, long shaderProgramId, - String attrName, int attrIndex); - private native void lookupNativeShaderAttrNames(long ctx, long shaderProgramId, - int numAttrNames, String[] attrNames, long[] locArr, - int[] typeArr, int[] sizeArr, boolean[] isArrayArr); - - private native ShaderError useShaderProgram(long ctx, long shaderProgramId); + ShaderError setUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + + return Pipeline.getPipeline().setGLSLUniform1iArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniform1fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + + return Pipeline.getPipeline().setGLSLUniform2iArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniform2fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + + return Pipeline.getPipeline().setGLSLUniform3iArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniform3fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + + return Pipeline.getPipeline().setGLSLUniform4iArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniform4fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniformMatrix3fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } + + ShaderError setUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + + return Pipeline.getPipeline().setGLSLUniformMatrix4fArray(ctx, + shaderProgramId, + uniformLocation, + numElements, + value); + } /** * Method to return a flag indicating whether this @@ -178,69 +291,64 @@ class GLSLShaderProgramRetained extends ShaderProgramRetained { /** * Method to create the native shader. */ - ShaderError createShader(long ctx, ShaderRetained shader, long[] shaderIdArr) { - return createNativeShader(ctx, shader.shaderType, shaderIdArr); + ShaderError createShader(Context ctx, ShaderRetained shader, ShaderId[] shaderIdArr) { + return Pipeline.getPipeline().createGLSLShader(ctx, shader.shaderType, shaderIdArr); } /** * Method to destroy the native shader. */ - ShaderError destroyShader(long ctx, long shaderId) { - return destroyNativeShader(ctx, shaderId); + ShaderError destroyShader(Context ctx, ShaderId shaderId) { + return Pipeline.getPipeline().destroyGLSLShader(ctx, shaderId); } /** * Method to compile the native shader. */ - ShaderError compileShader(long ctx, long shaderId, String source) { - return compileNativeShader(ctx, shaderId, source ); + ShaderError compileShader(Context ctx, ShaderId shaderId, String source) { + return Pipeline.getPipeline().compileGLSLShader(ctx, shaderId, source ); } /** * Method to create the native shader program. */ - ShaderError createShaderProgram(long ctx, long[] shaderProgramIdArr) { - return createNativeShaderProgram(ctx, shaderProgramIdArr); + ShaderError createShaderProgram(Context ctx, ShaderProgramId[] shaderProgramIdArr) { + return Pipeline.getPipeline().createGLSLShaderProgram(ctx, shaderProgramIdArr); } /** * Method to destroy the native shader program. */ - ShaderError destroyShaderProgram(long ctx, long shaderProgramId) { - return destroyNativeShaderProgram(ctx, shaderProgramId); + ShaderError destroyShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return Pipeline.getPipeline().destroyGLSLShaderProgram(ctx, shaderProgramId); } /** * Method to link the native shader program. */ - ShaderError linkShaderProgram(long ctx, long shaderProgramId, long[] shaderIds) { - return linkNativeShaderProgram(ctx, shaderProgramId, shaderIds); + ShaderError linkShaderProgram(Context ctx, ShaderProgramId shaderProgramId, ShaderId[] shaderIds) { + return Pipeline.getPipeline().linkGLSLShaderProgram(ctx, shaderProgramId, shaderIds); } - ShaderError bindVertexAttrName(long ctx, long shaderProgramId, String attrName, int attrIndex) { - return bindNativeVertexAttrName(ctx, shaderProgramId, attrName, attrIndex); + ShaderError bindVertexAttrName(Context ctx, ShaderProgramId shaderProgramId, String attrName, int attrIndex) { + return Pipeline.getPipeline().bindGLSLVertexAttrName(ctx, shaderProgramId, attrName, attrIndex); } - void lookupVertexAttrNames(long ctx, long shaderProgramId, String[] attrNames, boolean[] errArr) { + void lookupVertexAttrNames(Context ctx, ShaderProgramId shaderProgramId, String[] attrNames, boolean[] errArr) { // This method is a no-op for GLSL } - void lookupShaderAttrNames(long ctx, long shaderProgramId, + void lookupShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, String[] attrNames, AttrNameInfo[] attrNameInfoArr) { int numAttrNames = attrNames.length; - long[] locArr = new long[numAttrNames]; + ShaderAttrLoc[] locArr = new ShaderAttrLoc[numAttrNames]; int[] typeArr = new int[numAttrNames]; int[] sizeArr = new int[numAttrNames]; // currently unused boolean[] isArrayArr = new boolean[numAttrNames]; - // Initialize loc array to -1 (indicating no location) - for (int i = 0; i < numAttrNames; i++) { - locArr[i] = -1; - } - - lookupNativeShaderAttrNames(ctx, shaderProgramId, + Pipeline.getPipeline().lookupGLSLShaderAttrNames(ctx, shaderProgramId, numAttrNames, attrNames, locArr, typeArr, sizeArr, isArrayArr); for (int i = 0; i < numAttrNames; i++) { @@ -259,15 +367,15 @@ class GLSLShaderProgramRetained extends ShaderProgramRetained { /** * Method to enable the native shader program. */ - ShaderError enableShaderProgram(long ctx, long shaderProgramId) { - return useShaderProgram(ctx, shaderProgramId); + ShaderError enableShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return Pipeline.getPipeline().useGLSLShaderProgram(ctx, shaderProgramId); } /** * Method to disable the native shader program. */ - ShaderError disableShaderProgram(long ctx) { - return useShaderProgram(ctx, 0); + ShaderError disableShaderProgram(Context ctx) { + return Pipeline.getPipeline().useGLSLShaderProgram(ctx, null); } diff --git a/src/classes/share/javax/media/j3d/GeometryArray.java b/src/classes/share/javax/media/j3d/GeometryArray.java index e1ca8d6..e2e8ec6 100644 --- a/src/classes/share/javax/media/j3d/GeometryArray.java +++ b/src/classes/share/javax/media/j3d/GeometryArray.java @@ -327,10 +327,20 @@ public abstract class GeometryArray extends Geometry { */ public static final int VERTEX_ATTRIBUTES = 0x1000; + //NVaidya + /** + * Specifies that the indices in this GeometryArray + * are accessed by reference. This flag is only valid for + * indexed geometry arrays (subclasses of IndexedGeometryArray) and only + * when used in conjunction with the <code>BY_REFERENCE</code> and + * <code>USE_COORD_INDEX_ONLY</code> flags. + * + * @since Java 3D 1.5 + */ + public static final int BY_REFERENCE_INDICES = 0x2000; // Used to keep track of the last bit (for adding new bits only) - private static final int LAST_FORMAT_BIT = 0x1000; - + private static final int LAST_FORMAT_BIT = 0x2000; // Scratch arrays for converting Point[234]f to TexCoord[234]f private TexCoord2f [] texCoord2fArray = null; @@ -360,7 +370,7 @@ public abstract class GeometryArray extends Geometry { setDefaultReadCapabilities(readCapabilities); } - + //NVaidya /** * Constructs an empty GeometryArray object with the specified * number of vertices and vertex format. Defaults are used @@ -404,7 +414,10 @@ public abstract class GeometryArray extends Geometry { * is accessed via a J3DBuffer object that wraps an NIO buffer; * <code>USE_COORD_INDEX_ONLY</code>, * to indicate that only the coordinate indices are used for indexed - * geometry arrays. + * geometry arrays; + * <code>BY_REFERENCE_INDICES</code>, to indicate + * that the indices are accessed by reference in indexed + * geometry arrays.<p> * * @exception IllegalArgumentException if vertexCount < 0 * @@ -412,7 +425,8 @@ public abstract class GeometryArray extends Geometry { * include <code>COORDINATES</code> * * @exception IllegalArgumentException if the <code>USE_COORD_INDEX_ONLY</code> - * bit is set for non-indexed geometry arrays (that is, GeometryArray objects + * bit or the <code>BY_REFERENCE_INDICES</code> bit is set for + * non-indexed geometry arrays (that is, GeometryArray objects * that are not a subclass of IndexedGeometryArray) * * @exception IllegalArgumentException if the <code>INTERLEAVED</code> @@ -423,6 +437,11 @@ public abstract class GeometryArray extends Geometry { * * @exception IllegalArgumentException if the <code>INTERLEAVED</code> * bit and the <code>VERTEX_ATTRIBUTES</code> bit are both set + * + * @exception IllegalArgumentException if the + * <code>BY_REFERENCE_INDICES</code> + * bit is set without the <code>BY_REFERENCE</code> and + * <code>USE_COORD_INDEX_ONLY</code> bits being set */ public GeometryArray(int vertexCount, int vertexFormat) { this(vertexCount, vertexFormat, @@ -431,6 +450,7 @@ public abstract class GeometryArray extends Geometry { } + //NVaidya /** * Constructs an empty GeometryArray object with the specified * number of vertices, vertex format, number of texture coordinate @@ -462,6 +482,9 @@ public abstract class GeometryArray extends Geometry { * is accessed via a J3DBuffer object that wraps an NIO buffer; * <code>USE_COORD_INDEX_ONLY</code>, * to indicate that only the coordinate indices are used for indexed + * geometry arrays; + * <code>BY_REFERENCE_INDICES</code>, to indicate + * that the indices are accessed by reference in indexed * geometry arrays.<p> * * @param texCoordSetCount the number of texture coordinate sets @@ -536,7 +559,8 @@ public abstract class GeometryArray extends Geometry { * include <code>COORDINATES</code> * * @exception IllegalArgumentException if the <code>USE_COORD_INDEX_ONLY</code> - * bit is set for non-indexed geometry arrays (that is, GeometryArray objects + * bit or the <code>BY_REFERENCE_INDICES</code> bit is set for + * non-indexed geometry arrays (that is, GeometryArray objects * that are not a subclass of IndexedGeometryArray) * * @exception IllegalArgumentException if the <code>INTERLEAVED</code> @@ -548,6 +572,11 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if the <code>INTERLEAVED</code> * bit and the <code>VERTEX_ATTRIBUTES</code> bit are both set * + * @exception IllegalArgumentException if the + * <code>BY_REFERENCE_INDICES</code> + * bit is set without the <code>BY_REFERENCE</code> and + * <code>USE_COORD_INDEX_ONLY</code> bits being set + * * @exception IllegalArgumentException if * <code>texCoordSetCount < 0</code> * @@ -564,6 +593,7 @@ public abstract class GeometryArray extends Geometry { } + //NVaidya /** * Constructs an empty GeometryArray object with the specified * number of vertices, vertex format, number of texture coordinate @@ -597,6 +627,9 @@ public abstract class GeometryArray extends Geometry { * is accessed via a J3DBuffer object that wraps an NIO buffer; * <code>USE_COORD_INDEX_ONLY</code>, * to indicate that only the coordinate indices are used for indexed + * geometry arrays; + * <code>BY_REFERENCE_INDICES</code>, to indicate + * that the indices are accessed by reference in indexed * geometry arrays.<p> * * @param texCoordSetCount the number of texture coordinate sets @@ -681,7 +714,8 @@ public abstract class GeometryArray extends Geometry { * include <code>COORDINATES</code> * * @exception IllegalArgumentException if the <code>USE_COORD_INDEX_ONLY</code> - * bit is set for non-indexed geometry arrays (that is, GeometryArray objects + * bit or the <code>BY_REFERENCE_INDICES</code> bit is set for + * non-indexed geometry arrays (that is, GeometryArray objects * that are not a subclass of IndexedGeometryArray) * * @exception IllegalArgumentException if the <code>INTERLEAVED</code> @@ -693,6 +727,11 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if the <code>INTERLEAVED</code> * bit and the <code>VERTEX_ATTRIBUTES</code> bit are both set * + * @exception IllegalArgumentException if the + * <code>BY_REFERENCE_INDICES</code> + * bit is set without the <code>BY_REFERENCE</code> and + * <code>USE_COORD_INDEX_ONLY</code> bits being set + * * @exception IllegalArgumentException if * <code>texCoordSetCount < 0</code> * @@ -748,6 +787,16 @@ public abstract class GeometryArray extends Geometry { throw new IllegalArgumentException(J3dI18N.getString("GeometryArray135")); } + //NVaidya + if ((vertexFormat & BY_REFERENCE_INDICES) != 0) { + if (!(this instanceof IndexedGeometryArray)) + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray136")); + if ((vertexFormat & BY_REFERENCE) == 0) + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray137")); + if ((vertexFormat & USE_COORD_INDEX_ONLY) == 0) + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray138")); + } + if ((vertexFormat & USE_NIO_BUFFER) != 0 && (vertexFormat & BY_REFERENCE) == 0) throw new IllegalArgumentException(J3dI18N.getString("GeometryArray117")); diff --git a/src/classes/share/javax/media/j3d/GeometryArrayRetained.java b/src/classes/share/javax/media/j3d/GeometryArrayRetained.java index f50a9e1..5a82c09 100644 --- a/src/classes/share/javax/media/j3d/GeometryArrayRetained.java +++ b/src/classes/share/javax/media/j3d/GeometryArrayRetained.java @@ -62,7 +62,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // vertex data in packed format for each screen in multi-screen situation // if alpha values of each vertex are to be updated - float mvertexData[][]; + private float mvertexData[][]; // // The following offset/stride values are internally computed @@ -94,14 +94,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ int vertexAttrStride; // alpha value for transparency and texture blending - float[] lastAlpha = new float[1]; + private float[] lastAlpha = new float[1]; float lastScreenAlpha = -1; int colorChanged = 0; - // true if alpha value from transparencyAttrubute has changed - boolean alphaChanged = false; - // byte to float scale factor static final float ByteToFloatScale = 1.0f/255.0f; @@ -162,7 +159,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ static final int P3D = 0x8; static final int VERTEX_DEFINED = PF | PD | P3F | P3D; - static final int CF = 0x10; static final int CUB = 0x20; static final int C3F = 0x40; @@ -170,19 +166,19 @@ abstract class GeometryArrayRetained extends GeometryRetained{ static final int C3UB = 0x100; static final int C4UB = 0x200; static final int COLOR_DEFINED = CF | CUB | C3F | C4F| C3UB | C4UB; - + static final int NF = 0x400; static final int N3F = 0x800; static final int NORMAL_DEFINED = NF | N3F; - + static final int TF = 0x1000; static final int T2F = 0x2000; static final int T3F = 0x4000; static final int TEXCOORD_DEFINED = TF | T2F | T3F; - + static final int AF = 0x8000; static final int VATTR_DEFINED = AF; - + // Flag word indicating the type of by-ref texCoord. We will copy this to // the vertexType field only when the references for all texture coordinate // sets are set to non-null values. @@ -340,12 +336,12 @@ abstract class GeometryArrayRetained extends GeometryRetained{ IndexedGeometryArrayRetained cloneSourceArray = null; -// private MemoryFreeList pickVectorFreelist = -// FreeListManager.getFreeList(FreeListManager.PICKVECTOR); - static final double EPS = 1.0e-13; - native void freeD3DArray(boolean deleteVB); + void freeD3DArray(boolean deleteVB) { + assert VirtualUniverse.mc.isD3D(); + Pipeline.getPipeline().freeD3DArray(this, deleteVB); + } GeometryArrayRetained() { dirtyFlag = INDEX_CHANGED|VERTEX_CHANGED; @@ -363,7 +359,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (this.refCount > 1) { // Send to rendering attribute structure, /* - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.GEOMETRYARRAY_CHANGED; createMessage.universe = null; @@ -378,7 +374,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // otherwise, set mirrorGeometry to null (from previous clearLive) if (this instanceof IndexedGeometryArrayRetained) { // Send to rendering attribute structure, - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.GEOMETRY_CHANGED; createMessage.universe = null; @@ -396,7 +392,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (this.refCount <= 0) { if (pVertexBuffers != 0) { - J3dMessage renderMessage = VirtualUniverse.mc.getMessage(); + J3dMessage renderMessage = new J3dMessage(); renderMessage.threads = J3dThread.RENDER_THREAD; renderMessage.type = J3dMessage.RENDER_IMMEDIATE; renderMessage.universe = null; @@ -1644,93 +1640,15 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } - // used for GeometryArrays by Copy or interleaved - private native void execute(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean useAlpha, - boolean multiScreen, - boolean ignoreVertexColors, - int startVIndex, int vcount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetOffset, - int numActiveTexUnitState, - int[] texUnitStateMap, - int vertexAttrCount, int[] vertexAttrSizes, - float[] varray, float[] cdata, int texUnitIndex, int cdirty); - - // used by GeometryArray by Reference with java arrays - private native void executeVA(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean multiScreen, - boolean ignoreVertexColors, - int vcount, - int vformat, - int vdefined, - int coordIndex, float[] vfcoords, double[] vdcoords, - int colorIndex, float[] cfdata, byte[] cbdata, - int normalIndex, float[] ndata, - int vertexAttrCount, int[] vertexAttrSizes, - int[] vertexAttrIndex, float[][] vertexAttrData, - int pass, int texcoordmaplength, - int[] texcoordoffset, - int numActiveTexUnitState, int[] texunitstatemap, - int[] texIndex, int texstride, Object[] texCoords, - int cdirty); - - // used by GeometryArray by Reference with NIO buffer - private native void executeVABuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean multiScreen, - boolean ignoreVertexColors, - int vcount, - int vformat, - int vdefined, - int coordIndex, - Object vcoords, - int colorIndex, - Object cdataBuffer, - float[] cfdata, byte[] cbdata, - int normalIndex, Object ndata, - int vertexAttrCount, int[] vertexAttrSizes, - int[] vertexAttrIndex, Object[] vertexAttrData, - int pass, int texcoordmaplength, - int[] texcoordoffset, - int numActiveTexUnitState, int[] texunitstatemap, - int[] texIndex, int texstride, Object[] texCoords, - int cdirty); - - // used by GeometryArray by Reference in interleaved format with NIO buffer - private native void executeInterleavedBuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean useAlpha, - boolean multiScreen, - boolean ignoreVertexColors, - int startVIndex, int vcount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetOffset, - int numActiveTexUnitState, - int[] texUnitStateMap, - Object varray, float[] cdata, int texUnitIndex, int cdirty); - - private native void setVertexFormat(long ctx, - int vformat, boolean useAlpha, boolean ignoreVertexColors); - - private native void disableGlobalAlpha(long ctx, int vformat, - boolean useAlpha, boolean ignoreVertexColors); - - void setVertexFormat(boolean useAlpha, boolean ignoreVC, long ctx) { - setVertexFormat(ctx, vertexFormat, useAlpha, ignoreVC); + void setVertexFormat(boolean useAlpha, boolean ignoreVC, Context ctx) { + Pipeline.getPipeline().setVertexFormat(ctx, + this, vertexFormat, useAlpha, ignoreVC); } - void disableGlobalAlpha(long ctx, boolean useAlpha, boolean ignoreVC) { + void disableGlobalAlpha(Context ctx, boolean useAlpha, boolean ignoreVC) { // If global alpha was turned on, then disable it - disableGlobalAlpha(ctx, vertexFormat, useAlpha, ignoreVC); + Pipeline.getPipeline().disableGlobalAlpha(ctx, + this, vertexFormat, useAlpha, ignoreVC); } @@ -1745,12 +1663,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return mirrorFloatRefColors[0]; } - // Issue 113 - // TODO: Fix this for screen > 0, for now just ignore transparency - if (screen > 0) { - return mirrorFloatRefColors[0]; - } - // update alpha only if vertex format includes alpha if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0) return mirrorFloatRefColors[0]; @@ -1762,17 +1674,18 @@ abstract class GeometryArrayRetained extends GeometryRetained{ alpha = (float)EPSILON; } - // allocate an entry for the last alpha of the screen if needed - if (lastAlpha == null) { - lastAlpha = new float[screen + 1]; - lastAlpha[screen] = 1.0f; - } else if (lastAlpha.length <= screen) { + assert lastAlpha != null; + assert mirrorFloatRefColors != null; + assert mirrorFloatRefColors.length == lastAlpha.length; + + // Issue 113 - reallocate lastAlpha array if needed, but no need to + // update the values here + if (lastAlpha.length <= screen) { float[] la = new float[screen + 1]; for (int i = 0; i < lastAlpha.length; i++) { la[i] = lastAlpha[i]; } lastAlpha = la; - lastAlpha[screen] = 1.0f; } //System.out.println("updateAlphaInFloatRefColors screen is " + screen @@ -1780,48 +1693,30 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // mirrorFloatRefColors.length); // allocate a copy of the color data for the screen if needed. - // this piece of code is mainly for multi-screens case + // this piece of code is only for multi-screens case if (mirrorFloatRefColors.length <= screen) { float[][] cfData = new float[screen + 1][]; - float[] cdata; - int refScreen = -1; for (int i = 0; i < mirrorFloatRefColors.length; i++) { cfData[i] = mirrorFloatRefColors[i]; - if (Math.abs(lastAlpha[i] - alpha) < EPSILON) { - refScreen = i; - } } - cdata = cfData[screen] = new float[4 * vertexCount]; - // copy the data from a reference screen which has the closest - // alpha values - if (refScreen >= 0) { - System.arraycopy(cfData[refScreen], 0, cdata, 0, - 4 * vertexCount); - lastAlpha[screen] = lastAlpha[refScreen]; - } else { - float m = alpha / lastAlpha[0]; - float[] sdata = cfData[0]; + // Issue 113 - allocate entries for [oldSize..screen]; + // copy cfData[0] to cfData[oldsize..screen-1] and + // lastAlpha[0] to lastAlpha[oldsize..screen-1]. + for (int i = mirrorFloatRefColors.length; i < screen+1; i++) { + cfData[i] = new float[4 * vertexCount]; + System.arraycopy(cfData[0], 0, cfData[i], 0, 4 * vertexCount); + lastAlpha[i] = lastAlpha[0]; + } - int j = initialColorIndex * 4; - for (int i = initialColorIndex; i < validVertexCount; i++) { - cdata[j] = sdata[j++]; - cdata[j] = sdata[j++]; - cdata[j] = sdata[j++]; - cdata[j] = sdata[j++] * m; - } - lastAlpha[screen] = alpha; - } - mirrorFloatRefColors = cfData; + mirrorFloatRefColors = cfData; - // reset the colorChanged bit - colorChanged &= ~(1 << screen); - dirtyFlag |= COLOR_CHANGED; - - return cdata; + // Issue 113 - since we copied the data from screen 0, we don't need + // to do any further special processing. } + assert lastAlpha[screen] >= 0.0; /* System.out.println("updateAlphaInFloatRefColors ** : lastAlpha[screen] " + lastAlpha[screen]); @@ -1832,7 +1727,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if ((colorChanged & (1<<screen)) == 0) { // color data is not modified - if (Math.abs(lastAlpha[screen] - alpha) < EPSILON) { + if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) { // and if alpha is the same as the last one, // just return the data //System.out.println("updateAlphaInFloatRefColors 0 : alpha is the same as the last one " + alpha); @@ -1919,12 +1814,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return mirrorUnsignedByteRefColors[0]; } - // Issue 113 - // TODO: Fix this for screen > 0, for now just ignore transparency - if (screen > 0) { - return mirrorUnsignedByteRefColors[0]; - } - // update alpha only if vertex format includes alpha if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0) return mirrorUnsignedByteRefColors[0]; @@ -1936,59 +1825,45 @@ abstract class GeometryArrayRetained extends GeometryRetained{ alpha = (float)EPSILON; } - // allocate an entry for the last alpha of the screen if needed - if (lastAlpha == null) { - lastAlpha = new float[screen + 1]; - lastAlpha[screen] = -1.0f; - } else if (lastAlpha.length <= screen) { + assert lastAlpha != null; + assert mirrorUnsignedByteRefColors != null; + assert mirrorUnsignedByteRefColors.length == lastAlpha.length; + + // Issue 113 - reallocate lastAlpha array if needed, but no need to + // update the values here + if (lastAlpha.length <= screen) { float[] la = new float[screen + 1]; for (int i = 0; i < lastAlpha.length; i++) { la[i] = lastAlpha[i]; } lastAlpha = la; - lastAlpha[screen] = -1.0f; } // allocate a copy of the color data for the screen if needed. - // this piece of code is mainly for multi-screens case + // this piece of code is only for multi-screens case if (mirrorUnsignedByteRefColors.length <= screen) { - byte[][] cfData = new byte[screen + 1][]; - byte[] cdata; - int refScreen = -1; + byte[][] cbData = new byte[screen + 1][]; for (int i = 0; i < mirrorUnsignedByteRefColors.length; i++) { - cfData[i] = mirrorUnsignedByteRefColors[i]; - if (Math.abs(lastAlpha[i] - alpha) < EPSILON) { - refScreen = i; - } + cbData[i] = mirrorUnsignedByteRefColors[i]; } - cdata = cfData[screen] = new byte[4 * vertexCount]; - // copy the data from a reference screen which has the closest - // alpha values - if (refScreen >= 0) { - System.arraycopy(cfData[refScreen], 0, cdata, 0, - 4 * vertexCount); - lastAlpha[screen] = lastAlpha[refScreen]; - } else { - float m = alpha / lastAlpha[0]; - byte[] sdata = cfData[0]; + // Issue 113 - allocate entries for [oldSize..screen]; + // copy cbData[0] to cbData[oldsize..screen-1] and + // lastAlpha[0] to lastAlpha[oldsize..screen-1]. + for (int i = mirrorUnsignedByteRefColors.length; i < screen+1; i++) { + cbData[i] = new byte[4 * vertexCount]; + System.arraycopy(cbData[0], 0, cbData[i], 0, 4 * vertexCount); + lastAlpha[i] = lastAlpha[0]; + } - int j = initialColorIndex * 4; - for (int i = initialColorIndex; i < validVertexCount; i++) { - cdata[j] = sdata[j++]; - cdata[j] = sdata[j++]; - cdata[j] = sdata[j++]; - cdata[j] = (byte)(((int)sdata[j++]& 0xff) * m); - } - lastAlpha[screen] = alpha; - } - mirrorUnsignedByteRefColors = cfData; - colorChanged &= ~(1 << screen); - dirtyFlag |= COLOR_CHANGED; - return cdata; + mirrorUnsignedByteRefColors = cbData; + + // Issue 113 - since we copied the data from screen 0, we don't need + // to do any further special processing. } - /* + assert lastAlpha[screen] >= 0.0; + /* System.out.println("updateAlphaInByteRefColors ## : lastAlpha[screen] " + lastAlpha[screen]); @@ -1998,7 +1873,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if ((colorChanged & (1<<screen)) == 0) { // color data is not modified - if (Math.abs(lastAlpha[screen] - alpha) < EPSILON) { + if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) { // and if alpha is the same as the last one, // just return the data //System.out.println("updateAlphaInByteRefColors 0 : alpha is the same as the last one " + alpha); @@ -2080,13 +1955,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return retVal; } - // Issue 113 - // TODO: Fix this for screen > 0, for now just ignore transparency - if (screen > 0) { - retVal[1] = vertexData; - return retVal; - } - // update alpha only if vertex format includes alpha if ((vertexFormat & GeometryArray.COLOR) == 0) { retVal[1] = vertexData; @@ -2101,81 +1969,61 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } retVal[0] = Boolean.TRUE; - // allocate an entry for the last alpha of the screen if needed - if (lastAlpha == null) { - lastAlpha = new float[screen + 1]; - lastAlpha[screen] = 1.0f; - } else if (lastAlpha.length <= screen) { + assert lastAlpha != null; + assert mvertexData == null || mvertexData.length == lastAlpha.length; + + // Issue 113 - reallocate lastAlpha array if needed, but no need to + // update the values here + if (lastAlpha.length <= screen) { float[] la = new float[screen + 1]; for (int i = 0; i < lastAlpha.length; i++) { la[i] = lastAlpha[i]; } lastAlpha = la; - lastAlpha[screen] = 1.0f; } // allocate a copy of the vertex data for the screen if needed. - // this piece of code is mainly for multi-screens case - // NOTE: this might not too much data for just to update alpha + // Note that a copy operation only happens in the multi-screens case. + // We always use the existing vertexData for screen 0. if (mvertexData == null || mvertexData.length <= screen) { float[][] cfData = new float[screen + 1][]; - float[] cdata; - int refScreen = -1; + int oldSize = 1; if (mvertexData != null) { + oldSize = mvertexData.length; for (int i = 0; i < mvertexData.length; i++) { cfData[i] = mvertexData[i]; - if (Math.abs(lastAlpha[i] - alpha) < EPSILON) { - refScreen = i; - } } } if (cfData[0] == null) { - cfData[screen] = vertexData; - } - - if (screen > 0) - cfData[screen] = new float[stride * vertexCount]; - - cdata = cfData[screen]; - - // copy the data from a reference screen which has the closest - // alpha values - if (refScreen >= 0) { - System.arraycopy(cfData[refScreen], 0, cdata, 0, - stride * vertexCount); - lastAlpha[screen] = lastAlpha[refScreen]; - } else { - float m = alpha / lastAlpha[0]; - float[] sdata = cfData[0]; + cfData[0] = vertexData; + } + + // Issue 113 - allocate entries for [oldSize..screen]; + // copy cfData[0] to cfData[oldsize..screen-1] and + // lastAlpha[0] to lastAlpha[oldsize..screen-1]. + if (screen > 0) { + for (int i = oldSize; i < screen+1; i++) { + cfData[i] = new float[stride * vertexCount]; + System.arraycopy(cfData[0], 0, cfData[i], 0, + stride * vertexCount); + lastAlpha[i] = lastAlpha[0]; + } + } - /* - // screen 0 data is always up-to-date - if (screen > 0) { - System.arraycopy(cfData[0], 0, cdata, 0, - stride * vertexCount); - } - */ + mvertexData = cfData; - for (int i = 0, j = colorOffset; i < vertexCount; - i++, j+=stride) { - cdata[j+3] = sdata[j+3] * m; - } - lastAlpha[screen] = alpha; - } - mvertexData = cfData; - dirtyFlag |= COLOR_CHANGED; - // reset the colorChanged bit - colorChanged &= ~(1 << screen); - retVal[1] = cdata; - return retVal; + // Issue 113 - since we copied the data from screen 0, we don't need + // to do any further special processing. } + + assert lastAlpha[screen] >= 0.0; if ((colorChanged & (1<<screen)) == 0) { // color data is not modified - if (Math.abs(lastAlpha[screen] - alpha) < EPSILON) { + if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) { // and if alpha is the same as the last one, // just return the data retVal[1] = mvertexData[screen]; @@ -2237,15 +2085,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return retVal; } - // Issue 113 - // TODO: Fix this for screen > 0, for now just ignore transparency - if (screen > 0) { - retVal[1] = null; - return retVal; - } - // update alpha only if vertex format includes alpha - if (((vertexFormat | c4fAllocated) & GeometryArray.COLOR) == 0) { + if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0) { retVal[1] = mirrorInterleavedColorPointer[0]; return retVal; } @@ -2259,66 +2100,50 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } retVal[0] = Boolean.TRUE; - // allocate an entry for the last alpha of the screen if needed - if (lastAlpha == null) { - lastAlpha = new float[screen + 1]; - lastAlpha[screen] = 1.0f; - } else if (lastAlpha.length <= screen) { + assert lastAlpha != null; + assert mirrorInterleavedColorPointer != null; + assert mirrorInterleavedColorPointer.length == lastAlpha.length; + + // Issue 113 - reallocate lastAlpha array if needed, but no need to + // update the values here + if (lastAlpha.length <= screen) { float[] la = new float[screen + 1]; for (int i = 0; i < lastAlpha.length; i++) { la[i] = lastAlpha[i]; } lastAlpha = la; - lastAlpha[screen] = 1.0f; } // allocate a copy of the vertex data for the screen if needed. - // this piece of code is mainly for multi-screens case - // NOTE: this might not too much data for just to update alpha + // this piece of code is only for multi-screens case if (mirrorInterleavedColorPointer.length <= screen) { float[][] cfData = new float[screen + 1][]; - float[] cdata; - int refScreen = -1; for (int i = 0; i < mirrorInterleavedColorPointer.length; i++) { cfData[i] = mirrorInterleavedColorPointer[i]; - if (Math.abs(lastAlpha[i] - alpha) < EPSILON) { - refScreen = i; - } } - //cdata = cfData[screen] = new float[stride * vertexCount]; - cdata = cfData[screen] = new float[4 * vertexCount]; - - // copy the data from a reference screen which has the closest - // alpha values - if (refScreen >= 0) { - System.arraycopy(cfData[refScreen], 0, cdata, 0, - 4 * vertexCount); - lastAlpha[screen] = lastAlpha[refScreen]; - } else { - float m = alpha / lastAlpha[0]; - float[] sdata = cfData[0]; - - for (int i = coffset; i < coffset + (vertexCount << 2); i+=4) { - cdata[i+3] = sdata[i+3] * m; - } + // Issue 113 - allocate entries for [oldSize..screen]; + // copy cfData[0] to cfData[oldsize..screen-1] and + // lastAlpha[0] to lastAlpha[oldsize..screen-1]. + for (int i = mirrorInterleavedColorPointer.length; i < screen+1; i++) { + cfData[i] = new float[4 * vertexCount]; + System.arraycopy(cfData[0], 0, cfData[i], 0, 4 * vertexCount); + lastAlpha[i] = lastAlpha[0]; + } - lastAlpha[screen] = alpha; - } mirrorInterleavedColorPointer = cfData; - // reset the colorChanged bit - colorChanged &= ~(1 << screen); - dirtyFlag |= COLOR_CHANGED; - retVal[1] = cdata; - return retVal; + // Issue 113 - since we copied the data from screen 0, we don't need + // to do any further special processing. } - if ((colorChanged & (1<<screen)) == 0) { + assert lastAlpha[screen] >= 0.0; + + if ((colorChanged & (1<<screen)) == 0) { // color data is not modified - if (Math.abs(lastAlpha[screen] - alpha) < EPSILON) { + if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) { // and if alpha is the same as the last one, // just return the data retVal[1] = mirrorInterleavedColorPointer[screen]; @@ -2388,8 +2213,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, - boolean multiScreen, int screen, - boolean ignoreVertexColors, int pass) { + int screen, + boolean ignoreVertexColors) { int cdirty; boolean useAlpha = false; @@ -2427,9 +2252,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ dirtyFlag = 0; } - execute(cv.ctx, this, geoType, isNonUniformScale, + Pipeline.getPipeline().execute(cv.ctx, + this, geoType, isNonUniformScale, useAlpha, - multiScreen, ignoreVertexColors, initialVertexIndex, validVertexCount, @@ -2437,10 +2262,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ texCoordSetCount, texCoordSetMap, (texCoordSetMap == null) ? 0 : texCoordSetMap.length, texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, + cv.numActiveTexUnit, vertexAttrCount, vertexAttrSizes, vdata, null, - pass, cdirty); + cdirty); } //By reference with java array @@ -2473,9 +2298,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ dirtyFlag = 0; } - execute(cv.ctx, this, geoType, isNonUniformScale, + Pipeline.getPipeline().execute(cv.ctx, + this, geoType, isNonUniformScale, useAlpha, - multiScreen, ignoreVertexColors, initialVertexIndex, validVertexCount, @@ -2483,10 +2308,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ texCoordSetCount, texCoordSetMap, (texCoordSetMap == null) ? 0 : texCoordSetMap.length, texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, + cv.numActiveTexUnit, vertexAttrCount, vertexAttrSizes, interLeavedVertexData, cdata, - pass, cdirty); + cdirty); } // end of interleaved case @@ -2572,25 +2397,23 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if((vertexType & TEXCOORD_DEFINED) != 0) vdefined |= TEXCOORD_FLOAT; - executeVA(cv.ctx, this, geoType, isNonUniformScale, - multiScreen, - ignoreVertexColors, - validVertexCount, - (vertexFormat | c4fAllocated), - vdefined, - initialCoordIndex, - mirrorFloatRefCoords, mirrorDoubleRefCoords, - initialColorIndex, cfdata, cbdata, - initialNormalIndex, mirrorFloatRefNormals, - vertexAttrCount, vertexAttrSizes, - initialVertexAttrIndex, mirrorFloatRefVertexAttrs, - pass, - ((texCoordSetMap == null) ? 0:texCoordSetMap.length), - texCoordSetMap, - cv.numActiveTexUnit, - cv.texUnitStateMap, - initialTexCoordIndex,texCoordStride, - mirrorRefTexCoords, cdirty); + Pipeline.getPipeline().executeVA(cv.ctx, + this, geoType, isNonUniformScale, + ignoreVertexColors, + validVertexCount, + (vertexFormat | c4fAllocated), + vdefined, + initialCoordIndex, + mirrorFloatRefCoords, mirrorDoubleRefCoords, + initialColorIndex, cfdata, cbdata, + initialNormalIndex, mirrorFloatRefNormals, + vertexAttrCount, vertexAttrSizes, + initialVertexAttrIndex, mirrorFloatRefVertexAttrs, + ((texCoordSetMap == null) ? 0:texCoordSetMap.length), + texCoordSetMap, + cv.numActiveTexUnit, + initialTexCoordIndex,texCoordStride, + mirrorRefTexCoords, cdirty); }// end of all vertex data being set }// end of non interleaved case }// end of by reference with java array @@ -2629,19 +2452,19 @@ abstract class GeometryArrayRetained extends GeometryRetained{ dirtyFlag = 0; } - executeInterleavedBuffer(cv.ctx, this, geoType, isNonUniformScale, - useAlpha, - multiScreen, - ignoreVertexColors, - initialVertexIndex, - validVertexCount, - vertexFormat, - texCoordSetCount, texCoordSetMap, - (texCoordSetMap == null) ? 0 : texCoordSetMap.length, - texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, - interleavedFloatBufferImpl.getBufferAsObject(), cdata, - pass, cdirty); + Pipeline.getPipeline().executeInterleavedBuffer(cv.ctx, + this, geoType, isNonUniformScale, + useAlpha, + ignoreVertexColors, + initialVertexIndex, + validVertexCount, + vertexFormat, + texCoordSetCount, texCoordSetMap, + (texCoordSetMap == null) ? 0 : texCoordSetMap.length, + texCoordSetMapOffset, + cv.numActiveTexUnit, + interleavedFloatBufferImpl.getBufferAsObject(), cdata, + cdirty); } // end of interleaved case @@ -2747,89 +2570,32 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if((vertexType & TEXCOORD_DEFINED) != 0) vdefined |= TEXCOORD_FLOAT; - executeVABuffer(cv.ctx, this, geoType, isNonUniformScale, - multiScreen, - ignoreVertexColors, - validVertexCount, - (vertexFormat | c4fAllocated), - vdefined, - initialCoordIndex, - vcoord, - initialColorIndex, - cdataBuffer, - cfdata, cbdata, - initialNormalIndex, - normal, - vertexAttrCount, vertexAttrSizes, - initialVertexAttrIndex, - nioFloatBufferRefVertexAttrs, - pass, - ((texCoordSetMap == null) ? 0:texCoordSetMap.length), - texCoordSetMap, - cv.numActiveTexUnit, - cv.texUnitStateMap, - initialTexCoordIndex,texCoordStride, - refTexCoords, cdirty); + Pipeline.getPipeline().executeVABuffer(cv.ctx, + this, geoType, isNonUniformScale, + ignoreVertexColors, + validVertexCount, + (vertexFormat | c4fAllocated), + vdefined, + initialCoordIndex, + vcoord, + initialColorIndex, + cdataBuffer, + cfdata, cbdata, + initialNormalIndex, + normal, + vertexAttrCount, vertexAttrSizes, + initialVertexAttrIndex, + nioFloatBufferRefVertexAttrs, + ((texCoordSetMap == null) ? 0:texCoordSetMap.length), + texCoordSetMap, + cv.numActiveTexUnit, + initialTexCoordIndex,texCoordStride, + refTexCoords, cdirty); }// end of all vertex data being set }// end of non interleaved case }// end of by reference with nio-buffer case } - // used for GeometryArrays - private native void buildGA(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, boolean updateAlpha, - float alpha, - boolean ignoreVertexColors, - int startVIndex, - int vcount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, int[] texCoordSetMapOffset, - int vertexAttrCount, int[] vertexAttrSizes, - double[] xform, double[] nxform, - float[] varray); - - // used to Build Dlist GeometryArray by Reference with java arrays - private native void buildGAForByRef(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, boolean updateAlpha, - float alpha, - boolean ignoreVertexColors, - int vcount, - int vformat, - int vdefined, - int coordIndex, float[] vfcoords, double[] vdcoords, - int colorIndex, float[] cfdata, byte[] cbdata, - int normalIndex, float[] ndata, - int vertexAttrCount, int[] vertexAttrSizes, - int[] vertexAttrIndex, float[][] vertexAttrData, - int texcoordmaplength, - int[] texcoordoffset, - int[] texIndex, int texstride, Object[] texCoords, - double[] xform, double[] nxform); - - - // used to Build Dlist GeometryArray by Reference with NIO buffer - // NOTE: NIO buffers are no longer supported in display lists. - /* - private native void buildGAForBuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, boolean updateAlpha, - float alpha, - boolean ignoreVertexColors, - int vcount, - int vformat, - int vdefined, - int coordIndex, Object vcoords, - int colorIndex, Object cdata, - int normalIndex, Object ndata, - int texcoordmaplength, - int[] texcoordoffset, - int[] texIndex, int texstride, Object[] texCoords, - double[] xform, double[] nxform); - */ - - void buildGA(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, boolean ignoreVertexColors, Transform3D xform, Transform3D nxform) { @@ -2851,7 +2617,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ System.out.println("calling native buildGA()"); System.out.println("geoType = "+geoType+" initialVertexIndex = "+initialVertexIndex+" validVertexCount = "+validVertexCount+" vertexFormat = "+vertexFormat+" vertexData = "+vertexData); */ - buildGA(cv.ctx, this, geoType, isNonUniformScale, + Pipeline.getPipeline().buildGA(cv.ctx, + this, geoType, isNonUniformScale, updateAlpha, alpha, ignoreVertexColors, initialVertexIndex, validVertexCount, vertexFormat, @@ -2900,7 +2667,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if((vertexType & TEXCOORD_DEFINED) != 0) vdefined |= TEXCOORD_FLOAT; - buildGAForByRef(cv.ctx, this, geoType, isNonUniformScale, + Pipeline.getPipeline().buildGAForByRef(cv.ctx, + this, geoType, isNonUniformScale, updateAlpha, alpha, ignoreVertexColors, validVertexCount, @@ -2955,7 +2723,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if((vertexType & TEXCOORD_DEFINED) != 0) vdefined |= TEXCOORD_FLOAT; // NOTE : need to add vertex attrs - buildGAForBuffer(cv.ctx, this, geoType, isNonUniformScale, + Pipeline.getPipeline().buildGAForBuffer(cv.ctx, + this, geoType, isNonUniformScale, updateAlpha, alpha, ignoreVertexColors, validVertexCount, @@ -3744,7 +3513,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ gaList.add(Shape3DRetained.getGeomAtom(s)); } - m[k] = VirtualUniverse.mc.getMessage(); + m[k] = new J3dMessage(); m[k].type = J3dMessage.GEOMETRY_CHANGED; // Who to send this message to ? @@ -6297,8 +6066,23 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } } + + //NVaidya + // User may or may not have changed indices in updater callback. + // We need to presume that the user may indeed have and, thus, will + // need to recompute maxCoordIndex unconditionally while + // geomLock is still locked. + if ((vertexFormat & GeometryArray.BY_REFERENCE_INDICES) != 0) { + assert (this instanceof IndexedGeometryArrayRetained); + + if (((IndexedGeometryArrayRetained)this).getCoordIndicesRef() == null) { + nullGeo = true; + } + ((IndexedGeometryArrayRetained)this).doPostUpdaterUpdate(); + } } - dirtyFlag |= VERTEX_CHANGED; + + dirtyFlag |= VERTEX_CHANGED; colorChanged = 0xffff; geomLock.unLock(); @@ -6350,7 +6134,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // Setup bounding planes. Point3d pCoor[] = new Point3d[4]; for(i=0; i<4; i++) - pCoor[i] = getPoint3d(); + pCoor[i] = new Point3d(); // left plane. pCoor[0].set(box.lower.x, box.lower.y, box.lower.z); @@ -6365,8 +6149,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ null, dist, iPnt); } - // free points - for (i=0; i<4; i++) freePoint3d(pCoor[i]); return true; } @@ -6381,7 +6163,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ null, dist, iPnt); } - for (i=0; i<4; i++) freePoint3d(pCoor[i]); return true; } @@ -6396,7 +6177,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ null, dist, iPnt); } - for (i=0; i<4; i++) freePoint3d(pCoor[i]); return true; } // top plane. @@ -6410,7 +6190,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ null, dist, iPnt); } - for (i=0; i<4; i++) freePoint3d(pCoor[i]); return true; } @@ -6425,7 +6204,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ null, dist, iPnt); } - for (i=0; i<4; i++) freePoint3d(pCoor[i]); return true; } @@ -6440,11 +6218,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ null, dist, iPnt); } - for (i=0; i<4; i++) freePoint3d(pCoor[i]); return true; } - - for (i=0; i<4; i++) freePoint3d(pCoor[i]); return false; } @@ -6455,7 +6230,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ Point3d iPnt) { int i, j; - Vector3d tempV3D = getVector3d(); + Vector3d tempV3D = new Vector3d(); boolean esFlag; //Do trivial vertex test. @@ -6473,7 +6248,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ null, dist, iPnt); } - freeVector3d(tempV3D); return true; } } @@ -6493,25 +6267,22 @@ abstract class GeometryArrayRetained extends GeometryRetained{ dist, iPnt); } - freeVector3d(tempV3D); return true; } } if (coordinates.length < 3) { - - freeVector3d(tempV3D); return false; // We're done with line. } // Find rho. // Compute plane normal. - Vector3d vec0 = getVector3d(); // Edge vector from point 0 to point 1; - Vector3d vec1 = getVector3d(); // Edge vector from point 0 to point 2 or 3; - Vector3d pNrm = getVector3d(); - Vector3d pa = getVector3d(); - Point3d q = getPoint3d(); + Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1; + Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3; + Vector3d pNrm = new Vector3d(); + Vector3d pa = new Vector3d(); + Point3d q = new Point3d(); double nLenSq, pqLen, pNrmDotPa, tq; // compute plane normal for coordinates. @@ -6533,12 +6304,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(j == (coordinates.length-1)) { // System.out.println("(1) Degenerate polygon."); - freeVector3d(tempV3D); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freeVector3d(pa); - freePoint3d(q); return false; // Degenerate polygon. } @@ -6554,12 +6319,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ nLenSq = pNrm.lengthSquared(); if( nLenSq == 0.0) { // System.out.println("(2) Degenerate polygon."); - freeVector3d(tempV3D); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freeVector3d(pa); - freePoint3d(q); return false; // Degenerate polygon. } @@ -6572,12 +6331,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ pqLen = Math.sqrt(pNrmDotPa * pNrmDotPa/ nLenSq); if(pqLen > sphere.radius) { - freeVector3d(tempV3D); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freeVector3d(pa); - freePoint3d(q); return false; } @@ -6595,20 +6348,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ pNrm, dist, iPnt); } - freeVector3d(tempV3D); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freeVector3d(pa); - freePoint3d(q); return true; } - freeVector3d(tempV3D); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freeVector3d(pa); - freePoint3d(q); return false; } @@ -6945,8 +6686,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ Point3d end) { double abLenSq, acLenSq, apLenSq, abDotAp, radiusSq; - Vector3d ab = getVector3d(); - Vector3d ap = getVector3d(); + Vector3d ab = new Vector3d(); + Vector3d ap = new Vector3d(); ab.x = end.x - start.x; ab.y = end.y - start.y; @@ -6959,8 +6700,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ abDotAp = ab.dot(ap); if(abDotAp < 0.0) { - freeVector3d(ab); - freeVector3d(ap); return false; // line segment points away from sphere. } @@ -6968,8 +6707,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ acLenSq = abDotAp * abDotAp / abLenSq; if(acLenSq < abLenSq) { - freeVector3d(ab); - freeVector3d(ap); return false; // C doesn't lies between end points of edge. } @@ -6977,13 +6714,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ apLenSq = ap.lengthSquared(); if((apLenSq - acLenSq) <= radiusSq) { - freeVector3d(ab); - freeVector3d(ap); return true; } - freeVector3d(ab); - freeVector3d(ap); return false; } @@ -7095,8 +6828,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ Point3d end, Point3d iPnt) { - Vector3d tempV3d = getVector3d(); - Vector3d direction = getVector3d(); + Vector3d tempV3d = new Vector3d(); + Vector3d direction = new Vector3d(); double pD, pNrmDotrDir, tr; // Compute plane D. @@ -7112,8 +6845,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // edge is parallel to plane. if(pNrmDotrDir== 0.0) { // System.out.println("Edge is parallel to plane."); - freeVector3d(tempV3d); - freeVector3d(direction); return false; } @@ -7125,8 +6856,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // or exceed the edge's length. if((tr < 0.0 ) || (tr > 1.0 )) { // System.out.println("Edge intersects the plane behind the start or exceed end."); - freeVector3d(tempV3d); - freeVector3d(direction); return false; } @@ -7134,8 +6863,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ iPnt.y = start.y + tr * direction.y; iPnt.z = start.z + tr * direction.z; - freeVector3d(tempV3d); - freeVector3d(direction); return true; } @@ -7470,10 +7197,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ boolean intersectTriPnt(Point3d v0, Point3d v1, Point3d v2, Point3d u) { - Vector3d e1 = getVector3d(); - Vector3d e2 = getVector3d(); - Vector3d n1 = getVector3d(); - Vector3d tempV3d = getVector3d(); + Vector3d e1 = new Vector3d(); + Vector3d e2 = new Vector3d(); + Vector3d n1 = new Vector3d(); + Vector3d tempV3d = new Vector3d(); double d1, du; @@ -7490,10 +7217,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(n1.length() == 0.0) { // System.out.println("(1) Degenerate triangle."); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(tempV3d); return false; // Degenerate triangle. } @@ -7509,10 +7232,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // no intersection occurs if(du != 0.0) { - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(tempV3d); return false; } @@ -7549,17 +7268,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // finally, test if u is totally contained in tri. if(pointInTri(u, v0, v1, v2, i0, i1)) { - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(tempV3d); return true; } - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(tempV3d); return false; } @@ -7585,11 +7296,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ Point3d u0, Point3d u1, Point3d u2) { // System.out.println("In intersectTriTri ..."); - Vector3d e1 = getVector3d(); - Vector3d e2 = getVector3d(); - Vector3d n1 = getVector3d(); - Vector3d n2 = getVector3d(); - Vector3d tempV3d = getVector3d(); + Vector3d e1 = new Vector3d(); + Vector3d e2 = new Vector3d(); + Vector3d n1 = new Vector3d(); + Vector3d n2 = new Vector3d(); + Vector3d tempV3d = new Vector3d(); double d1, d2; double du0, du1, du2, dv0, dv1, dv2; @@ -7612,11 +7323,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(n1.length() == 0.0) { // System.out.println("(1) Degenerate triangle."); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(n2); - freeVector3d(tempV3d); return false; // Degenerate triangle. } @@ -7644,11 +7350,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // no intersection occurs if(du0du1>0.0 && du0du2>0.0) { // System.out.println("In intersectTriTri : du0du1>0.0 && du0du2>0.0"); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(n2); - freeVector3d(tempV3d); return false; } @@ -7665,11 +7366,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(n2.length() == 0.0) { // System.out.println("(2) Degenerate triangle."); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(n2); - freeVector3d(tempV3d); return false; // Degenerate triangle. } @@ -7697,11 +7393,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // no intersection occurs if(dv0dv1>0.0 && dv0dv2>0.0) { // System.out.println("In intersectTriTri : dv0dv1>0.0 && dv0dv2>0.0"); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(n2); - freeVector3d(tempV3d); return false; } // compute direction of intersection line. @@ -7782,11 +7473,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ else { // triangles are coplanar boolean toreturn = coplanarTriTri(n1, v0, v1, v2, u0, u1, u2); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(n2); - freeVector3d(tempV3d); return toreturn; } @@ -7821,11 +7507,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // triangles are coplanar // System.out.println("In intersectTriTri : coplanarTriTri test 2"); boolean toreturn = coplanarTriTri(n2, v0, v1, v2, u0, u1, u2); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(n2); - freeVector3d(tempV3d); return toreturn; } @@ -7859,20 +7540,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(isect1E<isect2S || isect2E<isect1S) { // System.out.println("In intersectTriTri :isect1E<isect2S || isect2E<isect1S"); // System.out.println("In intersectTriTri : return false"); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(n2); - freeVector3d(tempV3d); return false; } // System.out.println("In intersectTriTri : return true"); - freeVector3d(e1); - freeVector3d(e2); - freeVector3d(n1); - freeVector3d(n2); - freeVector3d(tempV3d); return true; } @@ -7881,9 +7552,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ boolean intersectPolygon(Point3d coord1[], Point3d coord2[]) { int i, j; - Vector3d vec0 = getVector3d(); // Edge vector from point 0 to point 1; - Vector3d vec1 = getVector3d(); // Edge vector from point 0 to point 2 or 3; - Vector3d pNrm = getVector3d(); + Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1; + Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3; + Vector3d pNrm = new Vector3d(); boolean epFlag; @@ -7906,9 +7577,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(j == (coord1.length-1)) { // System.out.println("(1) Degenerate polygon."); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); return false; // Degenerate polygon. } @@ -7923,16 +7591,13 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(pNrm.length() == 0.0) { // System.out.println("(2) Degenerate polygon."); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); return false; // Degenerate polygon. } j = 0; Point3d seg[] = new Point3d[2]; - seg[0] = getPoint3d(); - seg[1] = getPoint3d(); + seg[0] = new Point3d(); + seg[1] = new Point3d(); for(i=0; i<coord2.length; i++) { if(i < (coord2.length-1)) @@ -7949,29 +7614,14 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } if (j==0) { - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freePoint3d(seg[0]); - freePoint3d(seg[1]); return false; } if (coord2.length < 3) { boolean toreturn = pointIntersectPolygon2D(pNrm, coord1, seg[0]); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freePoint3d(seg[0]); - freePoint3d(seg[1]); return toreturn; } else { boolean toreturn = edgeIntersectPolygon2D(pNrm, coord1, seg); - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freePoint3d(seg[0]); - freePoint3d(seg[1]); return toreturn; } } @@ -7997,12 +7647,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ boolean intersectSegment( Point3d coordinates[], Point3d start, Point3d end, double dist[], Point3d iPnt ) { boolean result; - Vector3d direction = getVector3d(); + Vector3d direction = new Vector3d(); direction.x = end.x - start.x; direction.y = end.y - start.y; direction.z = end.z - start.z; result = intersectRayOrSegment(coordinates, direction, start, dist, iPnt, true); - freeVector3d(direction); return result; } @@ -8016,9 +7665,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ Vector3d direction, Point3d origin, double dist[], Point3d iPnt, boolean isSegment) { Vector3d vec0, vec1, pNrm, tempV3d; - vec0 = getVector3d(); - vec1 = getVector3d(); - pNrm = getVector3d(); + vec0 = new Vector3d(); + vec1 = new Vector3d(); + pNrm = new Vector3d(); double absNrmX, absNrmY, absNrmZ, pD = 0.0; double pNrmDotrDir = 0.0; @@ -8070,9 +7719,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ iPnt); // put the Vectors on the freelist - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); return isIntersect; } @@ -8101,14 +7747,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ break; } } - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); return isIntersect; } // Plane equation: (p - p0)*pNrm = 0 or p*pNrm = pD; - tempV3d = getVector3d(); + tempV3d = new Vector3d(); tempV3d.set((Tuple3d) coordinates[0]); pD = pNrm.dot(tempV3d); tempV3d.set((Tuple3d) origin); @@ -8124,10 +7767,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ (isSegment && (dist[0] > 1.0+EPS))) { // Ray intersects the plane behind the ray's origin // or intersect point not fall in Segment - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freeVector3d(tempV3d); return false; } @@ -8288,10 +7927,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (isIntersect) { dist[0] *= direction.length(); } - freeVector3d(vec0); - freeVector3d(vec1); - freeVector3d(pNrm); - freeVector3d(tempV3d); return isIntersect; } @@ -8428,7 +8063,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // System.out.println("start " + start + " end " + end ); // System.out.println("ori " + ori + " dir " + dir); - lDir = getVector3d(); + lDir = new Vector3d(); lDir.x = (end.x - start.x); lDir.y = (end.y - start.y); lDir.z = (end.z - start.z); @@ -8449,7 +8084,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ iPnt.set(start); } } - freeVector3d(lDir); return isIntersect; } // Find the inverse. @@ -8468,12 +8102,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(s<0.0) { // Before the origin of ray. // System.out.println("Before the origin of ray " + s); - freeVector3d(lDir); return false; } if((t<0)||(t>1.0)) {// Before or after the end points of line. // System.out.println("Before or after the end points of line. " + t); - freeVector3d(lDir); return false; } @@ -8482,7 +8114,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if((tmp1 < (tmp2 - EPS)) || (tmp1 > (tmp2 + EPS))) { // System.out.println("No intersection : tmp1 " + tmp1 + " tmp2 " + tmp2); - freeVector3d(lDir); return false; } @@ -8496,7 +8127,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } // System.out.println("Intersected : tmp1 " + tmp1 + " tmp2 " + tmp2); - freeVector3d(lDir); return true; } @@ -8507,11 +8137,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ boolean intersectCylinder(Point3d coordinates[], PickCylinder cyl, double dist[], Point3d iPnt) { - Point3d origin = getPoint3d(); - Point3d end = getPoint3d(); - Vector3d direction = getVector3d(); - Point3d iPnt1 = getPoint3d(); - Vector3d originToIpnt = getVector3d(); + Point3d origin = new Point3d(); + Point3d end = new Point3d(); + Vector3d direction = new Vector3d(); + Point3d iPnt1 = new Point3d(); + Vector3d originToIpnt = new Vector3d(); if (iPnt == null) { iPnt = new Point3d(); @@ -8532,24 +8162,12 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (cyl instanceof PickCylinderRay) { if (intersectRay(coordinates, new PickRay(origin, direction), - dist, iPnt)) { - - freePoint3d(origin); - freePoint3d(end); - freeVector3d(direction); - freeVector3d(originToIpnt); - freePoint3d(iPnt1); - + dist, iPnt)) { return true; } } else { if (intersectSegment(coordinates, origin, end, dist, iPnt)) { - freePoint3d(origin); - freePoint3d(end); - freeVector3d(direction); - freeVector3d(originToIpnt); - freePoint3d(iPnt1); return true; } } @@ -8575,19 +8193,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (sqDistToEdge <= radius*radius) { originToIpnt.sub (iPnt1, origin); dist[0] = originToIpnt.length(); - freePoint3d(origin); - freePoint3d(end); - freeVector3d(direction); - freeVector3d(originToIpnt); - freePoint3d(iPnt1); return true; } } - freePoint3d(origin); - freePoint3d(end); - freeVector3d(direction); - freeVector3d(originToIpnt); - freePoint3d(iPnt1); return false; } @@ -8598,14 +8206,14 @@ abstract class GeometryArrayRetained extends GeometryRetained{ boolean intersectCone(Point3d coordinates[], PickCone cone, double[] dist, Point3d iPnt) { - Point3d origin = getPoint3d(); - Point3d end = getPoint3d(); - Vector3d direction = getVector3d(); - Vector3d originToIpnt = getVector3d(); + Point3d origin = new Point3d(); + Point3d end = new Point3d(); + Vector3d direction = new Vector3d(); + Vector3d originToIpnt = new Vector3d(); double distance; - Point3d iPnt1 = getPoint3d(); - Vector3d vector = getVector3d(); + Point3d iPnt1 = new Point3d(); + Vector3d vector = new Vector3d(); if (iPnt == null) { iPnt = new Point3d(); @@ -8626,23 +8234,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (intersectRay(coordinates, new PickRay (origin, direction), dist, iPnt)) { - freePoint3d(origin); - freePoint3d(end); - freePoint3d(iPnt1); - freeVector3d(direction); - freeVector3d(originToIpnt); - freeVector3d(vector); return true; } } else { if (intersectSegment(coordinates, origin, end, dist, iPnt)) { - freePoint3d(origin); - freePoint3d(end); - freePoint3d(iPnt1); - freeVector3d(direction); - freeVector3d(originToIpnt); - freeVector3d(vector); return true; } } @@ -8671,21 +8267,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (sqDistToEdge <= radius*radius) { // System.out.println ("intersectCone: edge "+i+" intersected"); dist[0] = distance; - freePoint3d(origin); - freePoint3d(end); - freePoint3d(iPnt1); - freeVector3d(direction); - freeVector3d(originToIpnt); - freeVector3d(vector); return true; } } - freePoint3d(origin); - freePoint3d(end); - freePoint3d(iPnt1); - freeVector3d(direction); - freeVector3d(originToIpnt); - freeVector3d(vector); return false; } @@ -8697,11 +8281,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ boolean intersectCylinder(Point3d pt, PickCylinder cyl, double[] dist) { - Point3d origin = getPoint3d(); - Point3d end = getPoint3d(); - Vector3d direction = getVector3d(); - Point3d iPnt = getPoint3d(); - Vector3d originToIpnt = getVector3d(); + Point3d origin = new Point3d(); + Point3d end = new Point3d(); + Vector3d direction = new Vector3d(); + Point3d iPnt = new Point3d(); + Vector3d originToIpnt = new Vector3d(); // Get cylinder information cyl.getOrigin (origin); @@ -8719,18 +8303,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (sqDist <= radius*radius) { originToIpnt.sub (iPnt, origin); dist[0] = originToIpnt.length(); - freePoint3d(origin); - freePoint3d(end); - freePoint3d(iPnt); - freeVector3d(originToIpnt); - freeVector3d(direction); return true; } - freePoint3d(origin); - freePoint3d(end); - freePoint3d(iPnt); - freeVector3d(originToIpnt); - freeVector3d(direction); return false; } @@ -8740,11 +8314,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ */ boolean intersectCone(Point3d pt, PickCone cone, double[] dist) { - Point3d origin = getPoint3d(); - Point3d end = getPoint3d(); - Vector3d direction = getVector3d(); - Point3d iPnt = getPoint3d(); - Vector3d originToIpnt = getVector3d(); + Point3d origin = new Point3d(); + Point3d end = new Point3d(); + Vector3d direction = new Vector3d(); + Point3d iPnt = new Point3d(); + Vector3d originToIpnt = new Vector3d(); // Get cone information cone.getOrigin (origin); @@ -8769,11 +8343,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ radius = Math.tan (cone.getSpreadAngle()) * distance; if (sqDist <= radius*radius) { dist[0] = distance; - freePoint3d(origin); - freePoint3d(end); - freePoint3d(iPnt); - freeVector3d(direction); - freeVector3d(originToIpnt); return true; } return false; @@ -10713,18 +10282,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } - protected void finalize() { - // For Pure immediate mode, there is no clearLive so - // surface will free when JVM do GC - if (pVertexBuffers != 0) { - // memory not yet free for immediate mode rendering - // It is thread safe since D3D only free surface in - // the next swapBuffer() call which must be in the - // same renderer threads - freeD3DArray(true); - } - } - void freeDlistId() { if (dlistId != -1) { VirtualUniverse.mc.freeDisplayListId(dlistObj); @@ -11115,28 +10672,26 @@ abstract class GeometryArrayRetained extends GeometryRetained{ boolean intersect(Transform3D thisLocalToVworld, Transform3D otherLocalToVworld, GeometryRetained geom) { - Transform3D tg = VirtualUniverse.mc.getTransform3D(null); + Transform3D t3d = new Transform3D(); boolean isIntersect = false; if (geom instanceof GeometryArrayRetained ) { GeometryArrayRetained geomArray = (GeometryArrayRetained) geom; if (geomArray.validVertexCount >= validVertexCount) { - tg.invert(otherLocalToVworld); - tg.mul(thisLocalToVworld); - isIntersect = intersect(tg, geom); + t3d.invert(otherLocalToVworld); + t3d.mul(thisLocalToVworld); + isIntersect = intersect(t3d, geom); } else { - tg.invert(thisLocalToVworld); - tg.mul(otherLocalToVworld); - isIntersect = geomArray.intersect(tg, this); + t3d.invert(thisLocalToVworld); + t3d.mul(otherLocalToVworld); + isIntersect = geomArray.intersect(t3d, this); } } else { - tg.invert(thisLocalToVworld); - tg.mul(otherLocalToVworld); - isIntersect = geom.intersect(tg, this); + t3d.invert(thisLocalToVworld); + t3d.mul(otherLocalToVworld); + isIntersect = geom.intersect(t3d, this); } - - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, tg); return isIntersect; } @@ -11525,23 +11080,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ dist[0] = Math.sqrt(dist[0]); } - Vector3d getVector3d() { - return (Vector3d)FreeListManager.getObject(FreeListManager.VECTOR3D); - } - - void freeVector3d(Vector3d v) { - FreeListManager.freeObject(FreeListManager.VECTOR3D, v); - } - - Point3d getPoint3d() { - return (Point3d)FreeListManager.getObject(FreeListManager.POINT3D); - } - - void freePoint3d(Point3d p) { - FreeListManager.freeObject(FreeListManager.POINT3D, p); - } - - void handleFrequencyChange(int bit) { int mask = 0; if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { diff --git a/src/classes/share/javax/media/j3d/GeometryAtom.java b/src/classes/share/javax/media/j3d/GeometryAtom.java index 087ebdf..659230b 100644 --- a/src/classes/share/javax/media/j3d/GeometryAtom.java +++ b/src/classes/share/javax/media/j3d/GeometryAtom.java @@ -177,7 +177,7 @@ class GeometryAtom extends Object implements BHLeafInterface, NnuId { ra.rListInfo[j] = new RenderAtomListInfo(); ra.rListInfo[j].renderAtom = ra; ra.rListInfo[j].index = j; - ra.rListInfo[j].localToVworld = VirtualUniverse.mc.getTransform3D(null); + ra.rListInfo[j].localToVworld = new Transform3D(); } } @@ -213,7 +213,7 @@ class GeometryAtom extends Object implements BHLeafInterface, NnuId { ra.rListInfo[j] = new RenderAtomListInfo(); ra.rListInfo[j].renderAtom = ra; ra.rListInfo[j].index = j; - ra.rListInfo[j].localToVworld = VirtualUniverse.mc.getTransform3D(null); + ra.rListInfo[j].localToVworld = new Transform3D(); } } } diff --git a/src/classes/share/javax/media/j3d/GeometryRetained.java b/src/classes/share/javax/media/j3d/GeometryRetained.java index 183dba4..3c93e37 100644 --- a/src/classes/share/javax/media/j3d/GeometryRetained.java +++ b/src/classes/share/javax/media/j3d/GeometryRetained.java @@ -213,9 +213,7 @@ abstract class GeometryRetained extends NodeComponentRetained { abstract void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, - boolean multiScreen, int screen, - boolean ignoreVertexColors, - int pass); + int screen, boolean ignoreVertexColors); /** * This method should return an int indicating the format of the vertices, @@ -274,21 +272,19 @@ abstract class GeometryRetained extends NodeComponentRetained { boolean intersect(Transform3D thisLocalToVworld, Transform3D otherLocalToVworld, GeometryRetained geom) { - Transform3D tg = VirtualUniverse.mc.getTransform3D(null); - tg.invert(otherLocalToVworld); - tg.mul(thisLocalToVworld); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, tg); - return intersect(tg, geom); + Transform3D t3d = new Transform3D(); + t3d.invert(otherLocalToVworld); + t3d.mul(thisLocalToVworld); + return intersect(t3d, geom); } boolean intersect(Transform3D thisLocalToVworld, Bounds targetBound) { Bounds transBound = (Bounds) targetBound.clone(); - Transform3D tg = VirtualUniverse.mc.getTransform3D(null); - tg.invert(thisLocalToVworld); - transBound.transform(tg); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, tg); + Transform3D t3d = new Transform3D(); + t3d.invert(thisLocalToVworld); + transBound.transform(t3d); return intersect(transBound); } diff --git a/src/classes/share/javax/media/j3d/GeometryStructure.java b/src/classes/share/javax/media/j3d/GeometryStructure.java index a0ea460..bddfac0 100644 --- a/src/classes/share/javax/media/j3d/GeometryStructure.java +++ b/src/classes/share/javax/media/j3d/GeometryStructure.java @@ -306,8 +306,7 @@ class GeometryStructure extends J3dStructure { addBgGeometryAtomList(geomAtom); continue; } - BHLeafNode bhLeafNode = (BHLeafNode) - VirtualUniverse.mc.getBHNode(BHNode.BH_TYPE_LEAF); + BHLeafNode bhLeafNode = new BHLeafNode(); bhLeafNode.leafIF = geomAtom; geomAtom.bhLeafNode = bhLeafNode; bhLeafNode.computeBoundingHull(); @@ -317,8 +316,7 @@ class GeometryStructure extends J3dStructure { } else if (node instanceof GroupRetained) { synchronized (node) { GroupRetained group = (GroupRetained) node; - BHLeafNode bhLeafNode = (BHLeafNode) - VirtualUniverse.mc.getBHNode(BHNode.BH_TYPE_LEAF); + BHLeafNode bhLeafNode = new BHLeafNode(); bhLeafNode.leafIF = group; group.bhLeafNode = bhLeafNode; bhLeafNode.computeBoundingHull(); diff --git a/src/classes/share/javax/media/j3d/GraphicsConfigInfo.java b/src/classes/share/javax/media/j3d/GraphicsConfigInfo.java index 56711dc..a6bbcbb 100644 --- a/src/classes/share/javax/media/j3d/GraphicsConfigInfo.java +++ b/src/classes/share/javax/media/j3d/GraphicsConfigInfo.java @@ -12,24 +12,33 @@ package javax.media.j3d; +/** + * Container for the GraphicsTemplate3D and other private data about a selected + * GraphicsConfiguration. An instance of this class is created along with an + * instance of GrahpicsConfiguration, whenever getBestConfiguration is called. + */ class GraphicsConfigInfo { - private int reqStencilSize = 0; - private long fbConfig = 0L; + private GraphicsConfigTemplate3D graphicsConfigTemplate3D = null; + private Object privateData = null; - int getRequestedStencilSize() { - return reqStencilSize; + GraphicsConfigInfo(GraphicsConfigTemplate3D graphicsConfigTemplate3D) { + setGraphicsConfigTemplate3D(graphicsConfigTemplate3D); } - void setRequestedStencilSize(int reqSS) { - reqStencilSize = reqSS; + GraphicsConfigTemplate3D getGraphicsConfigTemplate3D() { + return graphicsConfigTemplate3D; } - - long getFBConfig() { - return fbConfig; + + void setGraphicsConfigTemplate3D(GraphicsConfigTemplate3D graphicsConfigTemplate3D) { + this.graphicsConfigTemplate3D = graphicsConfigTemplate3D; } - - void setFBConfig(long fbC) { - fbConfig = fbC; + + Object getPrivateData() { + return privateData; + } + + void setPrivateData(Object privateData) { + this.privateData = privateData; } } diff --git a/src/classes/share/javax/media/j3d/GraphicsConfigTemplate3D.java b/src/classes/share/javax/media/j3d/GraphicsConfigTemplate3D.java index 99536cc..a09d879 100644 --- a/src/classes/share/javax/media/j3d/GraphicsConfigTemplate3D.java +++ b/src/classes/share/javax/media/j3d/GraphicsConfigTemplate3D.java @@ -46,15 +46,7 @@ public class GraphicsConfigTemplate3D extends GraphicsConfigTemplate { static Object globalLock = new Object(); static Object monitorLock = new Object(); - static boolean threadWaiting = false; - - /** - * The platform dependent template. Since there is no - * template-specific instance data in the NativeConfigTemplate3D - * class, we can create one statically. - */ - static NativeConfigTemplate3D nativeTemplate = - new NativeConfigTemplate3D(); + static volatile boolean threadWaiting = false; /** * Constructs a GraphicsConfigTemplate3D object with default parameters. @@ -387,7 +379,8 @@ public class GraphicsConfigTemplate3D extends GraphicsConfigTemplate { synchronized (monitorLock) { switch (action) { case J3dThread.WAIT: - if (threadWaiting) { + // Issue 279 - loop until ready + while (threadWaiting) { try { monitorLock.wait(); } catch (InterruptedException e) { diff --git a/src/classes/share/javax/media/j3d/GraphicsContext3D.java b/src/classes/share/javax/media/j3d/GraphicsContext3D.java index 1369f32..8bfd972 100644 --- a/src/classes/share/javax/media/j3d/GraphicsContext3D.java +++ b/src/classes/share/javax/media/j3d/GraphicsContext3D.java @@ -12,6 +12,8 @@ package javax.media.j3d; +import java.awt.Point; +import java.awt.image.BufferedImage; import javax.vecmath.*; import java.util.Vector; import java.util.Enumeration; @@ -100,8 +102,6 @@ public class GraphicsContext3D extends Object { */ Canvas3D canvas3d = null; - int objectId = -1; - // // Graphics state // @@ -281,7 +281,8 @@ public class GraphicsContext3D extends Object { static final int FLUSH2D = 23; static final int DRAWANDFLUSH2D = 24; static final int SET_MODELCLIP = 25; - static final int NCOMMANDS = 26; // needs to be incremented + static final int DISPOSE2D = 26; + static final int NCOMMANDS = 27; // needs to be incremented // when a new command is to be // added to the list @@ -296,11 +297,9 @@ public class GraphicsContext3D extends Object { private static final int BUFFER_MODE = 0x1; private int dirtyMask = 0; - // multi-texture private int numActiveTexUnit = 0; private int lastActiveTexUnitIndex = 0; - private boolean toSimulateMultiTex = false; // for read raster private volatile boolean readRasterReady = false; @@ -341,17 +340,62 @@ public class GraphicsContext3D extends Object { * If the Appearance object is null, default values will be used * for all appearance attributes - it is as if an * Appearance node were created using the default constructor. + * * @param appearance the new Appearance object + * + * @exception IllegalSharingException if the specified appearance refers + * to an ImageComponent2D that is being used by a Canvas3D as + * an off-screen buffer. */ public void setAppearance(Appearance appearance) { - - if(appearance == null) { - if(defaultAppearance == null) { - defaultAppearance = new Appearance(); - } - appearance = defaultAppearance; - } - + + if(appearance == null) { + if(defaultAppearance == null) { + defaultAppearance = new Appearance(); + } + appearance = defaultAppearance; + } else { + // Check whether any ImageComponent2D referred to by + // the new appearance is being used as an off-screen buffer and throw + // IllegalSharingException if it is. + TextureRetained texRetained; + ImageComponent[] images; + AppearanceRetained appRetained = (AppearanceRetained)appearance.retained; + if(appRetained.texture != null) { + assert (appRetained.texUnitState == null); + texRetained = appRetained.texture; + images = texRetained.getImages(); + if(images != null) { + for(int i=0; i<images.length; i++) { + if(images[i] != null) { + ImageComponentRetained imageRetained = (ImageComponentRetained) images[i].retained; + // Do illegal sharing check + if(imageRetained.getUsedByOffScreen()) { + throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D30")); + } + } + } + } + } + else if(appRetained.texUnitState != null) { + for(int j=0; j<appRetained.texUnitState.length; j++) { + texRetained = appRetained.texUnitState[j].texture; + images = texRetained.getImages(); + if(images != null) { + for(int i=0; i<images.length; i++) { + if(images[i] != null) { + ImageComponentRetained imageRetained = (ImageComponentRetained) images[i].retained; + // Do illegal sharing check + if(imageRetained.getUsedByOffScreen()) { + throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D30")); + } + } + } + } + } + } + } + uAppearance = appearance; if ((canvas3d.view == null) || (canvas3d.view.universe == null) || @@ -591,16 +635,34 @@ public class GraphicsContext3D extends Object { * the canvas prior to rendering a new frame. The Background * node's application region is ignored for immediate-mode * rendering. + * * @param background the new Background object + * * @exception IllegalSharingException if the Background node * is part of or is subsequently made part of a live scene graph. + * + * @exception IllegalSharingException if the specified background node + * refers to an ImageComponent2D that is being used by a Canvas3D as + * an off-screen buffer. */ public void setBackground(Background background) { + if (background.isLive()) { throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D11")); } - if (((BackgroundRetained)background.retained).geometryBranch != null) + BackgroundRetained bgRetained = (BackgroundRetained)background.retained; + ImageComponent2D image = bgRetained.getImage(); + if(image != null) { + ImageComponent2DRetained imageRetained = (ImageComponent2DRetained) image.retained; + if(imageRetained.getUsedByOffScreen()) { + throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D31")); + } + } + + if (((BackgroundRetained)background.retained).geometryBranch != null) { throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D22")); + } + uBackground = background; if ((canvas3d.view == null) || (canvas3d.view.universe == null) || @@ -1068,7 +1130,7 @@ public class GraphicsContext3D extends Object { doSetModelTransform(t); } else { - Transform3D uModelTransform = VirtualUniverse.mc.getTransform3D(t); + Transform3D uModelTransform = new Transform3D(t); //Transform3D uModelTransform = t; if (Thread.currentThread() == canvas3d.view.universe.behaviorScheduler) { @@ -1102,7 +1164,7 @@ public class GraphicsContext3D extends Object { (Thread.currentThread() == canvas3d.screen.renderer)) { doMultiplyModelTransform(t); } else { - Transform3D tt = VirtualUniverse.mc.getTransform3D(t); + Transform3D tt = new Transform3D(t); if (Thread.currentThread() == canvas3d.view.universe.behaviorScheduler) { sendRenderMessage(false, GraphicsContext3D.MULTIPLY_MODEL_TRANSFORM, tt, null); @@ -1604,33 +1666,33 @@ public class GraphicsContext3D extends Object { } void doClear() { - + if (!canvas3d.firstPaintCalled) - return; - - RenderBin rb = canvas3d.view.renderBin; - BackgroundRetained back = null; - - - if (this.background != null) - back = (BackgroundRetained)this.background.retained; - else - back = this.black; - - // XXXX: This should ideally be done by the renderer (or by the - // canvas itself) when the canvas is first added to a view. - /* - if ((canvas3d.screen.renderer != null) && - (canvas3d.screen.renderer.renderBin == null)) - canvas3d.screen.renderer.renderBin = rb; - */ - // If we are in pure immediate mode, update the view cache - if (!canvas3d.isRunning) - updateViewCache(rb); - + return; + + RenderBin rb = canvas3d.view.renderBin; + BackgroundRetained back = null; + + + if (this.background != null) + back = (BackgroundRetained)this.background.retained; + else + back = this.black; + + // XXXX: This should ideally be done by the renderer (or by the + // canvas itself) when the canvas is first added to a view. + /* + if ((canvas3d.screen.renderer != null) && + (canvas3d.screen.renderer.renderBin == null)) + canvas3d.screen.renderer.renderBin = rb; + */ + // If we are in pure immediate mode, update the view cache + if (!canvas3d.isRunning) + updateViewCache(rb); + // We need to catch NullPointerException when the dsi // gets yanked from us during a remove. - + try { // Issue 78 - need to get the drawingSurface info every // frame; this is necessary since the HDC (window ID) @@ -1639,215 +1701,167 @@ public class GraphicsContext3D extends Object { if (!canvas3d.offScreen) { canvas3d.drawingSurfaceObject.getDrawingSurfaceObjectInfo(); } - - if (canvas3d.drawingSurfaceObject.renderLock()) { - // XXXX : Fix texture - /* - if (canvas3d.useSharedCtx) { - if (canvas3d.screen.renderer.sharedCtx == 0) { - synchronized (VirtualUniverse.mc.contextCreationLock) { - canvas3d.screen.renderer.sharedCtx = canvas3d.createNewContext( - canvas3d.screen.display, - canvas3d.window, canvas3d.vid, 0, true, - canvas3d.offScreen); - canvas3d.screen.renderer.sharedCtxTimeStamp = - VirtualUniverse.mc.getContextTimeStamp(); - canvas3d.screen.renderer.needToRebuildDisplayList = true; - } - } - } - */ - - if (canvas3d.ctx == 0) { - synchronized (VirtualUniverse.mc.contextCreationLock) { - canvas3d.ctx = canvas3d.createNewContext(0, false); - if (canvas3d.ctx == 0) { - canvas3d.drawingSurfaceObject.unLock(); - return; - } - - canvas3d.ctxTimeStamp = - VirtualUniverse.mc.getContextTimeStamp(); - canvas3d.screen.renderer.listOfCtxs.add( - new Long(canvas3d.ctx)); - canvas3d.screen.renderer.listOfCanvases.add(canvas3d); - - canvas3d.beginScene(); - - if (canvas3d.graphics2D != null) { - canvas3d.graphics2D.init(); - } - + + if (canvas3d.drawingSurfaceObject.renderLock()) { + // XXXX : Fix texture + /* + if (canvas3d.useSharedCtx) { + if (canvas3d.screen.renderer.sharedCtx == 0) { + synchronized (VirtualUniverse.mc.contextCreationLock) { + canvas3d.screen.renderer.sharedCtx = canvas3d.createNewContext( + canvas3d.screen.display, + canvas3d.window, 0, true, + canvas3d.offScreen); + canvas3d.screen.renderer.sharedCtxTimeStamp = + VirtualUniverse.mc.getContextTimeStamp(); + canvas3d.screen.renderer.needToRebuildDisplayList = true; + } + } + } + */ + + if (canvas3d.ctx == null) { + synchronized (VirtualUniverse.mc.contextCreationLock) { + canvas3d.ctx = canvas3d.createNewContext(null, false); + if (canvas3d.ctx == null) { + canvas3d.drawingSurfaceObject.unLock(); + return; + } + + canvas3d.ctxTimeStamp = + VirtualUniverse.mc.getContextTimeStamp(); + canvas3d.screen.renderer.listOfCtxs.add(canvas3d.ctx); + canvas3d.screen.renderer.listOfCanvases.add(canvas3d); + + canvas3d.beginScene(); + + if (canvas3d.graphics2D != null) { + canvas3d.graphics2D.init(); + } + // enable separate specular color - canvas3d.enableSeparateSpecularColor(); - } - + canvas3d.enableSeparateSpecularColor(); + } + // create the cache texture state in canvas // for state download checking purpose if (canvas3d.texUnitState == null) { canvas3d.createTexUnitState(); } - - // Create the texture unit state map - if (canvas3d.texUnitStateMap == null) { - canvas3d.createTexUnitStateMap(); + + canvas3d.drawingSurfaceObject.contextValidated(); + canvas3d.screen.renderer.currentCtx = canvas3d.ctx; + canvas3d.screen.renderer.currentDrawable = canvas3d.drawable; + initializeState(); + canvas3d.ctxChanged = true; + canvas3d.canvasDirty = 0xffff; + // Update Appearance + updateState(rb, RenderMolecule.SURFACE); + + canvas3d.currentLights = new + LightRetained[canvas3d.getNumCtxLights(canvas3d.ctx)]; + + for (int j=0; j<canvas3d.currentLights.length; j++) { + canvas3d.currentLights[j] = null; } + } + + + canvas3d.makeCtxCurrent(); + + if ((dirtyMask & BUFFER_MODE) != 0) { + if (bufferOverride) { + canvas3d.setRenderMode(canvas3d.ctx, stereoMode, + canvas3d.useDoubleBuffer && !frontBufferRendering); + } else { + if (!canvas3d.isRunning) { + canvas3d.setRenderMode(canvas3d.ctx, + Canvas3D.FIELD_ALL, + canvas3d.useDoubleBuffer); + } + } + dirtyMask &= ~BUFFER_MODE; + } + + Dimension size = canvas3d.getSize(); + int winWidth = size.width; + int winHeight = size.height; + boolean isByRefBackgroundImage = false; + if (back.image != null) { + if (back.image.isByReference()) { + back.image.geomLock.getLock(); + isByRefBackgroundImage = true; + } + + back.image.evaluateExtensions(canvas3d); + } + + canvas3d.clear(back, winWidth, winHeight); - canvas3d.drawingSurfaceObject.contextValidated(); - canvas3d.screen.renderer.currentCtx = canvas3d.ctx; - canvas3d.screen.renderer.currentWindow = canvas3d.window; - initializeState(); - canvas3d.ctxChanged = true; - canvas3d.canvasDirty = 0xffff; - // Update Appearance - updateState(rb, RenderMolecule.SURFACE); - - canvas3d.currentLights = new - LightRetained[canvas3d.getNumCtxLights(canvas3d.ctx)]; - - for (int j=0; j<canvas3d.currentLights.length; j++) { - canvas3d.currentLights[j] = null; - } - } - - - canvas3d.makeCtxCurrent(); - - if ((dirtyMask & BUFFER_MODE) != 0) { - if (bufferOverride) { - canvas3d.setRenderMode(canvas3d.ctx, stereoMode, - canvas3d.useDoubleBuffer && !frontBufferRendering); - } else { - if (!canvas3d.isRunning) { - canvas3d.setRenderMode(canvas3d.ctx, - Canvas3D.FIELD_ALL, - canvas3d.useDoubleBuffer); - } - } - dirtyMask &= ~BUFFER_MODE; - } - - Dimension size = canvas3d.getSize(); - int winWidth = size.width; - int winHeight = size.height; - - if (back.image != null && back.image.isByReference()) { - back.image.geomLock.getLock(); - back.image.evaluateExtensions(canvas3d.extensionsSupported); - if (!VirtualUniverse.mc.isBackgroundTexture) { - canvas3d.clear(canvas3d.ctx, - back.color.x, back.color.y, - back.color.z, winWidth, winHeight, back.image, - back.imageScaleMode, - back.image != null?back.image.imageYdown[0]:null); - } - else { - - // this is if the background image resizes with the canvas -// Dimension size = null; -// canvas3d.getSize(size); -// int xmax = size.width; -// int ymax = size.height; - if (objectId == -1) { - objectId = VirtualUniverse.mc.getTexture2DId(); - } - - canvas3d.textureclear(canvas3d.ctx, - back.xmax, back.ymax, - back.color.x, back.color.y, - back.color.z, winWidth, winHeight, - objectId, back.imageScaleMode, back.texImage, true); - } - back.image.geomLock.unLock(); - } - else { - if (!VirtualUniverse.mc.isBackgroundTexture) { - canvas3d.clear(canvas3d.ctx, - back.color.x, back.color.y, - back.color.z, winWidth, winHeight, back.image, - back.imageScaleMode, - back.image != null?back.image.imageYdown[0]:null); - } - else { - - // this is if the background image resizes with the canvas -// Dimension size = null; -// canvas3d.getSize(size); -// int xmax = size.width; -// int ymax = size.height; - if (objectId == -1) { - objectId = VirtualUniverse.mc.getTexture2DId(); - } - - canvas3d.textureclear(canvas3d.ctx, - back.xmax, back.ymax, - back.color.x, back.color.y, - back.color.z, - winWidth, winHeight, - objectId, back.imageScaleMode, back.texImage, true); - } - } - - // Set the viewport and view matrices - if (!canvas3d.isRunning) { - CanvasViewCache cvCache = canvas3d.canvasViewCache; - canvas3d.setViewport(canvas3d.ctx, - 0, 0, - cvCache.getCanvasWidth(), - cvCache.getCanvasHeight()); - if (bufferOverride && (stereoMode == STEREO_RIGHT)) { - canvas3d.setProjectionMatrix(canvas3d.ctx, - cvCache.getRightProjection().mat); - canvas3d.setModelViewMatrix(canvas3d.ctx, - cvCache.getRightVpcToEc().mat, - rb.vworldToVpc); - } - else { - canvas3d.setProjectionMatrix(canvas3d.ctx, - cvCache.getLeftProjection().mat); - canvas3d.setModelViewMatrix(canvas3d.ctx, - cvCache.getLeftVpcToEc().mat, - rb.vworldToVpc); - } - } - - canvas3d.drawingSurfaceObject.unLock(); - } - } catch (NullPointerException ne) { - canvas3d.drawingSurfaceObject.unLock(); - throw ne; - } + if (isByRefBackgroundImage) { + back.image.geomLock.unLock(); + } + + + // Set the viewport and view matrices + if (!canvas3d.isRunning) { + CanvasViewCache cvCache = canvas3d.canvasViewCache; + canvas3d.setViewport(canvas3d.ctx, + 0, 0, + cvCache.getCanvasWidth(), + cvCache.getCanvasHeight()); + if (bufferOverride && (stereoMode == STEREO_RIGHT)) { + canvas3d.setProjectionMatrix(canvas3d.ctx, + cvCache.getRightProjection()); + canvas3d.setModelViewMatrix(canvas3d.ctx, + cvCache.getRightVpcToEc().mat, + rb.vworldToVpc); + } else { + canvas3d.setProjectionMatrix(canvas3d.ctx, + cvCache.getLeftProjection()); + canvas3d.setModelViewMatrix(canvas3d.ctx, + cvCache.getLeftVpcToEc().mat, + rb.vworldToVpc); + } + } + + canvas3d.drawingSurfaceObject.unLock(); + } + } catch (NullPointerException ne) { + canvas3d.drawingSurfaceObject.unLock(); + throw ne; + } } - + // Method to update compTransform. private void computeCompositeTransform() { - ViewPlatform vp; - - if ((canvas3d == null) || - (canvas3d.view == null) || - (((vp = canvas3d.view.getViewPlatform()) == null)) || - (((ViewPlatformRetained)(vp.retained)) == null)) { - compTransform.set(modelTransform); - return; - } - + ViewPlatform vp; + + if ((canvas3d == null) || + (canvas3d.view == null) || + (((vp = canvas3d.view.getViewPlatform()) == null)) || + (((ViewPlatformRetained)(vp.retained)) == null)) { + compTransform.set(modelTransform); + return; + } + ViewPlatformRetained vpR = (ViewPlatformRetained)vp.retained; - if ((vpR == null) || (vpR.locale == null)) { - compTransform.set(modelTransform); - return; - } - - HiResCoord localeHiRes = vpR.locale.hiRes; - - if (localeHiRes.equals(hiRes)) { - compTransform.set(modelTransform); - } else { - Transform3D trans = new Transform3D(); - Vector3d localeTrans = new Vector3d(); - localeHiRes.difference( hiRes, localeTrans ); - trans.setTranslation( localeTrans ); - compTransform.mul(trans, modelTransform); - } + if ((vpR == null) || (vpR.locale == null)) { + compTransform.set(modelTransform); + return; + } + + HiResCoord localeHiRes = vpR.locale.hiRes; + + if (localeHiRes.equals(hiRes)) { + compTransform.set(modelTransform); + } else { + Transform3D trans = new Transform3D(); + Vector3d localeTrans = new Vector3d(); + localeHiRes.difference( hiRes, localeTrans ); + trans.setTranslation( localeTrans ); + compTransform.mul(trans, modelTransform); + } } // Method to update the view cache in pure immediate mode @@ -1892,14 +1906,14 @@ public class GraphicsContext3D extends Object { LightRetained light; boolean lightingOn = true; - if (canvas3d.ctx == 0) { + if (canvas3d.ctx == null) { // Force an initial clear if one has not yet been done doClear(); } if (J3dDebug.devPhase && J3dDebug.debug) { - J3dDebug.doAssert(canvas3d.ctx != 0, "canvas3d.ctx != 0"); + J3dDebug.doAssert(canvas3d.ctx != null, "canvas3d.ctx != null"); } // We need to catch NullPointerException when the dsi @@ -1933,8 +1947,7 @@ public class GraphicsContext3D extends Object { // (dirtyMask & BUFFER_MODE) above after testing // PureImmediate mode canvas3d.setProjectionMatrix(canvas3d.ctx, - cvCache.getRightProjection(). - mat); + cvCache.getRightProjection()); break; case STEREO_LEFT: case STEREO_BOTH: @@ -1944,8 +1957,7 @@ public class GraphicsContext3D extends Object { // (dirtyMask & BUFFER_MODE) above after testing // PureImmediate mode canvas3d.setProjectionMatrix(canvas3d.ctx, - cvCache.getLeftProjection(). - mat); + cvCache.getLeftProjection()); } } else if (!canvas3d.isRunning || @@ -2057,84 +2069,38 @@ public class GraphicsContext3D extends Object { ((Text3DRetained)geometry.retained).setModelViewMatrix( vpcToEc, this.drawTransform); drawGeo = (GeometryRetained)geometry.retained; - } else if (geometry.retained instanceof RasterRetained) { - ImageComponent2DRetained img = ((RasterRetained)geometry.retained).image; - if (img != null && img.isByReference()) { - img.geomLock.getLock(); - img.evaluateExtensions(canvas3d.extensionsSupported); - img.geomLock.unLock(); - } - drawGeo = (GeometryRetained)geometry.retained; - } else { + } else if (geometry.retained instanceof RasterRetained) { + ImageComponent2DRetained img = ((RasterRetained)geometry.retained).image; + if (img != null) { + if(img.isByReference()) { + img.geomLock.getLock(); + img.evaluateExtensions(canvas3d); + img.geomLock.unLock(); + } else { + img.evaluateExtensions(canvas3d); + } + } + drawGeo = (GeometryRetained)geometry.retained; + } else { drawGeo = (GeometryRetained)geometry.retained; } - if (!toSimulateMultiTex) { drawGeo.execute(canvas3d, null, isNonUniformScale, false, alpha, - ((canvas3d.view.getScreens()).length > 1), canvas3d.screen.screen, - ignoreVertexColors, - -1); - } else { - // NOTE: we really should leverage the code in textureBin - boolean startToSimulate = false; - - // simulate multiple texture units - AppearanceRetained app = - (AppearanceRetained)appearance.retained; - - assert VirtualUniverse.mc.allowSimulatedMultiTexture; - assert numActiveTexUnit > 1; - assert app.texUnitState != null; - assert app.texUnitState.length > 1; - - // first turn off fog - if (fog != null) - canvas3d.setFogEnableFlag(canvas3d.ctx, false); - - for (i = 0; i < app.texUnitState.length; i++) { - if (app.texUnitState[i] != null && - app.texUnitState[i].isTextureEnabled()) { - - // turn on fog for the last pass - if (i == lastActiveTexUnitIndex) - canvas3d.setFogEnableFlag(canvas3d.ctx, true); - - app.texUnitState[i].updateNative(-1, canvas3d, - false, startToSimulate); - - startToSimulate = true; - drawGeo.execute(canvas3d, null, - isNonUniformScale, false, alpha, - ((canvas3d.view.getScreens()).length > 1), - canvas3d.screen.screen, - ignoreVertexColors, - i); - } - } + ignoreVertexColors); - // adjust the depth test back to what it was - // and adjust the blend func to what it it was - if (startToSimulate) { - if (app.transparencyAttributes != null) { - app.transparencyAttributes.updateNative( - canvas3d.ctx, alpha, geometryType, - polygonMode, lineAA, pointAA); - } else { - canvas3d.resetTransparency(canvas3d.ctx, geometryType, - polygonMode, lineAA, pointAA); - } + if (geoRetained != null) { + if (geoRetained.pVertexBuffers != 0) { + // Issue 121: always free D3D vertex buffer memory + // after immediate mode rendering + geoRetained.freeD3DArray(true); } - if (fog != null) { - canvas3d.setFogEnableFlag(canvas3d.ctx, true); - } - } - if (geoRetained != null) - geoRetained.geomLock.unLock(); + geoRetained.geomLock.unLock(); + } - canvas3d.drawingSurfaceObject.unLock(); + canvas3d.drawingSurfaceObject.unLock(); } } catch (NullPointerException ne) { canvas3d.drawingSurfaceObject.unLock(); @@ -2145,8 +2111,25 @@ public class GraphicsContext3D extends Object { /** * Draw the specified Geometry component object. * @param geometry the Geometry object to draw. + * + * @exception IllegalSharingException if the specified geometry is a + * Raster that refers to an ImageComponent2D that is being used by a + * Canvas3D as an off-screen buffer. */ public void draw(Geometry geometry) { + // do illegalSharing check + if((geometry != null) && (geometry instanceof Raster)) { + RasterRetained rasRetained = (RasterRetained) geometry.retained; + ImageComponent2D image = rasRetained.getImage(); + if(image != null) { + ImageComponentRetained imageRetained = (ImageComponentRetained) image.retained; + // Do illegal sharing check + if(imageRetained.getUsedByOffScreen()) { + throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D32")); + } + } + } + if ((canvas3d.view == null) || (canvas3d.view.universe == null) || (!canvas3d.view.active)) { return; @@ -2170,10 +2153,16 @@ public class GraphicsContext3D extends Object { * setAppearance(Appearance) and draw(Geometry) methods * passing the appearance and geometry component objects of * the specified shape node as arguments. + * * @param shape the Shape3D node containing the Appearance component * object to set and Geometry component object to draw + * * @exception IllegalSharingException if the Shape3D node * is part of or is subsequently made part of a live scene graph. + * + * @exception IllegalSharingException if the Shape3D node's Appearance + * refers to an ImageComponent2D that is being used by a + * Canvas3D as an off-screen buffer. */ public void draw(Shape3D shape) { if (shape.isLive()) { @@ -2185,16 +2174,6 @@ public class GraphicsContext3D extends Object { } /** - * Native method for readRaster - */ - native void readRasterNative(long d3dctx, - int type, int xSrcOffset, int ySrcOffset, - int width, int height, int hCanvas, int format, - ImageComponentRetained image, - DepthComponentRetained depth, - GraphicsContext3D ctx); - - /** * Read an image from the frame buffer and copy it into the * ImageComponent and/or DepthComponent * objects referenced by the specified Raster object. @@ -2208,18 +2187,52 @@ public class GraphicsContext3D extends Object { * @param raster the Raster object used to read the * contents of the frame buffer * - * @exception IllegalArgumentException if the Raster's - * ImageComponent2D is in by-reference mode and its RenderedImage - * is not an instance of a BufferedImage. + * @exception IllegalArgumentException if the image class of the specified + * Raster's ImageComponent2D is <i>not</i> ImageClass.BUFFERED_IMAGE. * - * @exception IllegalSharingException if the Raster object - * is part of a live scene graph. + * @exception IllegalArgumentException if the specified Raster's + * ImageComponent2D is in by-reference mode and its + * RenderedImage is null. + * + * @exception IllegalArgumentException if the the Raster's + * ImageComponent2D format + * is <i>not</i> a 3-component format (e.g., FORMAT_RGB) + * or a 4-component format (e.g., FORMAT_RGBA). + * + * @exception IllegalSharingException if the Raster object is + * part of a live scene graph, or if the Raster's ImageComponent2D is + * part of a live scene graph. + * + * @exception IllegalSharingException if the Raster's ImageComponent2D is + * being used by an immediate mode context, or by a Canvas3D as + * an off-screen buffer. * * @see #flush * @see ImageComponent * @see DepthComponent */ public void readRaster(Raster raster) { + if ((raster != null) && raster.isLive()) { + ImageComponent2D image = raster.getImage(); + if (image != null){ + ImageComponent2DRetained imageRetained = (ImageComponent2DRetained)image.retained; + if (image.getImageClass() != ImageComponent.ImageClass.BUFFERED_IMAGE) { + throw new IllegalArgumentException(J3dI18N.getString("GraphicsContext3D33")); + } + if (image.isByReference() && (image.getImage() == null)) { + throw new IllegalArgumentException(J3dI18N.getString("GraphicsContext3D34")); + } + if (imageRetained.getNumberOfComponents() < 3) { + throw new IllegalArgumentException(J3dI18N.getString("GraphicsContext3D35")); + } + if (image.isLive()) { + throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D36")); + } + if (imageRetained.getInImmCtx() || imageRetained.getUsedByOffScreen()) { + throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D37")); + } + } + } if ((canvas3d.view == null) || (canvas3d.view.universe == null) || (!canvas3d.view.active)) { return; @@ -2242,122 +2255,119 @@ public class GraphicsContext3D extends Object { } } - - void doReadRaster(Raster raster) { - - - if (!canvas3d.firstPaintCalled) { - readRasterReady = true; - return; - } - - RasterRetained ras = (RasterRetained)raster.retained; - Dimension canvasSize = canvas3d.getSize(); - int format = 0; // Not use in case of DepthComponent read - - if (raster.isLive()) { - readRasterReady = true; - throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D21")); + if (!canvas3d.firstPaintCalled) { + readRasterReady = true; + return; } - // XXXX: implement illegal argument exception - /* - if (ras.image.byReference && - !(ras.image.imageReference instanceof BufferedImage)) { + RasterRetained ras = (RasterRetained)raster.retained; + Dimension canvasSize = canvas3d.getSize(); + Dimension rasterSize = new Dimension(); + ImageComponent2DRetained image = ras.image; - throw new IllegalArgumentException(...); - } - */ + int format = 0; // Not use in case of DepthComponent read - if (canvas3d.ctx == 0) { - // Force an initial clear if one has not yet been done - doClear(); - } + if (canvas3d.ctx == null) { + // Force an initial clear if one has not yet been done + doClear(); + } if (J3dDebug.devPhase && J3dDebug.debug) { - J3dDebug.doAssert(canvas3d.ctx != 0, "canvas3d.ctx != 0"); + J3dDebug.doAssert(canvas3d.ctx != null, "canvas3d.ctx != null"); } - - // allocate read buffer space + ras.getSize(rasterSize); + // allocate read buffer space if ( (ras.type & Raster.RASTER_COLOR) != 0) { - int bpp = ras.image.getEffectiveBytesPerPixel(); - int size = ras.image.height * ras.image.width - * bpp; - format = ras.image.getEffectiveFormat(); - if ((ras.width > ras.image.width) || - (ras.height > ras.image.height)) { - throw new RuntimeException(J3dI18N.getString("GraphicsContext3D27")); - } - if (byteBuffer.length < size) - byteBuffer = new byte[size]; + if ((rasterSize.width > ras.image.width) || + (rasterSize.height > ras.image.height)) { + throw new RuntimeException(J3dI18N.getString("GraphicsContext3D27")); + } } if ( (ras.type & Raster.RASTER_DEPTH) != 0) { int size = ras.depthComponent.height * ras.depthComponent.width; - if (ras.depthComponent.type - == DepthComponentRetained.DEPTH_COMPONENT_TYPE_FLOAT) { + if (ras.depthComponent.type + == DepthComponentRetained.DEPTH_COMPONENT_TYPE_FLOAT) { if (floatBuffer.length < size) floatBuffer = new float[size]; } else { // type INT or NATIVE if (intBuffer.length < size) intBuffer = new int[size]; } - if ((ras.width > ras.depthComponent.width) || - (ras.height > ras.depthComponent.height)) { - throw new RuntimeException(J3dI18N.getString("GraphicsContext3D28")); - } + if ((rasterSize.width > ras.depthComponent.width) || + (rasterSize.height > ras.depthComponent.height)) { + throw new RuntimeException(J3dI18N.getString("GraphicsContext3D28")); + } } - + if ( (ras.type & Raster.RASTER_COLOR) != 0) { - // If by reference, check if a copy needs to be made - // and also evaluate the storedFormat .. - if (ras.image.isByReference()) { - ras.image.geomLock.getLock(); - ras.image.evaluateExtensions(canvas3d.extensionsSupported); - ras.image.geomLock.unLock(); - } - } + + // If by reference, check if a copy needs to be made + // and also evaluate the storedFormat .. + if (image.isByReference()) { + image.geomLock.getLock(); + image.evaluateExtensions(canvas3d); + image.geomLock.unLock(); + } else { + // If image has a null buffer ( BufferedImage) + if (image.imageData == null) { + image.createBlankImageData(); + } + // Check for possible format conversion in imageData + else { + // Format convert imageData if format is unsupported. + image.evaluateExtensions(canvas3d); + } + } + } // We need to catch NullPointerException when the dsi // gets yanked from us during a remove. try { - if (canvas3d.drawingSurfaceObject.renderLock()) { - // Make the context current and read the raster information - canvas3d.makeCtxCurrent(); - canvas3d.syncRender(canvas3d.ctx, true); - readRasterNative(canvas3d.ctx, - ras.type, ras.xSrcOffset, ras.ySrcOffset, - ras.width, ras.height, canvasSize.height, format, - ras.image, ras.depthComponent, this); - canvas3d.drawingSurfaceObject.unLock(); - } - } catch (NullPointerException ne) { - canvas3d.drawingSurfaceObject.unLock(); - throw ne; - } - - // flip color image: yUp -> yDown and convert to BufferedImage - if ( (ras.type & Raster.RASTER_COLOR) != 0) { - ras.image.retrieveImage(byteBuffer, ras.width, ras.height); + if (canvas3d.drawingSurfaceObject.renderLock()) { + // Make the context current and read the raster information + canvas3d.makeCtxCurrent(); + canvas3d.syncRender(canvas3d.ctx, true); + Point rasterSrcOffset = new Point(); + ras.getDstOffset(rasterSrcOffset); + + DepthComponentRetained depthComp = ras.depthComponent; + int depthType = 0; + if(depthComp != null) { + depthType = depthComp.type; + } + Pipeline.getPipeline().readRaster(canvas3d.ctx, + ras.type, rasterSrcOffset.x, rasterSrcOffset.y, + rasterSize.width, rasterSize.height, canvasSize.height, + image.getImageDataTypeIntValue(), + image.getImageFormatTypeIntValue(false), + image.imageData.get(), + depthType, depthComp); + + canvas3d.drawingSurfaceObject.unLock(); + } + } catch (NullPointerException ne) { + canvas3d.drawingSurfaceObject.unLock(); + throw ne; } if ( (ras.type & Raster.RASTER_DEPTH) != 0) { - if (ras.depthComponent.type == - DepthComponentRetained.DEPTH_COMPONENT_TYPE_FLOAT) + if (ras.depthComponent.type == + DepthComponentRetained.DEPTH_COMPONENT_TYPE_FLOAT) ((DepthComponentFloatRetained)ras.depthComponent).retrieveDepth( - floatBuffer, ras.width, ras.height); - else if (ras.depthComponent.type == - DepthComponentRetained.DEPTH_COMPONENT_TYPE_INT) + floatBuffer, rasterSize.width, rasterSize.height); + else if (ras.depthComponent.type == + DepthComponentRetained.DEPTH_COMPONENT_TYPE_INT) ((DepthComponentIntRetained)ras.depthComponent).retrieveDepth( - intBuffer, ras.width, ras.height); - else if (ras.depthComponent.type == - DepthComponentRetained.DEPTH_COMPONENT_TYPE_NATIVE) - ((DepthComponentNativeRetained)ras.depthComponent).retrieveDepth( - intBuffer, ras.width, ras.height); + intBuffer, rasterSize.width, rasterSize.height); + else if (ras.depthComponent.type == + DepthComponentRetained.DEPTH_COMPONENT_TYPE_NATIVE) + ((DepthComponentNativeRetained)ras.depthComponent).retrieveDepth( + intBuffer, rasterSize.width, rasterSize.height); } - readRasterReady = true; + readRasterReady = true; } /** @@ -2386,8 +2396,9 @@ public class GraphicsContext3D extends Object { sendRenderMessage(true, GraphicsContext3D.FLUSH, waitArg, null); } + // Issue 131: AutomaticOffscreen canvases must be treated as onscreen ones. if (wait && canvas3d.active && canvas3d.isRunningStatus && - !canvas3d.offScreen) { + !canvas3d.manualRendering ) { // No need to wait if renderer thread is not schedule runMonitor(J3dThread.WAIT); } @@ -2514,7 +2525,6 @@ public class GraphicsContext3D extends Object { boolean updateState(RenderBin rb, int geometryType) { boolean useAlpha = false; - toSimulateMultiTex = false; numActiveTexUnit = 0; lastActiveTexUnitIndex = 0; @@ -2623,24 +2633,8 @@ public class GraphicsContext3D extends Object { // set the number active texture unit in Canvas3D canvas3d.setNumActiveTexUnit(numActiveTexUnit); - } else if (!useShaders && VirtualUniverse.mc.allowSimulatedMultiTexture) { - // Simulated (multi-pass) multi-texture rendering - - toSimulateMultiTex = true; - - // will fall back to the multi-pass case; - // reset all the texture units first - for (int i = 0; i < prevNumActiveTexUnit; i++) { - canvas3d.resetTexture(canvas3d.ctx, i); - } - - // set the number active texture unit in Canvas3D - canvas3d.setNumActiveTexUnit(1); - } - else { - // Exceeded limit, and not using simulated multi-texture - - // disable all the texture units + } else { + // Exceeded limit, disable all the texture units for (int i = 0; i < prevNumActiveTexUnit; i++) { canvas3d.resetTexture(canvas3d.ctx, i); } @@ -2674,15 +2668,6 @@ public class GraphicsContext3D extends Object { // If the image is by reference, check if the image // should be processed if (app.texture != null) { - for (int f = 0; f < app.texture.numFaces; f++) { - for (int k = 0; k < app.texture.maxLevels; k++) { - if (app.texture.images[f][k].isByReference()) { - app.texture.images[f][k].geomLock.getLock(); - app.texture.images[f][k].evaluateExtensions(canvas3d.extensionsSupported); - app.texture.images[f][k].geomLock.unLock(); - } - } - } app.texture.updateNative(canvas3d); canvas3d.canvasDirty |= Canvas3D.TEXTUREBIN_DIRTY|Canvas3D.TEXTUREATTRIBUTES_DIRTY; numActiveTexUnit = 1; @@ -3008,7 +2993,7 @@ public class GraphicsContext3D extends Object { // send a message to the request renderer - J3dMessage renderMessage = VirtualUniverse.mc.getMessage(); + J3dMessage renderMessage = new J3dMessage(); renderMessage.threads = J3dThread.RENDER_THREAD; renderMessage.type = J3dMessage.RENDER_IMMEDIATE; renderMessage.universe = null; @@ -3041,7 +3026,7 @@ public class GraphicsContext3D extends Object { return; } // send a message to the request sound scheduling - J3dMessage soundMessage = VirtualUniverse.mc.getMessage(); + J3dMessage soundMessage = new J3dMessage(); soundMessage.threads = J3dThread.SOUND_SCHEDULER; soundMessage.type = J3dMessage.RENDER_IMMEDIATE; soundMessage.universe = canvas3d.view.universe; diff --git a/src/classes/share/javax/media/j3d/GroupRetained.java b/src/classes/share/javax/media/j3d/GroupRetained.java index 3861c1c..e27ff91 100644 --- a/src/classes/share/javax/media/j3d/GroupRetained.java +++ b/src/classes/share/javax/media/j3d/GroupRetained.java @@ -155,7 +155,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } if (source.isLive()) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.COLLISION_BOUND_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY; @@ -231,14 +231,16 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { messages = new J3dMessage[numMessages]; for (int i = 0; i < numMessages; i++) { - messages[i] = VirtualUniverse.mc.getMessage(); + messages[i] = new J3dMessage(); } } if(oldchildr != null) { oldchildr.setParent(null); checkClearLive(oldchildr, messages, 0, index, null); - universe.notifyStructureChangeListeners(false, this.source, (BranchGroup)oldchildr.source); + if (this.source.isLive()) { + universe.notifyStructureChangeListeners(false, this.source, (BranchGroup)oldchildr.source); + } } removeChildrenData(index); @@ -250,7 +252,9 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { return; } - universe.notifyStructureChangeListeners(true, this.source, (BranchGroup)child); + if (this.source.isLive()) { + universe.notifyStructureChangeListeners(true, this.source, (BranchGroup)child); + } NodeRetained childr = (NodeRetained) child.retained; childr.setParent(this); children.set(index, childr); @@ -558,7 +562,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } messages = new J3dMessage[numMessages]; for (int i=0; i<numMessages; i++) { - messages[i] = VirtualUniverse.mc.getMessage(); + messages[i] = new J3dMessage(); messages[i].type = J3dMessage.INVALID_TYPE; } @@ -600,9 +604,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { for (int i=0; i < numMessages; i++) { if (messages[i].type != J3dMessage.INVALID_TYPE) { ms[k++] = messages[i]; - } else { - VirtualUniverse.mc.addMessageToFreelists(messages[i]); - } + } } if (ms != null) { VirtualUniverse.mc.processMessage(ms); @@ -1363,7 +1365,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { // Since we want to update collisionVwcBounds when // transform change in TransformStructure. TransformGroupRetained tg; - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.threads = J3dThread.UPDATE_GEOMETRY; message.universe = universe; // send message to GeometryStructure to add/remove this @@ -1567,7 +1569,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { messages = new J3dMessage[numMessages]; messageIndex = 0; for(int mIndex=0; mIndex < numMessages; mIndex++) { - messages[mIndex] = VirtualUniverse.mc.getMessage(); + messages[mIndex] = new J3dMessage(); } sendMessages = true; } @@ -1745,7 +1747,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { messages = new J3dMessage[numMessages]; messageIndex = 0; for(int mIndex=0; mIndex < numMessages; mIndex++) { - messages[mIndex] = VirtualUniverse.mc.getMessage(); + messages[mIndex] = new J3dMessage(); } sendMessages = true; } @@ -2962,7 +2964,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { if (source.isLive() && collisionBound == null && autoCompute && mirrorGroup != null) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.COLLISION_BOUND_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY; @@ -2978,7 +2980,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { if (source.isLive() && !boundsAutoCompute && collisionBound == null && mirrorGroup != null) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.COLLISION_BOUND_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY; diff --git a/src/classes/share/javax/media/j3d/IllegalRenderingStateException.java b/src/classes/share/javax/media/j3d/IllegalRenderingStateException.java index de93adc..903ec37 100644 --- a/src/classes/share/javax/media/j3d/IllegalRenderingStateException.java +++ b/src/classes/share/javax/media/j3d/IllegalRenderingStateException.java @@ -13,8 +13,8 @@ package javax.media.j3d; /** - * Indicates an illegal state for rendering. This exception is currently - * unused. + * Indicates an illegal state for rendering. This is typically some sort of + * resource or graphics device error encountered during rendering. */ public class IllegalRenderingStateException extends IllegalStateException { diff --git a/src/classes/share/javax/media/j3d/ImageComponent.java b/src/classes/share/javax/media/j3d/ImageComponent.java index d6ab908..deaccc1 100644 --- a/src/classes/share/javax/media/j3d/ImageComponent.java +++ b/src/classes/share/javax/media/j3d/ImageComponent.java @@ -161,10 +161,45 @@ public abstract class ImageComponent extends NodeComponent { */ public static final int FORMAT_CHANNEL8 = 10; - // Internal variable for checking validity of formats - // Change this if any more formats are added or removed + // Internal variable for checking validity of formats + // Change this if any more formats are added or removed static final int FORMAT_TOTAL = 10; + + /** + * Used to specify the class of the image being wrapped. + * + * @since Java 3D 1.5 + */ + public enum ImageClass { + /** + * Indicates that this ImageComponent object wraps a BufferedImage + * object. This is the default state. Note that the image class will + * be BUFFERED_IMAGE following a call to set(RenderedImage image) + * if we are in by-copy mode, or if the image is an instance of + * BufferedImage. + */ + BUFFERED_IMAGE, + + /** + * Indicates that this ImageComponent object wraps a RenderedImage + * object that is <i>not</i> a BufferedImage. Note that the image class + * of an ImageComponent following a call to set(RenderedImage image) + * will be RENDERED_IMAGE, if and only if the image is not an instance + * of BufferedImage and the ImageComponent is in by-reference mode. + */ + RENDERED_IMAGE, + + /** + * Indicates that this ImageComponent object wraps an NioImageBuffer + * object. Note that an ImageComponent in this state must not be used + * as the off-screen buffer of a Canvas3D nor as the target of a + * readRaster operation. + */ + NIO_IMAGE_BUFFER, + } + + /** * Specifies that this ImageComponent object allows reading its * size component information (width, height, and depth). @@ -335,10 +370,21 @@ public abstract class ImageComponent extends NodeComponent { * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * + * @exception IllegalStateException if the image class of this object + * is ImageClass.NIO_IMAGE_BUFFER. + * + * @deprecated as of Java 3D 1.5, the yUp flag should only be set at object + * construction time. + * * @since Java 3D 1.2 */ public void setYUp(boolean yUp) { checkForLiveOrCompiled(); + + // check for illegal image class + if (((ImageComponentRetained)this.retained).getImageClass() == ImageClass.NIO_IMAGE_BUFFER) { + throw new IllegalStateException("ImageComponent4"); + } ((ImageComponentRetained)this.retained).setYUp(yUp); } @@ -357,4 +403,18 @@ public abstract class ImageComponent extends NodeComponent { return ((ImageComponentRetained)this.retained).isYUp(); } + + /** + * Retrieves the image class of this ImageComponent object. + * + * @return the image class of this ImageComponent, + * one of: ImageClass.BUFFERED_IMAGE, + * ImageClass.RENDERED_IMAGE, or ImageClass.NIO_IMAGE_BUFFER. + * + * @since Java 3D 1.5 + */ + public ImageClass getImageClass() { + return ((ImageComponentRetained)this.retained).getImageClass(); + } + } diff --git a/src/classes/share/javax/media/j3d/ImageComponent2D.java b/src/classes/share/javax/media/j3d/ImageComponent2D.java index d46db4b..9bb31ef 100644 --- a/src/classes/share/javax/media/j3d/ImageComponent2D.java +++ b/src/classes/share/javax/media/j3d/ImageComponent2D.java @@ -42,6 +42,9 @@ import java.awt.image.RenderedImage; * </code> * </ul> * + * <p> + * As of Java 3D 1.5, an ImageComponent2D accepts an NioImageBuffer object + * as an alternative to a RenderedImage. */ public class ImageComponent2D extends ImageComponent { @@ -51,7 +54,12 @@ public class ImageComponent2D extends ImageComponent { /** * Constructs a 2D image component object using the specified - * format, width, and height, and a null image. + * format, width, and height. Default values are used for + * all other parameters. The default values are as follows: + * <ul> + * image : null<br> + * imageClass : ImageClass.BUFFERED_IMAGE<br> + * </ul> * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA, etc. @@ -72,6 +80,8 @@ public class ImageComponent2D extends ImageComponent { /** * Constructs a 2D image component object using the specified format * and BufferedImage. A copy of the BufferedImage is made. + * The image class is set to ImageClass.BUFFERED_IMAGE. + * Default values are used for all other parameters. * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA, etc. @@ -81,13 +91,15 @@ public class ImageComponent2D extends ImageComponent { */ public ImageComponent2D(int format, BufferedImage image) { - ((ImageComponent2DRetained)this.retained).processParams(format, image.getWidth(null), image.getHeight(null), 1); + ((ImageComponent2DRetained)this.retained).processParams(format, image.getWidth(), image.getHeight(), 1); ((ImageComponent2DRetained)this.retained).set(image); } /** * Constructs a 2D image component object using the specified format * and RenderedImage. A copy of the RenderedImage is made. + * The image class is set to ImageClass.BUFFERED_IMAGE. + * Default values are used for all other parameters. * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA, etc. @@ -106,8 +118,8 @@ public class ImageComponent2D extends ImageComponent { /** * Constructs a 2D image component object using the specified - * format, width, height, byReference flag, and yUp flag, and - * a null image. + * format, width, height, byReference flag, and yUp flag. + * Default values are used for all other parameters. * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA, etc. @@ -132,7 +144,6 @@ public class ImageComponent2D extends ImageComponent { boolean byReference, boolean yUp) { - ((ImageComponentRetained)this.retained).setByReference(byReference); ((ImageComponentRetained)this.retained).setYUp(yUp); ((ImageComponent2DRetained)this.retained).processParams(format, width, height, 1); @@ -141,6 +152,7 @@ public class ImageComponent2D extends ImageComponent { /** * Constructs a 2D image component object using the specified format, * BufferedImage, byReference flag, and yUp flag. + * The image class is set to ImageClass.BUFFERED_IMAGE. * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA, etc. @@ -161,16 +173,19 @@ public class ImageComponent2D extends ImageComponent { boolean byReference, boolean yUp) { - ((ImageComponentRetained)this.retained).setByReference(byReference); ((ImageComponentRetained)this.retained).setYUp(yUp); - ((ImageComponent2DRetained)this.retained).processParams(format, image.getWidth(null), image.getHeight(null), 1); + ((ImageComponent2DRetained)this.retained).processParams(format, image.getWidth(), image.getHeight(), 1); ((ImageComponent2DRetained)this.retained).set(image); } /** * Constructs a 2D image component object using the specified format, * RenderedImage, byReference flag, and yUp flag. + * The image class is set to ImageClass.RENDERED_IMAGE if the byReferece + * flag is true and the specified RenderedImage is <i>not</i> an instance + * of BufferedImage. In all other cases, the image class is set to + * ImageClass.BUFFERED_IMAGE. * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA, etc. @@ -187,32 +202,72 @@ public class ImageComponent2D extends ImageComponent { * @since Java 3D 1.2 */ public ImageComponent2D(int format, - RenderedImage image, - boolean byReference, - boolean yUp) { - + RenderedImage image, + boolean byReference, + boolean yUp) { + + ((ImageComponentRetained)this.retained).setByReference(byReference); + ((ImageComponentRetained)this.retained).setYUp(yUp); + ((ImageComponent2DRetained)this.retained).processParams(format, image.getWidth(), image.getHeight(), 1); + ((ImageComponent2DRetained)this.retained).set(image); + } - ((ImageComponentRetained)this.retained).setByReference(byReference); - ((ImageComponentRetained)this.retained).setYUp(yUp); - ((ImageComponent2DRetained)this.retained).processParams(format, image.getWidth(), image.getHeight(), 1); - ((ImageComponent2DRetained)this.retained).set(image); + /** + * Constructs a 2D image component object using the specified format, + * NioImageBuffer, byReference flag, and yUp flag. + * The image class is set to ImageClass.NIO_IMAGE_BUFFER. + * + * @param format the image component format, one of: FORMAT_RGB, + * FORMAT_RGBA, etc. + * @param image the NioImageBuffer used to create this 2D image component + * @param byReference a flag that indicates whether the data is copied + * into this image component object or is accessed by reference. + * @param yUp a flag that indicates the y-orientation of this image + * component. If yUp is set to true, the origin of the image is + * the lower left; otherwise, the origin of the image is the upper + * left. + * + * @exception IllegalArgumentException if format is invalid, or if + * the width or height of the image are not positive. + * + * @exception IllegalArgumentException if the byReference flag is false. + * + * @exception IllegalArgumentException if the yUp flag is false. + * + * @since Java 3D 1.5 + */ + public ImageComponent2D(int format, + NioImageBuffer image, + boolean byReference, + boolean yUp) { + + ((ImageComponentRetained)this.retained).setByReference(byReference); + ((ImageComponentRetained)this.retained).setYUp(yUp); + ((ImageComponent2DRetained)this.retained).processParams(format, image.getWidth(), image.getHeight(), 1); + ((ImageComponent2DRetained)this.retained).set(image); } /** * Sets this image component to the specified BufferedImage - * object. If the data access mode is not by-reference, then the + * object. + * If the data access mode is not by-reference, then the * BufferedImage data is copied into this object. If * the data access mode is by-reference, then a reference to the * BufferedImage is saved, but the data is not necessarily * copied. + * <p> + * The image class is set to ImageClass.BUFFERED_IMAGE. * * @param image BufferedImage object containing the image. - * The format and size must be the same as the current format in this + * Its size must be the same as the current size of this * ImageComponent2D object. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalArgumentException if the width and height of the + * specified image is not equal to the width and height of this + * ImageComponent object. */ public void set(BufferedImage image) { if (isLiveOrCompiled()) { @@ -231,14 +286,23 @@ public class ImageComponent2D extends ImageComponent { * the data access mode is by-reference, a reference to the * RenderedImage is saved, but the data is not necessarily * copied. + * <p> + * The image class is set to ImageClass.RENDERED_IMAGE if the the + * data access mode is by-reference and the specified + * RenderedImage is <i>not</i> an instance of BufferedImage. In all + * other cases, the image class is set to ImageClass.BUFFERED_IMAGE. * * @param image RenderedImage object containing the image. - * The format and size must be the same as the current format in this + * Its size must be the same as the current size of this * ImageComponent2D object. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalArgumentException if the width and height of the + * specified image is not equal to the width and height of this + * ImageComponent object. + * * @since Java 3D 1.2 */ public void set(RenderedImage image) { @@ -252,6 +316,43 @@ public class ImageComponent2D extends ImageComponent { } /** + * Sets this image component to the specified NioImageBuffer + * object. If the data access mode is not by-reference, the + * NioImageBuffer data is copied into this object. If + * the data access mode is by-reference, a reference to the + * NioImageBuffer is saved, but the data is not necessarily + * copied. + * <p> + * The image class is set to ImageClass.NIO_IMAGE_BUFFER. + * + * @param image NioImageBuffer object containing the image. + * Its size must be the same as the current size of this + * ImageComponent2D object. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalStateException if this ImageComponent object + * is <i>not</i> yUp. + * + * @exception IllegalArgumentException if the width and height of the + * specified image is not equal to the width and height of this + * ImageComponent object. + * + * @since Java 3D 1.5 + */ + public void set(NioImageBuffer image) { + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_IMAGE_WRITE)) { + throw new CapabilityNotSetException( + J3dI18N.getString("ImageComponent2D1")); + } + } + + ((ImageComponent2DRetained)this.retained).set(image); + } + + /** * Retrieves the image from this ImageComponent2D object. If the * data access mode is not by-reference, a copy of the image * is made. If the data access mode is by-reference, the @@ -264,9 +365,8 @@ public class ImageComponent2D extends ImageComponent { * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * - * @exception IllegalStateException if the data access mode is - * by-reference and the image referenced by this ImageComponent2D - * object is not an instance of BufferedImage. + * @exception IllegalStateException if the image class is not + * ImageClass.BUFFERED_IMAGE. */ public BufferedImage getImage() { if (isLiveOrCompiled()) { @@ -296,6 +396,9 @@ public class ImageComponent2D extends ImageComponent { * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalStateException if the image class is not one of: + * ImageClass.BUFFERED_IMAGE or ImageClass.RENDERED_IMAGE. + * * @since Java 3D 1.2 */ public RenderedImage getRenderedImage() { @@ -306,6 +409,35 @@ public class ImageComponent2D extends ImageComponent { return ((ImageComponent2DRetained)this.retained).getImage(); } + /** + * Retrieves the image from this ImageComponent2D object. If the + * data access mode is not by-reference, a copy of the image + * is made. If the data access mode is by-reference, the + * reference is returned. + * + * @return either a new NioImageBuffer object created from the data + * in this image component, or the NioImageBuffer object referenced + * by this image component. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalStateException if the image class is not + * ImageClass.NIO_IMAGE_BUFFER. + * + * @since Java 3D 1.5 + */ + public NioImageBuffer getNioImage() { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ImageComponent.ALLOW_IMAGE_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("ImageComponent2D0")); + } + } + return ((ImageComponent2DRetained)this.retained).getNioImage(); + + } + /** * Modifies a contiguous subregion of the image component. @@ -313,8 +445,8 @@ public class ImageComponent2D extends ImageComponent { * starting at the offset (srcX, srcY) of the specified * RenderedImage object will be copied into the image component * starting at the offset (dstX, dstY) of the ImageComponent2D object. - * The RenderedImage object must be of the same format as the current - * format of this object. + * The specified RenderedImage object must be of the same format as + * the current RenderedImage object in this image component. * This method can only be used if the data access mode is * by-copy. If it is by-reference, see updateData(). * @@ -332,15 +464,19 @@ public class ImageComponent2D extends ImageComponent { * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * * @exception IllegalStateException if the data access mode is * <code>BY_REFERENCE</code>. + * * @exception IllegalArgumentException if <code>width</code> or * <code>height</code> of * the subregion exceeds the dimension of the image of this object. + * * @exception IllegalArgumentException if <code>dstX</code> < 0, or * (<code>dstX</code> + <code>width</code>) > width of this object, or * <code>dstY</code> < 0, or * (<code>dstY</code> + <code>height</code>) > height of this object. + * * @exception IllegalArgumentException if <code>srcX</code> < 0, or * (<code>srcX</code> + <code>width</code>) > width of the RenderedImage * object containing the subimage, or @@ -348,6 +484,12 @@ public class ImageComponent2D extends ImageComponent { * (<code>srcY</code> + <code>height</code>) > height of the * RenderedImage object containing the subimage. * + * @exception IllegalArgumentException if the specified RenderedImage + * is not compatible with the existing RenderedImage. + * + * @exception IllegalStateException if the image class is not one of: + * ImageClass.BUFFERED_IMAGE or ImageClass.RENDERED_IMAGE. + * * @since Java 3D 1.3 */ public void setSubImage(RenderedImage image, int width, int height, @@ -457,7 +599,7 @@ public class ImageComponent2D extends ImageComponent { public NodeComponent cloneNodeComponent() { ImageComponent2DRetained rt = (ImageComponent2DRetained) retained; - ImageComponent2D img = new ImageComponent2D(rt.format, + ImageComponent2D img = new ImageComponent2D(rt.getFormat(), rt.width, rt.height, rt.byReference, @@ -485,15 +627,26 @@ public class ImageComponent2D extends ImageComponent { * @see NodeComponent#setDuplicateOnCloneTree */ void duplicateAttributes(NodeComponent originalNodeComponent, - boolean forceDuplicate) { - super.duplicateAttributes(originalNodeComponent, forceDuplicate); - - RenderedImage img = ((ImageComponent2DRetained) - originalNodeComponent.retained).getImage(); - - if (img != null) { - ((ImageComponent2DRetained) retained).set(img); - } + boolean forceDuplicate) { + super.duplicateAttributes(originalNodeComponent, forceDuplicate); + + ImageComponent.ImageClass imageClass = + ((ImageComponentRetained)originalNodeComponent.retained).getImageClass(); + if(imageClass == ImageComponent.ImageClass.NIO_IMAGE_BUFFER) { + NioImageBuffer nioImg = ((ImageComponent2DRetained) + originalNodeComponent.retained).getNioImage(); + + if(nioImg != null) { + ((ImageComponent2DRetained) retained).set(nioImg); + } + } else { + RenderedImage img = ((ImageComponent2DRetained) + originalNodeComponent.retained).getImage(); + + if (img != null) { + ((ImageComponent2DRetained) retained).set(img); + } + } } /** diff --git a/src/classes/share/javax/media/j3d/ImageComponent2DRetained.java b/src/classes/share/javax/media/j3d/ImageComponent2DRetained.java index 50680bf..b754b36 100644 --- a/src/classes/share/javax/media/j3d/ImageComponent2DRetained.java +++ b/src/classes/share/javax/media/j3d/ImageComponent2DRetained.java @@ -22,1238 +22,243 @@ import java.awt.color.ColorSpace; */ class ImageComponent2DRetained extends ImageComponentRetained { - private int rasterRefCnt = 0; // number of raster using this object - private int textureRefCnt = 0; // number of texture using this object - private DetailTextureImage detailTexture = null; // will reference a - // DetailTexture object if - // this image is being - // referenced as a detail image - - // use in D3D to map object to surface pointer - int hashId; - native void freeD3DSurface(int hashId); - - float[] lastAlpha = new float[1]; - - static final double EPSILON = 1.0e-6; - - // dirty mask to track if the image has been changed since the last - // alpha update. The nth bit in the mask represents the dirty bit - // of the image for screen nth. If nth bit is set, then the image - // needs to be updated with the current alpha values. - int imageChanged = 0; + // used in D3D to map object to surface pointer + int hashId; ImageComponent2DRetained() { hashId = hashCode(); } - + /** - * Copies the specified BufferedImage to this 2D image component object. - * @param image BufferedImage object containing the image. + * This method handles NioImageBuffer + * Refers or copies the specified NioImageBuffer to this 2D image component object. + * @param image NioImageBuffer object containing the image. * The format and size must be the same as the current format in this * ImageComponent2D object. */ - final void set(BufferedImage image) { - int width = image.getWidth(null); - int height = image.getHeight(null); + void set(NioImageBuffer image) { - if (width != this.width) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2DRetained0")); + int width = image.getWidth(); + int height = image.getHeight(); - if (height != this.height) + if (!byReference) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2D7")); + } + if (!yUp) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2D8")); + } + + if (width != this.width) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2DRetained0")); + } + if (height != this.height) { throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2DRetained1")); + } + + geomLock.getLock(); - int imageBytes; - // Note, currently only EXT_ABGR and EXT_BGR are not copied, if - // its going to be copied, do it at set time (at this time, the - // renderer is running in parallel), if we delay it until - // renderBin:updateObject time (when it calls evaluateExtension), - // we are stalling the renderer - geomLock.getLock(); - if (!byReference || (byReference && willBeCopied(image))) { - imageBytes = height * width * bytesPerPixelIfStored; - if (usedByTexture || ! usedByRaster) { - // ==> (usedByTexture) || (! usedByTexture && ! usedByRaster) - - if (imageYup == null || imageYup.length < imageBytes) { - imageYup = new byte[imageBytes]; - imageYupAllocated = true; - } - - // buffered image -> imageYup - storedYupFormat = internalFormat; - bytesPerYupPixelStored = getBytesStored(storedYupFormat); - copyImage(image, imageYup, true, 0, storedYupFormat, - bytesPerYupPixelStored); - imageYupClass = BUFFERED_IMAGE; - } - - if (usedByRaster) { - imageYdownClass = BUFFERED_IMAGE; - storedYdownFormat = internalFormat; - bytesPerYdownPixelStored = getBytesStored(storedYdownFormat); - - if (imageYdown[0] == null || imageYdown[0].length < imageBytes) { - imageYdown[0] = new byte[imageBytes]; - imageYdownAllocated = true; - } - - if (imageYup != null){ - //imageYup -> imageYdown - setImageYdown(imageYup, imageYdown[0]); - } else { - // buffered image -> imageYdown - copyImage(image, imageYdown[0], false, 0, - storedYdownFormat, bytesPerYdownPixelStored); - } - } - // If its byRef case, but we copied because we know that - // the underlying native API cannot support this case! - if (byReference) { - bImage[0] = image; - if (usedByTexture || !usedByRaster) - imageYupCacheDirty = false; - else - imageYupCacheDirty = true; - - if (usedByRaster) - imageYdownCacheDirty = false; - else - imageYdownCacheDirty = true; - - } - else { - imageDirty[0] = true; - } - - } - // If its by reference, then make a copy only if necessary - else { - imageYupCacheDirty = true; - imageYdownCacheDirty = true; - bImage[0] = image; - } - imageChanged = 0xffff; - lastAlpha[0] = 1.0f; - geomLock.unLock(); - - if (source.isLive()) { - freeSurface(); - - // send a IMAGE_CHANGED message in order to - // notify all the users of the change - sendMessage(IMAGE_CHANGED, null); - } - } - - - boolean willBeCopied(RenderedImage image) { - return shouldImageBeCopied(getImageType(image), - (Canvas3D.EXT_ABGR|Canvas3D.EXT_BGR), image); - } - - - - // NOTE, IMPORTANT: any additions to the biType tested , should be added to - // the willBeCopied() function - final boolean shouldImageBeCopied(int biType, int ext, RenderedImage ri) { - - if (!byReference) - return true; - - if ((((ext & Canvas3D.EXT_ABGR) != 0) && - ((biType == BufferedImage.TYPE_4BYTE_ABGR) && - (format == ImageComponent.FORMAT_RGBA8))) || - (((ext & Canvas3D.EXT_BGR) != 0) && - ((biType == BufferedImage.TYPE_3BYTE_BGR) && - (format == ImageComponent.FORMAT_RGB))) || - ((biType == BufferedImage.TYPE_BYTE_GRAY) && - (format == ImageComponent.FORMAT_CHANNEL8)) || - (is4ByteRGBAOr3ByteRGB(ri))) { - /* ||XXXX: Don't do short for now! - ((biType == BufferedImage.TYPE_USHORT_GRAY) && - (format == ImageComponent.FORMAT_CHANNEL8) - */ - - return false; - } - return true; - } - - final int getStoredFormat(int biType, RenderedImage ri) { - int f = 0; - switch(biType) { - case BufferedImage.TYPE_4BYTE_ABGR: - f= BYTE_ABGR; - break; - case BufferedImage.TYPE_BYTE_GRAY: - f= BYTE_GRAY; - break; - case BufferedImage.TYPE_USHORT_GRAY: - f = USHORT_GRAY; - break; - case BufferedImage.TYPE_3BYTE_BGR: - f = BYTE_BGR; - break; - case BufferedImage.TYPE_CUSTOM: - if (is4ByteRGBAOr3ByteRGB(ri)) { - SampleModel sm = ri.getSampleModel(); - if (sm.getNumBands() == 3) { - f = BYTE_RGB; - } - else { - f = BYTE_RGBA; - } - } - break; - default: - // Should never come here - } - return f; - } - - final void set(RenderedImage image) { + setImageClass(image); - if (image instanceof BufferedImage) { - set(((BufferedImage)image)); - } - else { - /* - // Create a buffered image from renderImage - ColorModel cm = image.getColorModel(); - WritableRaster wRaster = image.copyData(null); - BufferedImage bi = new BufferedImage(cm, - wRaster, - cm.isAlphaPremultiplied() - ,null); - set(bi); - } - */ - int width = image.getWidth(); - int height = image.getHeight(); + // This is a byRef image. + setRefImage(image,0); - if (width != this.width) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2DRetained0")); - - if (height != this.height) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2DRetained1")); - - int imageBytes; - // Note, currently only EXT_ABGR and EXT_BGR are not copied, if - // its going to be copied, do it at set time (at this time, the - // renderer is running in parallel), if we delay it until - // renderBin:updateObject time (when it calls evaluateExtension), - // we are stalling the renderer - geomLock.getLock(); - if (!byReference ||(byReference && willBeCopied(image))) { - imageBytes = height * width * bytesPerPixelIfStored; - if (usedByTexture || ! usedByRaster) { - if (imageYup == null || imageYup.length < imageBytes) { - imageYup = new byte[imageBytes]; - imageYupAllocated = true; - } - - // buffered image -> imageYup - storedYupFormat = internalFormat; - bytesPerYupPixelStored = getBytesStored(storedYupFormat); - copyImage(image, imageYup, true, 0, storedYupFormat, - bytesPerYupPixelStored); - imageYupClass = BUFFERED_IMAGE; - } - - if (usedByRaster) { + // Reset this flag to true, incase it was set to false due to + // the previous image type. + abgrSupported = true; - imageYdownClass = BUFFERED_IMAGE; - storedYdownFormat = internalFormat; - bytesPerYdownPixelStored = getBytesStored(storedYdownFormat); + imageTypeIsSupported = isImageTypeSupported(image); - if (imageYdown[0] == null || imageYdown[0].length < imageBytes) { - imageYdown[0] = new byte[imageBytes]; - imageYdownAllocated = true; - } - - if (imageYup != null) - //imageYup -> imageYdown - setImageYdown(imageYup, imageYdown[0]); - else - // buffered image -> imageYdown - copyImage(image, imageYdown[0], false, 0, - storedYdownFormat, bytesPerYdownPixelStored); - } - if (byReference) { - bImage[0] = image; - if (usedByTexture || !usedByRaster) - imageYupCacheDirty = false; - else - imageYupCacheDirty = true; - - if (usedByRaster) - imageYdownCacheDirty = false; - else - imageYdownCacheDirty = true; - } - else { - imageDirty[0] = true; - } - } - // If its by reference, then make a copy only if necessary - else { - imageYupCacheDirty = true; - imageYdownCacheDirty = true; - bImage[0] = image; - } + if (imageTypeIsSupported) { + + /* Use reference when ( format is OK, Yup is true, and byRef is true). */ + // Create image data object with the byRef image. */ + imageData = createNioImageBufferDataObject(image); + + } else { + // Handle abgrSupported is false case. + imageData = createNioImageBufferDataObject(null); + copyUnsupportedNioImageToImageData(image, 0, 0, 0, 0, width, height, imageData); - } - imageChanged = 0xffff; - lastAlpha[0] = 1.0f; - geomLock.unLock(); - if (source.isLive()) { - freeSurface(); + } + + geomLock.unLock(); + + if (source.isLive()) { + freeSurface(); + + // send a IMAGE_CHANGED message in order to + // notify all the users of the change sendMessage(IMAGE_CHANGED, null); - } + } } - - /** - * Retrieves a copy of the image in this ImageComponent2D object. - * @return a new BufferedImage object created from the image in this - * ImageComponent2D object + + /** + * This method handles both BufferedImage and RenderedImage + * Copies the specified RenderedImage to this 2D image component object. + * @param image RenderedImage object containing the image. + * The format and size must be the same as the current format in this + * ImageComponent2D object. */ - final RenderedImage getImage() { - if (!byReference && imageDirty[0]) { - imageDirty[0] = false; - retrieveBufferedImage(0); - } - return bImage[0]; - } - - // allocate storage for imageYdown - // set imageYdown and free imageYup if necessary - final void setRasterRef() { - // Ref case will be handled by evaluateExtension(); - if (usedByRaster) - return; - - usedByRaster = true; - - if (format == ImageComponent.FORMAT_CHANNEL8) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2DRetained2")); - - if (!byReference) { - if (imageYdown[0] == null && imageYup != null) { - imageYdown[0] = new byte[height * width * bytesPerYupPixelStored]; - imageYdownAllocated = true; - - // imageYup -> imageYdown - imageYdownClass = BUFFERED_IMAGE; - storedYdownFormat = storedYupFormat; - bytesPerYdownPixelStored = bytesPerYupPixelStored; - setImageYdown(imageYup, imageYdown[0]); - } - if (usedByTexture == false) { - imageYup = null; - imageYupAllocated = false; - } - - } - else { - if (willBeCopied(bImage[0])) { - geomLock.getLock(); - if (imageYdownCacheDirty) { - if (imageYdown[0] == null) { - - if (imageYup != null) { - storedYdownFormat = storedYupFormat; - bytesPerYdownPixelStored = bytesPerYupPixelStored; - imageYdown[0] =new byte[height*width *bytesPerYdownPixelStored]; - setImageYdown(imageYup, imageYdown[0]); - } - else { - imageYdown[0] = new byte[height * width * bytesPerPixelIfStored]; - bytesPerYdownPixelStored = bytesPerPixelIfStored; - storedYdownFormat = internalFormat; - - if (bImage[0] instanceof BufferedImage) { - copyImage(((BufferedImage)bImage[0]), - imageYdown[0], false, 0, - storedYdownFormat, - bytesPerYdownPixelStored); - } - else { - copyImage(bImage[0], imageYdown[0], false, 0, - storedYdownFormat, - bytesPerYdownPixelStored); - } - } - imageYdownClass = BUFFERED_IMAGE; - imageYdownAllocated = true; - } - imageYdownCacheDirty = false; - } - geomLock.unLock(); - } - else { - geomLock.getLock(); - imageYdownCacheDirty = true; - geomLock.unLock(); - } - /* - // Can't do this - since I don't know which extension - // will be supported, if Ydown is going away then - // this code will be useful - else if (yUp) { - geomLock.getLock(); - if (imageYdownCacheDirty) { - storeRasterImageWithFlip(bImage[0]); - imageYdownCacheDirty = false; - } - geomLock.unLock(); - } - */ - } - } - - // allocate storage for imageYup - // set imageYup and free imageYdown if necessary - final void setTextureRef() { - // Ref case will be handled by evaluateExtension(); - if (usedByTexture) - return; - - usedByTexture = true; - - if (!byReference) { - - if (imageYup == null && imageYdown[0] != null) { - storedYupFormat = storedYdownFormat; - bytesPerYupPixelStored = bytesPerYdownPixelStored; - imageYup = new byte[height * width * bytesPerYupPixelStored]; - // imageYdown -> imageYup - setImageYup(imageYdown[0], imageYup); - imageYupClass = BUFFERED_IMAGE; - imageYupAllocated = true; - } - if (usedByRaster == false) { - imageYdown[0] = null; - imageYdownAllocated = false; - } - - } - // If the image will not be stored by reference, because - // the format is not supported by the underlying API - else { - if (willBeCopied(bImage[0])) { - geomLock.getLock(); - if (imageYupCacheDirty) { - if (imageYup == null) { - if (imageYdown[0] != null) { - // imageYdown -> imageYup - storedYupFormat = storedYdownFormat; - bytesPerYupPixelStored = bytesPerYdownPixelStored; - imageYup = new byte[height * width * bytesPerYupPixelStored]; - setImageYup(imageYdown[0], imageYup); - } - else { - imageYup = new byte[height * width * bytesPerPixelIfStored]; - bytesPerYupPixelStored = bytesPerPixelIfStored; - storedYupFormat = internalFormat; - - if (bImage[0] instanceof BufferedImage) { - copyImage(((BufferedImage)bImage[0]), imageYup, - true, 0, storedYupFormat, - bytesPerYupPixelStored); - } - else { - copyImage(bImage[0], imageYup, true, 0, - storedYupFormat, - bytesPerYupPixelStored); - } - } - imageYupClass = BUFFERED_IMAGE; - imageYupAllocated = true; - } - imageYupCacheDirty = false; - } - geomLock.unLock(); - } - else { - geomLock.getLock(); - imageYupCacheDirty = true; - geomLock.unLock(); - } - /* - // Can't do this - since I don't know which extension - // will be supported, if Ydown is going away then - // this code will be useful - - // If Image will not be stored by reference because - // of wrong orienetation - else if (!yUp) { - geomLock.getLock(); - if (imageYupCacheDirty) { - storeTextureImageWithFlip(bImage[0]); - imageYupCacheDirty = false; - } - geomLock.unLock(); - } - */ - } - - } - - - // copy imageYup to imageYdown in reverse scanline order - final void setImageYdown(byte[] src, byte[] dst) { - int scanLineSize = width * bytesPerYdownPixelStored; - int srcOffset, dstOffset, i; - - for (srcOffset = (height - 1) * scanLineSize, dstOffset = 0, - i = 0; i < height; i++, - srcOffset -= scanLineSize, dstOffset += scanLineSize) { - - System.arraycopy(src, srcOffset, dst, dstOffset, - scanLineSize); + void set(RenderedImage image) { + + int width = image.getWidth(); + int height = image.getHeight(); + + if (width != this.width) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2DRetained0")); } - - } - - // Preserve the incoming format of thre renderImage, but maybe - // flip the image or make a plain copy - // Used only for raster - final void copyRImage(RenderedImage image, byte[] dst, boolean flip, - int bPerPixel) { - - int numX = image.getNumXTiles(); - int numY = image.getNumYTiles(); - int tilew = image.getTileWidth(); - int tileh = image.getTileHeight(); - int i, j, h; - java.awt.image.Raster ras; - int tileLineBytes = tilew * bPerPixel; - int x = image.getMinTileX(); - int y = image.getMinTileY(); - int srcOffset, dstOffset; - int dstLineBytes = 0; - int tileStart; - int tileBytes = tileh * tilew * numX * bPerPixel; - int dstStart; - int tmph, tmpw, curw, curh; - int rowOffset, colOffset; - int sign; - - if (flip) { - dstLineBytes =width * bPerPixel; - tileStart = (height - 1) * dstLineBytes; - dstLineBytes = -(dstLineBytes); - } - else { - tileStart = 0; - dstLineBytes = width * bPerPixel; - } - // convert from Ydown to Yup for texture - int minX = image.getMinX(); - int minY = image.getMinY(); - int xoff = image.getTileGridXOffset(); - int yoff = image.getTileGridYOffset(); - int endXTile = x * tilew + xoff+tilew; - int endYTile = y * tileh + yoff+tileh; - tmpw = width; - tmph = height; - // Check if the width is less than the tile itself .. - curw = (endXTile - minX); - curh = (endYTile - minY); - - if (tmpw < curw) { - curw = tmpw; - } - - if (tmph < curh) { - curh = tmph; - } - int startw = curw ; - - rowOffset = (tilew - curw) * bPerPixel; - colOffset = tilew * (tileh - curh) * bPerPixel; - int bytesCopied = 0; - srcOffset = rowOffset + colOffset; - - - for (i = y; i < y+numY; i++) { - dstStart = tileStart; - curw = startw; - tmpw = width; - for (j = x; j < x+numX; j++) { - ras = image.getTile(j,i); - byte[] src = ((DataBufferByte)ras.getDataBuffer()).getData(); - dstOffset = dstStart; - bytesCopied = curw * bPerPixel; - for (h = 0;h < curh; h++) { - System.arraycopy(src, srcOffset, dst, dstOffset, - bytesCopied); - srcOffset += tileLineBytes; - dstOffset += dstLineBytes; - } - srcOffset = colOffset; - dstStart += curw * bPerPixel; - tmpw -= curw; - if (tmpw < tilew) - curw = tmpw; - else - curw = tilew; - } - srcOffset = rowOffset; - colOffset = 0; - tileStart += curh * dstLineBytes; - tmph -= curh; - if (tmph < tileh) - curh = tmph; - else - curh = tileh; - } - } - - // copy imageYdown to imageYup in reverse scanline order - final void setImageYup(byte[] src, byte[] dst) { - int scanLineSize = width * bytesPerYupPixelStored; - int srcOffset, dstOffset, i; - - for (srcOffset = 0, dstOffset = (height - 1) * scanLineSize, - i = 0; i < height; i++, - srcOffset += scanLineSize, dstOffset -= scanLineSize) { - - System.arraycopy(src, srcOffset, dst, dstOffset, - scanLineSize); + if (height != this.height) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent2DRetained1")); + } + + setImageClass(image); + + geomLock.getLock(); + + if (byReference) { + setRefImage(image,0); + } + + // Reset this flag to true, incase it was set to false due to + // the previous image type. + abgrSupported = true; + + imageTypeIsSupported = isImageTypeSupported(image); + + if (imageTypeIsSupported) { + + if (byReference && yUp) { + /* Use reference when ( format is OK, Yup is true, and byRef is true). */ + // System.err.println("ImageComponent2DRetained.set() : (imageTypeSupported && byReference && yUp) --- (1)"); + if (image instanceof BufferedImage) { + // Create image data object with the byRef image. */ + imageData = createRenderedImageDataObject(image); + } + else { + // System.err.println("byRef and not BufferedImage !!!"); + imageData = null; + } + + } else { + // Either not byRef or not yUp or not both + // System.err.println("ImageComponent2DRetained.set() : (imageTypeSupported && ((!byReference && yUp) || (imageTypeSupported && !yUp)) --- (2)"); + + // Create image data object with buffer for image. */ + imageData = createRenderedImageDataObject(null); + copySupportedImageToImageData(image, 0, imageData); + } + + } else { + // image type is unsupported, need to create a supported local copy. + // TODO : borrow code from JAI to convert to right format. + // System.err.println("ImageComponent2DRetained.set() : (imageTypeSupported == false) --- (4)"); + /* Will use the code segment in copy() method */ + + // Create image data object with buffer for image. */ + imageData = createRenderedImageDataObject(null); + copyUnsupportedImageToImageData(image, 0, imageData); + + } + + geomLock.unLock(); + + if (source.isLive()) { + freeSurface(); + + // send a IMAGE_CHANGED message in order to + // notify all the users of the change + sendMessage(IMAGE_CHANGED, null); } } - // Lock out user thread from modifying usedByRaster and - // usedByTexture variables by using synchronized routines - final void evaluateExtensions(int ext) { - int i; - int imageBytes; - RenderedImage image = bImage[0]; - - // System.out.println("!!!!!!!!!!!!!imageYupCacheDirty = "+imageYupCacheDirty); - // System.out.println("!!!!!!!!!!!!!imageYdownCacheDirty = "+imageYdownCacheDirty); - // System.out.println("!!!!!!!!!!!!!usedByTexture = "+usedByTexture); - // System.out.println("!!!!!!!!!!!!!usedByRaster = "+usedByRaster); - - - if (!imageYupCacheDirty && !imageYdownCacheDirty) { - return; - } - - int riType = getImageType(image); - - // Thread.dumpStack(); - if (usedByTexture == true || ! usedByRaster) { - // If the image is already allocated, then return - // nothing to do! - // Since this is a new image, the app may have changed the image - // when it was not live, so re-compute, until the image is allocated - // for this pass! - // System.out.println("!!!!!!!!!!!!!imageYupCacheDirty = "+imageYupCacheDirty); - if (!imageYupCacheDirty) { - evaluateRaster(riType, ext); - return; - } - if (shouldImageBeCopied(riType, ext, image)) { - - imageBytes = height * width * bytesPerPixelIfStored; - if (imageYup == null || !imageYupAllocated) { - imageYup = new byte[imageBytes]; - imageYupAllocated = true; - } - // buffered image -> imageYup - bytesPerYupPixelStored = bytesPerPixelIfStored; - storedYupFormat = internalFormat; - copyImage(image, imageYup, true, 0, - storedYupFormat, bytesPerYupPixelStored); - imageYupClass = BUFFERED_IMAGE; - imageYupCacheDirty = false; - } - else { - // This image is already valid .. - if (!imageYupCacheDirty) { - evaluateRaster(riType, ext); - return; - } - storedYupFormat = getStoredFormat(riType, image); - bytesPerYupPixelStored = getBytesStored(storedYupFormat); - - // It does not have to be copied, but we - // have to copy because the incoming image is - // ydown - if (!yUp) { - storeTextureImageWithFlip(image); - } - else { - if (image instanceof BufferedImage) { - byte[] tmpImage = ((DataBufferByte)((BufferedImage)image).getRaster().getDataBuffer()).getData(); - imageYup = tmpImage; - imageYupAllocated = false; - imageYupClass = BUFFERED_IMAGE; - } - else { - numXTiles = image.getNumXTiles(); - numYTiles = image.getNumYTiles(); - tilew = image.getTileWidth(); - tileh = image.getTileHeight(); - minTileX = image.getMinTileX(); - minTileY = image.getMinTileY(); - minX = image.getMinX(); - minY = image.getMinY(); - tileGridXOffset =image.getTileGridXOffset(); - tileGridYOffset = image.getTileGridYOffset(); - imageYupAllocated = false; - imageYupClass = RENDERED_IMAGE; - imageYup = null; - } - } - - } - if (usedByRaster == false) { - imageYdown[0] = null; - imageYdownAllocated = false; - } - } - evaluateRaster(riType, ext); - } - - void evaluateRaster(int riType, int ext) { - int i; - int imageBytes; - RenderedImage image = bImage[0]; - - if (usedByRaster) { - // If the image is already allocated, then return - // nothing to do! - if (!imageYdownCacheDirty) { - return; - } - if (shouldImageBeCopied(riType, ext, image)) { - // System.out.println("Raster Image is copied"); - imageBytes = height * width * bytesPerPixelIfStored; - if (imageYdown[0] == null || !imageYdownAllocated || imageYdown[0].length < imageBytes){ - imageYdown[0] = new byte[imageBytes]; - imageYdownAllocated = true; - } - if (imageYup != null) { - storedYdownFormat = storedYupFormat; - bytesPerYdownPixelStored = bytesPerYupPixelStored; - setImageYdown(imageYup, imageYdown[0]); - } - else { - // buffered image -> imageYup - storedYdownFormat = internalFormat; - bytesPerYdownPixelStored = bytesPerPixelIfStored; - copyImage(image, imageYdown[0], false, 0, - storedYdownFormat, bytesPerYdownPixelStored); - } - imageYdownCacheDirty = false; - imageYdownClass = BUFFERED_IMAGE; - } - else { - // This image is already valid .. - if (!imageYdownCacheDirty) { - return; - } - storedYdownFormat = getStoredFormat(riType, image); - bytesPerYdownPixelStored = getBytesStored(storedYdownFormat); - if (yUp) { - storeRasterImageWithFlip(image); - } - else { - if (image instanceof BufferedImage) { - byte[] tmpImage = ((DataBufferByte)((BufferedImage)image).getRaster().getDataBuffer()).getData(); - imageYdown[0] = tmpImage; - imageYdownAllocated = false; - imageYdownClass = BUFFERED_IMAGE; - // System.out.println("Raster Image is stored by ref"); - } - else { - // Right now, always copy since opengl rasterpos is - // too restrictive - imageBytes = width*height*bytesPerYdownPixelStored; - if (imageYdown[0] == null || !imageYdownAllocated ||imageYdown[0].length < imageBytes){ - imageYdown[0] = new byte[imageBytes]; - imageYdownAllocated = true; - } - imageYdownClass = BUFFERED_IMAGE; - copyRImage(image,imageYdown[0], false, bytesPerYdownPixelStored); - // System.out.println("Copying by ref RImage"); - - /* - numXTiles = image.getNumXTiles(); - numYTiles = image.getNumYTiles(); - tilew = image.getTileWidth(); - tileh = image.getTileHeight(); - minTileX = image.getMinTileX(); - minTileY = image.getMinTileY(); - imageYdownAllocated = false; - imageYdownClass = RENDERED_IMAGE; - imageYdown = null; - */ - } - imageYdownCacheDirty = false; - } - - - } - if (usedByTexture == false) { - imageYup = null; - imageYupAllocated = false; - } - } - } - - void storeRasterImageWithFlip(RenderedImage image) { - int imageBytes; - - if (image instanceof BufferedImage) { - imageBytes = width*height*bytesPerYdownPixelStored; - if (imageYdown[0] == null || !imageYdownAllocated ||imageYdown[0].length < imageBytes){ - imageYdown[0] = new byte[imageBytes]; - imageYdownAllocated = true; - } - imageYdownClass = BUFFERED_IMAGE; - imageYdownCacheDirty = false; - byte[] tmpImage = ((DataBufferByte)((BufferedImage)image).getRaster().getDataBuffer()).getData(); - setImageYdown(tmpImage, imageYdown[0]); - } - else { - // Right now, always copy since opengl rasterpos is - // too restrictive - - imageBytes = width*height*bytesPerYdownPixelStored; - if (imageYdown[0] == null || !imageYdownAllocated ||imageYdown[0].length < imageBytes){ - imageYdown[0] = new byte[imageBytes]; - imageYdownAllocated = true; - } - imageYdownClass = BUFFERED_IMAGE; - imageYdownCacheDirty = false; - copyRImage(image, imageYdown[0], true, bytesPerYdownPixelStored); - } - } - - void storeTextureImageWithFlip(RenderedImage image) { - int imageBytes; - - if (image instanceof BufferedImage) { - byte[] tmpImage = ((DataBufferByte)((BufferedImage)image).getRaster().getDataBuffer()).getData(); - - if (imageYup == null || !imageYupAllocated) { - imageBytes = width*height*bytesPerYupPixelStored; - imageYup = new byte[imageBytes]; - imageYupAllocated = true; - } - imageYupClass = BUFFERED_IMAGE; - setImageYup(tmpImage, imageYup); - imageYupCacheDirty = false; - - } - else { - if (imageYup == null || !imageYupAllocated) { - imageBytes = width*height*bytesPerYupPixelStored; - imageYup = new byte[imageBytes]; - imageYupAllocated = true; - } - imageYupClass = BUFFERED_IMAGE; - copyRImage(image, imageYup, true, bytesPerYupPixelStored); - imageYupCacheDirty = false; - } - } - - void setLive(boolean inBackgroundGroup, int refCount) { - super.setLive(inBackgroundGroup, refCount); - } - - void clearLive(int refCount) { - super.clearLive(refCount); - if (this.refCount <= 0) { - freeSurface(); - } - } - - void freeSurface() { - if (VirtualUniverse.mc.isD3D()) { - freeD3DSurface(hashId); - } - } - - protected void finalize() { - // For Pure immediate mode, there is no clearLive so - // surface will free when JVM do GC - freeSurface(); - } - void updateAlpha(Canvas3D cv, int screen, float alpha) { - // if alpha is smaller than EPSILON, set it to EPSILON, so that - // even if alpha is equal to 0, we will not completely lose - int i, j; - byte byteAlpha; - float rndoff = 0.0f; - - // the original alpha value - if (alpha <= EPSILON) { - alpha = (float)EPSILON; - } - // System.out.println("========> updateAlpha, this = "+this); - // Lock out the other renderers .. - synchronized (this) { - // If by reference, the image has been copied, but aset has occured - // or if the format is not RGBA, then copy - // Thread.dumpStack(); - if (isByReference() && ((storedYdownFormat != internalFormat) || ((imageChanged & 1) != 0))) { - int imageBytes = height * width * bytesPerPixelIfStored; - if (imageYdown[0] == null || !imageYdownAllocated|| imageYdown[0].length < imageBytes) - imageYdown[0] = new byte[imageBytes]; - bytesPerYdownPixelStored = bytesPerPixelIfStored; - storedYdownFormat = internalFormat; - copyImage(bImage[0],imageYdown[0], false, 0, - storedYdownFormat, bytesPerYdownPixelStored); - imageYdownCacheDirty = false; - imageYdownClass = BUFFERED_IMAGE; - imageYdownAllocated = true; - imageChanged &= ~1; - freeSurface(); - } - - // allocate an entry for the last alpha of the screen if needed - if (lastAlpha == null) { - lastAlpha = new float[screen+1]; - lastAlpha[screen] = 1.0f; - } - else if (lastAlpha.length <= screen) { - float[] la = new float[screen+1]; - for (i = 0; i < lastAlpha.length; i++) { - la[i] = lastAlpha[i]; - } - lastAlpha = la; - lastAlpha[screen] = 1.0f; - } - // allocate a copy of the color data for the screen if needed. - // this piece of code is mainly for multi-screens case - if (imageYdown.length <= screen) { - byte[][] bdata = new byte[screen+1][]; - byte[] idata; - int refScreen = -1; - - int imageBytes = height * width * bytesPerYdownPixelStored; - idata = bdata[screen] = new byte[imageBytes]; - for (i = 0; i < imageYdown.length; i++) { - bdata[i] = imageYdown[i]; - if (Math.abs(lastAlpha[i] - alpha) < EPSILON) { - refScreen = i; - } - } - - if (noAlpha) { - byteAlpha = (byte) (alpha * 255.0f + 0.5); - for (j=3,i=0; i< width * height; i++,j+=4) { - idata[j] = byteAlpha; - } - } - else { - - // copy the data from a reference screen which has the closest - // alpha values - if (refScreen >= 0) { - System.arraycopy(imageYdown[refScreen], 0, idata, 0, imageBytes); - lastAlpha[screen] = lastAlpha[refScreen]; - } - else { - float m = alpha/lastAlpha[0]; - if (m < 1.0f) - rndoff = 0.5f; - else - rndoff = -0.5f; - - byte[] srcData = imageYdown[0]; - for (i = 0, j = 0; i < width * height; i++, j+= 4) { - System.arraycopy(srcData, j, idata, j, 3); - idata[j+3] =(byte)( ((int)srcData[j+3] & 0xff) * m + rndoff); - } - lastAlpha[screen] = alpha; - } - } - imageYdown = bdata; - - imageChanged &= ~(1 << screen); - freeSurface(); - return; - } + void setSubImage(RenderedImage image, int width, int height, + int srcX, int srcY, int dstX, int dstY) { - if ((imageChanged & (1<< screen)) == 0) { - // color data is not modified - // if alpha is different, update the alpha values - int val = -1; - if (Math.abs(lastAlpha[screen] - alpha) > EPSILON) { - byte[] idata = imageYdown[screen]; - if (noAlpha) { - byteAlpha = (byte) (alpha * 255.0f + 0.5); - for (j=3,i=0; i< width * height; i++,j+=4) { - idata[j] = byteAlpha; - } - } - else { - float m = alpha/lastAlpha[screen]; - if (m < 1.0f) - rndoff = 0.5f; - else - rndoff = -0.5f; - - for (i = 0, j = 3; i < width * height; i++, j+= 4) { - idata[j] =(byte)( ((int)idata[j] & 0xff) * m + rndoff); - } - } - freeSurface(); - } - } - else { - // color data is modified - if (screen == 0) { - // just update alpha values since screen 0 data is - // already updated in copyImage() - byte[] idata = imageYdown[0]; - if (noAlpha) { - byteAlpha = (byte) (alpha * 255.0f + 0.5); - for (j=3,i=0; i< width * height; i++,j+=4) { - idata[j] = byteAlpha; - } - } - else { - for (i = 0, j = 3; i < width * height; i++, j+= 4) { - idata[j] =(byte)( ((int)idata[j] & 0xff) * alpha + 0.5); - } - } - - } - else { - // update color values from screen 0 data - float m; - byte[] ddata = imageYdown[screen]; - if (noAlpha) { - byteAlpha = (byte) (alpha * 255.0f + 0.5); - for (j=3,i=0; i< width * height; i++,j+=4) { - ddata[j] = byteAlpha; - } - } - else { - if ((imageChanged & 1) == 0) { - // alpha is up to date in screen 0 - m = alpha / lastAlpha[0]; - } - else { - m = alpha; - } + if (!isSubImageTypeEqual(image)) { + throw new IllegalStateException( + J3dI18N.getString("ImageComponent2D6")); + } - if (m < 1.0f) - rndoff = 0.5f; - else - rndoff = -0.5f; + // Can't be byReference + assert (!byReference); + assert (imageData != null); + + geomLock.getLock(); + + if (imageTypeIsSupported) { + // Either not byRef or not yUp or not both + // System.err.println("ImageComponent2DRetained.setSubImage() : (imageTypeSupported ) --- (1)"); + if (image instanceof BufferedImage) { + copyImageLineByLine((BufferedImage)image, srcX, srcY, dstX, dstY, 0, width, height, imageData); + } + else { + copySupportedImageToImageData(image, srcX, srcY, dstX, dstY, 0, width, height, imageData); + } + } else { + // image type is unsupported, need to create a supported local copy. + // TODO : Should look into borrow code from JAI to convert to right format. + // System.err.println("ImageComponent2DRetained.setSubImage() : (imageTypeSupported == false) --- (2)"); + if (image instanceof BufferedImage) { + copyUnsupportedImageToImageData((BufferedImage)image, srcX, srcY, dstX, dstY, 0, width, height, imageData); + } + else { + copyUnsupportedImageToImageData(image, srcX, srcY, dstX, dstY, 0, width, height, imageData); + } + } + geomLock.unLock(); - byte[] sdata = imageYdown[0]; + if (source.isLive()) { - for (i = 0, j = 0; i < width * height; i++, j+= 4) { - System.arraycopy(sdata, j, ddata, j, 3); - ddata[j+3] =(byte)( ((int)sdata[j+3] & 0xff) * m + rndoff); - } - } - } - freeSurface(); - } - lastAlpha[screen] = alpha; - imageChanged &= ~(1 << screen); - } - } + // XXXX: check whether this is needed + freeSurface(); + // send a SUBIMAGE_CHANGED message in order to + // notify all the users of the change - int getEffectiveBytesPerPixel() { - if (byReference) { - if (usedByTexture || !usedByRaster) - return bytesPerYupPixelStored; - else - return bytesPerYdownPixelStored; - } - else { - return bytesPerPixelIfStored; - } - } + ImageComponentUpdateInfo info; + info = new ImageComponentUpdateInfo(); + info.x = dstX; + info.y = dstY; + info.z = 0; + info.width = width; + info.height = height; - int getEffectiveFormat() { - if (byReference) { - if (usedByTexture || !usedByRaster) - return storedYupFormat; - else - return storedYdownFormat; - } - else { - return internalFormat; - } - } + sendMessage(SUBIMAGE_CHANGED, info); + } + } /** - * retrieve image data from read buffer to ImageComponent's - * internal representation - */ - final void retrieveImage(byte[] buf, int wRead, int hRead) { - retrieveImage(buf, 0, 0, wRead, hRead); + * Retrieves a copy of the image in this ImageComponent2D object. + * @return a new RenderedImage object created from the image in this + * ImageComponent2D object + */ + RenderedImage getImage() { + + if (isByReference()) { + return (RenderedImage) getRefImage(0); + } + + if(imageData != null) { + return imageData.createBufferedImage(0); + } + + return null; } - /** - * retrieve a subimage data from read buffer to ImageComponent's - * internal representation - */ - final void retrieveImage(byte[] buf, int xRead, int yRead, int - wRead, int hRead) { - - int srcOffset, dstOffset, h,w,i,j; - int dstWidth; - - byte[] bdata; - - - // If byReference, then copy to the reference image immediately after - // readRaster or offscreenbuffer - - // In the by reference case, they should have set and image, before - // calling readRaster, so there should be a valid imageYup or imageYdown - // as used by texture or raster - - // Note the format of the glReadPixels is based on storedFormat - // so, we can do a direct copy - - int bpp = getEffectiveBytesPerPixel(); - int format = getEffectiveFormat(); - - if (!byReference) { - - dstWidth = width * bytesPerPixelIfStored; - if ((usedByTexture || !usedByRaster)&& (imageYup == null)) { - imageYup = new byte[height * dstWidth]; - bytesPerYupPixelStored = bytesPerPixelIfStored; - storedYupFormat = internalFormat; - imageYupAllocated = true; - } - if (usedByRaster && imageYdown[0] == null) { - imageYdown[0] = new byte[height * dstWidth]; - bytesPerYdownPixelStored = bytesPerPixelIfStored; - storedYdownFormat = internalFormat; - imageYdownAllocated = true; - } - } - - - int srcWidth = wRead * bpp; - int srcLineBytes = width * bpp; - - /* - System.out.println("bytesPerYdownPixelStored = "+bytesPerYdownPixelStored+" bpp = "+bpp); - System.out.println("storedYdownFormat = "+storedYdownFormat+" format = "+format); - System.out.println("bytesPerPixelIfStored = "+bytesPerPixelIfStored+" internalformat = "+internalFormat); - System.out.println("imageYup = "+imageYup+" imageYdown = "+imageYdown[0]); - System.out.println("===> usedByRaster = "+usedByRaster); - */ - - // array copy by scanline - - //position of a raster specifies the upper-left corner - // copy yUp -> yDown - imageDirty [0] = true; - - if (usedByRaster) { - dstWidth = width * bytesPerYdownPixelStored; - srcOffset = (yRead * srcLineBytes) + (xRead * bpp); - - dstOffset = ((height - yRead - 1)) * dstWidth + - (xRead * bytesPerYdownPixelStored); - // If by Reference and a copy has not been made ... - if (byReference && storedYdownFormat != internalFormat) { - bdata =((DataBufferByte) ((BufferedImage)bImage[0]).getRaster().getDataBuffer()).getData(); - imageDirty [0] = false; - } - else { - bdata = imageYdown[0]; - } - if (storedYdownFormat == format) { - for (h = 0; h < hRead; h++, - srcOffset += srcLineBytes, dstOffset -= dstWidth) { - System.arraycopy(buf, srcOffset, bdata, dstOffset, srcWidth); - } - } - else { // Would be one of the stored formats to RGBA - // Convert from one of the byRef formats to RGBA - switch(format) { - case BYTE_ABGR: - for (h = 0; h < hRead; h++, - srcOffset += srcLineBytes, dstOffset -= dstWidth) { - int offset = dstOffset; - for (w = 0; w < srcWidth; w +=bpp) { - bdata[offset++] = buf[srcOffset+w+3]; - bdata[offset++] = buf[srcOffset+w+2]; - bdata[offset++] = buf[srcOffset+w+1]; - bdata[offset++] = buf[srcOffset+w]; - - } - } - break; - case BYTE_BGR: - - for (h = 0; h < hRead; h++, - srcOffset += srcLineBytes, dstOffset -= dstWidth) { - int offset = dstOffset; - for (w = 0; w < srcWidth; w +=bpp) { - bdata[offset++] = buf[srcOffset+w+2]; - bdata[offset++] = buf[srcOffset+w+1]; - bdata[offset++] = buf[srcOffset+w]; - bdata[offset++] = (byte)0xff; - - } - } - break; - - } - } - } - - if (usedByTexture || !usedByRaster) { - imageYupCacheDirty = true; - dstWidth = width * bytesPerYupPixelStored; - srcOffset = (yRead * srcLineBytes) + (xRead * bpp); + * Retrieves the reference of the nio image in this ImageComponent2D object. + */ + NioImageBuffer getNioImage() { - // If by Reference and a copy has not been made ... - if (byReference && storedYupFormat != internalFormat) { - bdata =((DataBufferByte) ((BufferedImage)bImage[0]).getRaster().getDataBuffer()).getData(); - imageDirty [0] = false; - } - else { - bdata = imageYup; - } - // If used by texture, then storedYupFormat is always equal to format - if (storedYupFormat == format) { - for (dstOffset = srcOffset, - h = 0; h < hRead; h++, - srcOffset += srcLineBytes, dstOffset += dstWidth) { - System.arraycopy(buf, srcOffset, bdata, dstOffset, srcWidth); - } - } - } - // If its by reference and a copy has been made, make the user's copy - // up-to-date - - if (byReference && imageDirty[0]) { - imageDirty [0] = false; - if (usedByTexture || !usedByRaster) { - copyBufferedImageWithFormatConversion(true, 0); - } - else { - copyBufferedImageWithFormatConversion(false, 0); - } - } - imageChanged = 0xffff; - lastAlpha[0] = 1.0f; + if (getImageClass() != ImageComponent.ImageClass.NIO_IMAGE_BUFFER) { + throw new IllegalStateException(J3dI18N.getString("ImageComponent2D9")); + } + + assert (byReference == true); + + return (NioImageBuffer) getRefImage(0); } /** @@ -1265,29 +270,41 @@ class ImageComponent2DRetained extends ImageComponentRetained { int x, int y, int width, int height) { geomLock.getLock(); - // call the user supplied updateData method to update the data updater.updateData((ImageComponent2D)source, x, y, width, height); - // update the internal copy of the image data if a copy has been - // made - if (imageYupAllocated) { - copyImage(bImage[0], (x + bImage[0].getMinX()), - (y + bImage[0].getMinY()), imageYup, x, y, - true, 0, width, height, storedYupFormat, - bytesPerYupPixelStored); - } - - - if (imageYdownAllocated) { - copyImage(bImage[0], (x + bImage[0].getMinX()), - (y + bImage[0].getMinY()), imageYdown[0], x, y, - false, 0, width, height, storedYdownFormat, - bytesPerYdownPixelStored); - } - - imageDirty[0] = true; - + Object refImage = getRefImage(0); + assert (refImage != null); + assert (imageData != null); + + // Check is data copied internally. + if(!imageData.isDataByRef()) { + // update the internal copy of the image data if a copy has been + // made + if (imageTypeIsSupported) { + assert !(refImage instanceof NioImageBuffer); + + if (refImage instanceof BufferedImage) { + copyImageLineByLine((BufferedImage)refImage, x, y, x, y, 0, width, height, imageData); + } else { + RenderedImage ri = (RenderedImage)refImage; + copySupportedImageToImageData(ri, (x + ri.getMinX()), (y + ri.getMinY()), x, y, 0, width, height, imageData); + } + } else { + // image type is unsupported, need to create a supported local copy. + // TODO : Should look into borrow code from JAI to convert to right format. + if (refImage instanceof BufferedImage) { + copyUnsupportedImageToImageData((BufferedImage)refImage, x, y, x, y, 0, width, height, imageData); + } else if (refImage instanceof RenderedImage) { + RenderedImage ri = (RenderedImage)refImage; + copyUnsupportedImageToImageData(ri, (x + ri.getMinX()), (y + ri.getMinY()), x, y, 0, width, height, imageData); + } else if (refImage instanceof NioImageBuffer) { + copyUnsupportedNioImageToImageData((NioImageBuffer)refImage, x, y, x, y, width, height, imageData); + } else { + assert false; + } + } + } geomLock.unLock(); @@ -1301,7 +318,7 @@ class ImageComponent2DRetained extends ImageComponentRetained { ImageComponentUpdateInfo info; - info = VirtualUniverse.mc.getFreeImageUpdateInfo(); + info = new ImageComponentUpdateInfo(); info.x = x; info.y = y; info.z = 0; @@ -1311,74 +328,58 @@ class ImageComponent2DRetained extends ImageComponentRetained { sendMessage(SUBIMAGE_CHANGED, info); } } + + ImageComponentRetained createNextLevelMipMapImage() { + + int xScale, yScale, newWidth, newHeight; + + if (width > 1) { + newWidth = width >> 1; + xScale = 2; + } else { + newWidth = 1; + xScale = 1; + } + if (height > 1) { + newHeight = height >> 1; + yScale = 2; + } else { + newHeight = 1; + yScale = 1; + } + + ImageComponent2DRetained newImage = new ImageComponent2DRetained(); + newImage.processParams(getFormat(), newWidth, newHeight, 1); + newImage.setImageFormatType(getImageFormatType()); + newImage.setUnitsPerPixel(getUnitsPerPixel()); + newImage.imageData = newImage.createRenderedImageDataObject(null); + + newImage.scaleImage(xScale, yScale, 0, this); + + return newImage; + } - void setSubImage(RenderedImage image, int width, int height, - int srcX, int srcY, int dstX, int dstY) { - - geomLock.getLock(); - - if (imageYupAllocated) { - copyImage(image, srcX, srcY, imageYup, dstX, dstY, - true, 0, width, height, storedYupFormat, - bytesPerYupPixelStored); - } - - if (imageYdownAllocated) { - copyImage(image, srcX, srcY, imageYdown[0], - dstX, dstY, false, 0, width, height, - storedYdownFormat, bytesPerYdownPixelStored); + void clearLive(int refCount) { + super.clearLive(refCount); + if (this.refCount <= 0) { + freeSurface(); } - - imageDirty[0] = true; - - geomLock.unLock(); - - - if (source.isLive()) { - - // XXXX: check whether this is needed - freeSurface(); - - // send a SUBIMAGE_CHANGED message in order to - // notify all the users of the change - - ImageComponentUpdateInfo info; - - info = VirtualUniverse.mc.getFreeImageUpdateInfo(); - info.x = dstX; - info.y = dstY; - info.z = 0; - info.width = width; - info.height = height; - - sendMessage(SUBIMAGE_CHANGED, info); - } } - synchronized void updateMirrorObject(int component, Object value) { - - super.updateMirrorObject(component, value); - - if (detailTexture != null) { - if (((component & IMAGE_CHANGED) != 0) || - ((component & SUBIMAGE_CHANGED) != 0)) { - - // notify detailTexture of image change - - detailTexture.notifyImageComponentImageChanged(this, value); - } + void freeSurface() { + if (VirtualUniverse.mc.isD3D()) { + Pipeline.getPipeline().freeD3DSurface(this, hashId); } } + // TODO KCR ISSUE 121 : REPLACE THIS WITH A WEAK REFERENCE OR OTHER SCHEME + // Issue 121 : Stop using finalize() to clean up state + // Use similar approach as in handling ogl Texture resource cleanup. +// protected void finalize() { +// System.err.println("finalize: " + this); +//// // For Pure immediate mode, there is no clearLive so +//// // surface will free when JVM do GC +//// freeSurface(); +// } - synchronized void setDetailTexture(DetailTextureImage tex) { - detailTexture = tex; - } - - synchronized DetailTextureImage getDetailTexture() { - if (detailTexture == null) { - detailTexture = new DetailTextureImage(this); - } - return detailTexture; - } } diff --git a/src/classes/share/javax/media/j3d/ImageComponent3D.java b/src/classes/share/javax/media/j3d/ImageComponent3D.java index 9127277..6c0238c 100644 --- a/src/classes/share/javax/media/j3d/ImageComponent3D.java +++ b/src/classes/share/javax/media/j3d/ImageComponent3D.java @@ -41,6 +41,7 @@ import java.awt.image.RenderedImage; * ic.set(0, ri);<br> * </code> * </ul> + * */ public class ImageComponent3D extends ImageComponent { @@ -53,6 +54,7 @@ public class ImageComponent3D extends ImageComponent { * all other parameters. The default values are as follows: * <ul> * array of images : null<br> + * imageClass : ImageClass.BUFFERED_IMAGE<br> * </ul> * * @param format the image component format, one of: FORMAT_RGB, @@ -71,25 +73,26 @@ public class ImageComponent3D extends ImageComponent { int depth) { ((ImageComponent3DRetained)this.retained).processParams(format, width, height, depth); - ((ImageComponent3DRetained)this.retained).setDepth(depth); } /** * Constructs a 3D image component object using the specified format, * and the BufferedImage array. + * The image class is set to ImageClass.BUFFERED_IMAGE. * Default values are used for all other parameters. + * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA etc. * @param images an array of BufferedImage objects. The * first image in the array determines the width and height of this * ImageComponent3D. + * * @exception IllegalArgumentException if format is invalid, or if * the width or height of the first image are not positive. */ public ImageComponent3D(int format, BufferedImage[] images) { ((ImageComponent3DRetained)this.retained).processParams(format, images[0].getWidth(null), images[0].getHeight(null), images.length); - ((ImageComponent3DRetained)this.retained).setDepth(images.length); for (int i=0; i<images.length; i++) { ((ImageComponent3DRetained)this.retained).set(i, images[i]); } @@ -98,12 +101,15 @@ public class ImageComponent3D extends ImageComponent { /** * Constructs a 3D image component object using the specified format, * and the RenderedImage array. + * The image class is set to ImageClass.BUFFERED_IMAGE. * Default values are used for all other parameters. + * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA etc. * @param images an array of RenderedImage objects. The * first image in the array determines the width and height of this * ImageComponent3D. + * * @exception IllegalArgumentException if format is invalid, or if * the width or height of the first image are not positive. * @@ -113,7 +119,6 @@ public class ImageComponent3D extends ImageComponent { ((ImageComponent3DRetained)this.retained).processParams(format, images[0].getWidth(), images[0].getHeight(), images.length); - ((ImageComponent3DRetained)this.retained).setDepth(images.length); for (int i=0; i<images.length; i++) { ((ImageComponent3DRetained)this.retained).set(i, images[i]); } @@ -153,13 +158,13 @@ public class ImageComponent3D extends ImageComponent { ((ImageComponentRetained)this.retained).setByReference(byReference); ((ImageComponentRetained)this.retained).setYUp(yUp); ((ImageComponent3DRetained)this.retained).processParams(format, width, height, depth); - ((ImageComponent3DRetained)this.retained).setDepth(depth); } /** * Constructs a 3D image component object using the specified format, * BufferedImage array, byReference flag, and yUp flag. - * Default values are used for all other parameters. + * The image class is set to ImageClass.BUFFERED_IMAGE. + * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA etc. * @param images an array of BufferedImage objects. The @@ -171,6 +176,7 @@ public class ImageComponent3D extends ImageComponent { * component. If yUp is set to true, the origin of the image is * the lower left; otherwise, the origin of the image is the upper * left. + * * @exception IllegalArgumentException if format is invalid, or if * the width or height of the first image are not positive. * @@ -184,8 +190,8 @@ public class ImageComponent3D extends ImageComponent { ((ImageComponentRetained)this.retained).setByReference(byReference); ((ImageComponentRetained)this.retained).setYUp(yUp); - ((ImageComponent3DRetained)this.retained).processParams(format, images[0].getWidth(null), images[0].getHeight(null), images.length); - ((ImageComponent3DRetained)this.retained).setDepth(images.length); + ((ImageComponent3DRetained)this.retained).processParams(format, + images[0].getWidth(null), images[0].getHeight(null), images.length); for (int i=0; i<images.length; i++) { ((ImageComponent3DRetained)this.retained).set(i, images[i]); } @@ -194,7 +200,11 @@ public class ImageComponent3D extends ImageComponent { /** * Constructs a 3D image component object using the specified format, * RenderedImage array, byReference flag, and yUp flag. - * Default values are used for all other parameters. + * The image class is set to ImageClass.RENDERED_IMAGE if the byReference + * flag is true and any of the specified RenderedImages is <i>not</i> an + * instance of BufferedImage. In all other cases, the image class is set to + * ImageClass.BUFFERED_IMAGE. + * * @param format the image component format, one of: FORMAT_RGB, * FORMAT_RGBA etc. * @param images an array of RenderedImage objects. The @@ -216,19 +226,67 @@ public class ImageComponent3D extends ImageComponent { boolean byReference, boolean yUp) { - ((ImageComponentRetained)this.retained).setByReference(byReference); ((ImageComponentRetained)this.retained).setYUp(yUp); - ((ImageComponent3DRetained)this.retained).processParams(format, images[0].getWidth(), images[0].getHeight(), images.length); - ((ImageComponent3DRetained)this.retained).setDepth(images.length); + ((ImageComponent3DRetained)this.retained).processParams(format, + images[0].getWidth(), images[0].getHeight(), images.length); + for (int i=0; i<images.length; i++) { + ((ImageComponent3DRetained)this.retained).set(i, images[i]); + } + } + + /** + * Constructs a 3D image component object using the specified format, + * NioImageBuffer array, byReference flag, and yUp flag. + * The image class is set to ImageClass.NIO_IMAGE_BUFFER. + * + * @param format the image component format, one of: FORMAT_RGB, + * FORMAT_RGBA etc. + * @param images an array of NioImageBuffer objects. The + * first image in the array determines the width and height of this + * ImageComponent3D. + * @param byReference a flag that indicates whether the data is copied + * into this image component object or is accessed by reference. + * @param yUp a flag that indicates the y-orientation of this image + * component. If yUp is set to true, the origin of the image is + * the lower left; otherwise, the origin of the image is the upper + * left. + * + * @exception IllegalArgumentException if format is invalid, or if + * the width or height of the first image are not positive. + * + * @exception IllegalArgumentException if the byReference flag is false. + * + * @exception IllegalArgumentException if the yUp flag is false. + * + * @exception UnsupportedOperationException this method is not supported + * for Java 3D 1.5. + * + * @since Java 3D 1.5 + */ + public ImageComponent3D(int format, + NioImageBuffer[] images, + boolean byReference, + boolean yUp) { + + + throw new UnsupportedOperationException(); + /* + ((ImageComponentRetained)this.retained).setByReference(byReference); + ((ImageComponentRetained)this.retained).setYUp(yUp); + ((ImageComponent3DRetained)this.retained).processParams(format, + images[0].getWidth(), images[0].getHeight(), images.length); for (int i=0; i<images.length; i++) { ((ImageComponent3DRetained)this.retained).set(i, images[i]); } + */ } /** * Retrieves the depth of this 3D image component object. - * @return the format of this 3D image component object + * + * @return the depth of this 3D image component object + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ @@ -247,14 +305,23 @@ public class ImageComponent3D extends ImageComponent { * then a shallow copy of the array of references to the * BufferedImage objects is made, but the BufferedImage * data is not necessarily copied. + * <p> + * The image class is set to ImageClass.BUFFERED_IMAGE. * * @param images array of BufferedImage objects containing the image. - * The format and size must be the same as the current format in the - * image component. + * The size (width and height) of each image must be the same as the + * size of the image component, and the length of the images array + * must equal the depth of the image component. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalArgumentException if the length of the images array is + * not equal to the depth of this ImageComponent object. + * + * @exception IllegalArgumentException if the width and height of each + * image in the images array is not equal to the width and height of this + * ImageComponent object. */ public void set(BufferedImage[] images) { checkForLiveOrCompiled(); @@ -275,14 +342,27 @@ public class ImageComponent3D extends ImageComponent { * then a shallow copy of the array of references to the * RenderedImage objects is made, but the RenderedImage * data is not necessarily copied. + * <p> + * The image class is set to ImageClass.RENDERED_IMAGE if the data access + * mode is by-reference and any of the specified RenderedImages + * is <i>not</i> an instance of BufferedImage. In all other cases, + * the image class is set to ImageClass.BUFFERED_IMAGE. * * @param images array of RenderedImage objects containing the image. - * The format and size must be the same as the current format in the - * image component. + * The size (width and height) of each image must be the same as the + * size of the image component, and the length of the images array + * must equal the depth of the image component. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalArgumentException if the length of the images array is + * not equal to the depth of this ImageComponent object. + * + * @exception IllegalArgumentException if the width and height of each + * image in the images array is not equal to the width and height of this + * ImageComponent object. + * * @since Java 3D 1.2 */ public void set(RenderedImage[] images) { @@ -298,6 +378,55 @@ public class ImageComponent3D extends ImageComponent { } /** + * Sets the array of images in this image component to the + * specified array of NioImageBuffer objects. If the data access + * mode is not by-reference, then the NioImageBuffer data is copied + * into this object. If the data access mode is by-reference, + * then a shallow copy of the array of references to the + * NioImageBuffer objects is made, but the NioImageBuffer + * data is not necessarily copied. + * <p> + * The image class is set to ImageClass.NIO_IMAGE_BUFFER. + * + * @param images array of NioImageBuffer objects containing the image. + * The size (width and height) of each image must be the same as the + * size of the image component, and the length of the images array + * must equal the depth of the image component. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalStateException if this ImageComponent object + * is <i>not</i> yUp. + * + * @exception IllegalArgumentException if the length of the images array is + * not equal to the depth of this ImageComponent object. + * + * @exception IllegalArgumentException if the width and height of each + * image in the images array is not equal to the width and height of this + * ImageComponent object. + * + * @exception UnsupportedOperationException this method is not supported + * for Java 3D 1.5. + * + * @since Java 3D 1.5 + */ + public void set(NioImageBuffer[] images) { + + throw new UnsupportedOperationException(); + /* + checkForLiveOrCompiled(); + int depth = ((ImageComponent3DRetained)this.retained).getDepth(); + + if (depth != images.length) + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent3D1")); + for (int i=0; i<depth; i++) { + ((ImageComponent3DRetained)this.retained).set(i, images[i]); + } + */ + } + + /** * Sets this image component at the specified index to the * specified BufferedImage object. If the data access mode is not * by-reference, then the BufferedImage data is copied into this @@ -305,15 +434,21 @@ public class ImageComponent3D extends ImageComponent { * reference to the BufferedImage is saved, but the data is not * necessarily copied. * - * @param index the image index + * @param index the image index. + * The index must be less than the depth of this ImageComponent3D object. + * * @param image BufferedImage object containing the image. - * The format and size must be the same as the current format in this - * ImageComponent3D object. The index must not exceed the depth of this + * The size (width and height) must be the same as the current size of this * ImageComponent3D object. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalStateException if the image class is not + * ImageClass.BUFFERED_IMAGE. + * + * @exception IllegalArgumentException if the width and height the image + * is not equal to the width and height of this ImageComponent object. */ public void set(int index, BufferedImage image) { checkForLiveOrCompiled(); @@ -334,30 +469,71 @@ public class ImageComponent3D extends ImageComponent { * reference to the RenderedImage is saved, but the data is not * necessarily copied. * - * @param index the image index + * @param index the image index. + * The index must be less than the depth of this ImageComponent3D object. + * * @param image RenderedImage object containing the image. - * The format and size must be the same as the current format in this - * ImageComponent3D object. The index must not exceed the depth of this + * The size (width and height) must be the same as the current size of this * ImageComponent3D object. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalStateException if the image class is not one of: + * ImageClass.BUFFERED_IMAGE or ImageClass.RENDERED_IMAGE. + * + * @exception IllegalArgumentException if the width and height the image + * is not equal to the width and height of this ImageComponent object. + * * @since Java 3D 1.2 */ public void set(int index, RenderedImage image) { checkForLiveOrCompiled(); - if (image.getWidth() != this.getWidth()) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponent3D2")); - - if (image.getHeight() != this.getHeight()) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponent3D4")); - + // For RenderedImage the width and height checking is done in the retained. ((ImageComponent3DRetained)this.retained).set(index, image); } /** + * Sets this image component at the specified index to the + * specified NioImageBuffer object. If the data access mode is not + * by-reference, then the NioImageBuffer data is copied into this + * object. If the data access mode is by-reference, then a + * reference to the NioImageBuffer is saved, but the data is not + * necessarily copied. + * + * @param index the image index. + * The index must be less than the depth of this ImageComponent3D object. + * + * @param image NioImageBuffer object containing the image. + * The size (width and height) must be the same as the current size of this + * ImageComponent3D object. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalStateException if the image class is not + * ImageClass.NIO_IMAGE_BUFFER. + * + * @exception IllegalArgumentException if the width and height the image + * is not equal to the width and height of this ImageComponent object. + * + * @exception UnsupportedOperationException this method is not supported + * for Java 3D 1.5. + * + * @since Java 3D 1.5 + */ + public void set(int index, NioImageBuffer image) { + + throw new UnsupportedOperationException(); + /* + checkForLiveOrCompiled(); + // For NioImageBuffer the width and height checking is done in the retained. + ((ImageComponent3DRetained)this.retained).set(index, image); + */ + } + + /** * Retrieves the images from this ImageComponent3D object. If the * data access mode is not by-reference, then a copy of the images * is made. If the data access mode is by-reference, then the @@ -371,9 +547,8 @@ public class ImageComponent3D extends ImageComponent { * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * - * @exception IllegalStateException if the data access mode is - * by-reference and any image referenced by this ImageComponent3D - * object is not an instance of BufferedImage. + * @exception IllegalStateException if the image class is not + * ImageClass.BUFFERED_IMAGE. */ public BufferedImage[] getImage() { if (isLiveOrCompiled()) @@ -396,10 +571,12 @@ public class ImageComponent3D extends ImageComponent { * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalStateException if the image class is not one of: + * ImageClass.BUFFERED_IMAGE or ImageClass.RENDERED_IMAGE. + * * @since Java 3D 1.2 */ public RenderedImage[] getRenderedImage() { - if (isLiveOrCompiled()) if(!this.getCapability(ImageComponent.ALLOW_IMAGE_READ)) throw new CapabilityNotSetException(J3dI18N.getString("ImageComponent3D3")); @@ -407,21 +584,50 @@ public class ImageComponent3D extends ImageComponent { } /** + * Retrieves the images from this ImageComponent3D object. If the + * data access mode is not by-reference, then a copy of the images + * is made. If the data access mode is by-reference, then the + * references are returned. + * + * @return either a new array of new RenderedImage objects created from + * the data + * in this image component, or a new array of + * references to the RenderedImages that this image component refers to. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalStateException if the image class is not + * ImageClass.NIO_IMAGE_BUFFER. + * + * @exception UnsupportedOperationException this method is not supported + * for Java 3D 1.5. + * + * @since Java 3D 1.5 + */ + public NioImageBuffer[] getNioImage() { + + throw new UnsupportedOperationException(); + } + + /** * Retrieves one of the images from this ImageComponent3D object. If the * data access mode is not by-reference, then a copy of the image * is made. If the data access mode is by-reference, then the * reference is returned. * - * @param index the index of the image to retrieve + * @param index the index of the image to retrieve. + * The index must be less than the depth of this ImageComponent3D object. + * * @return either a new BufferedImage object created from the data * in this image component, or the BufferedImage object referenced * by this image component. + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * - * @exception IllegalStateException if the data access mode is - * by-reference and the image referenced by this ImageComponent3D - * object at the specified index is not an instance of BufferedImage. + * @exception IllegalStateException if the image class is not + * ImageClass.BUFFERED_IMAGE. */ public BufferedImage getImage(int index) { if (isLiveOrCompiled()) @@ -441,13 +647,19 @@ public class ImageComponent3D extends ImageComponent { * is made. If the data access mode is by-reference, then the * reference is returned. * - * @param index the index of the image to retrieve + * @param index the index of the image to retrieve. + * The index must be less than the depth of this ImageComponent3D object. + * * @return either a new RenderedImage object created from the data * in this image component, or the RenderedImage object referenced * by this image component. + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalStateException if the image class is not one of: + * ImageClass.BUFFERED_IMAGE or ImageClass.RENDERED_IMAGE. + * * @since Java 3D 1.2 */ public RenderedImage getRenderedImage(int index) { @@ -459,6 +671,35 @@ public class ImageComponent3D extends ImageComponent { } /** + * Retrieves one of the images from this ImageComponent3D object. If the + * data access mode is not by-reference, then a copy of the image + * is made. If the data access mode is by-reference, then the + * reference is returned. + * + * @param index the index of the image to retrieve. + * The index must be less than the depth of this ImageComponent3D object. + * + * @return either a new NioImageBuffer object created from the data + * in this image component, or the NioImageBuffer object referenced + * by this image component. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalStateException if the image class is not + * ImageClass.NIO_IMAGE_BUFFER. + * + * @exception UnsupportedOperationException this method is not supported + * for Java 3D 1.5. + * + * @since Java 3D 1.5 + */ + public NioImageBuffer getNioImage(int index) { + + throw new UnsupportedOperationException(); + } + + /** * Modifies a contiguous subregion of a particular slice of * image of this ImageComponent3D object. * Block of data of dimension (width * height) @@ -471,8 +712,8 @@ public class ImageComponent3D extends ImageComponent { * This method can only be used if the data access mode is * by-copy. If it is by-reference, see updateData(). * - * @param index index of the image to be modified. The index must not - * exceed the depth of the object. + * @param index index of the image to be modified. + * The index must be less than the depth of this ImageComponent3D object. * @param image RenderedImage object containing the subimage. * @param width width of the subregion. * @param height height of the subregion. @@ -485,15 +726,19 @@ public class ImageComponent3D extends ImageComponent { * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * * @exception IllegalStateException if the data access mode is * <code>BY_REFERENCE</code>. + * * @exception IllegalArgumentException if <code>width</code> or * <code>height</code> of * the subregion exceeds the dimension of the image in this object. + * * @exception IllegalArgumentException if <code>dstX</code> < 0, or * (<code>dstX</code> + <code>width</code>) > width of this object, or * <code>dstY</code> < 0, or * (<code>dstY</code> + <code>height</code>) > height of this object. + * * @exception IllegalArgumentException if <code>srcX</code> < 0, or * (<code>srcX</code> + <code>width</code>) > width of the RenderedImage * object containing the subimage, or @@ -501,6 +746,12 @@ public class ImageComponent3D extends ImageComponent { * (<code>srcY</code> + <code>height</code>) > height of the * RenderedImage object containing the subimage. * + * @exception IllegalArgumentException if the specified RenderedImage + * is not compatible with the existing RenderedImage. + * + * @exception IllegalStateException if the image class is not one of: + * ImageClass.BUFFERED_IMAGE or ImageClass.RENDERED_IMAGE. + * * @since Java 3D 1.3 */ public void setSubImage(int index, RenderedImage image, @@ -550,8 +801,8 @@ public class ImageComponent3D extends ImageComponent { * <p> * @param updater object whose updateData callback method will be * called to update the data referenced by this ImageComponent3D object. - * @param index index of the image to be modified. The index must - * not exceed the depth of this object. + * @param index index of the image to be modified. + * The index must be less than the depth of this ImageComponent3D object. * @param x starting X offset of the subregion. * @param y starting Y offset of the subregion. * @param width width of the subregion. @@ -617,7 +868,7 @@ public class ImageComponent3D extends ImageComponent { public NodeComponent cloneNodeComponent() { ImageComponent3DRetained rt = (ImageComponent3DRetained) retained; - ImageComponent3D img = new ImageComponent3D(rt.format, + ImageComponent3D img = new ImageComponent3D(rt.getFormat(), rt.width, rt.height, rt.depth); @@ -656,7 +907,7 @@ public class ImageComponent3D extends ImageComponent { void duplicateAttributes(NodeComponent originalNodeComponent, boolean forceDuplicate) { super.duplicateAttributes(originalNodeComponent, forceDuplicate); - + // TODO : Handle NioImageBuffer if its supported. RenderedImage imgs[] = ((ImageComponent3DRetained) originalNodeComponent.retained).getImage(); diff --git a/src/classes/share/javax/media/j3d/ImageComponent3DRetained.java b/src/classes/share/javax/media/j3d/ImageComponent3DRetained.java index 21813f8..91947bb 100644 --- a/src/classes/share/javax/media/j3d/ImageComponent3DRetained.java +++ b/src/classes/share/javax/media/j3d/ImageComponent3DRetained.java @@ -20,7 +20,6 @@ import java.awt.image.*; */ class ImageComponent3DRetained extends ImageComponentRetained { - int depth; // Depth of 3D image void setDepth(int depth) { this.depth = depth; @@ -30,7 +29,7 @@ class ImageComponent3DRetained extends ImageComponentRetained { * Retrieves the depth of this 3D image component object. * @return the format of this 3D image component object */ - final int getDepth() { + int getDepth() { return depth; } @@ -43,19 +42,135 @@ class ImageComponent3DRetained extends ImageComponentRetained { * ImageComponent3D object. The index must not exceed the depth of this * ImageComponent3D object. */ - final void set(int index, BufferedImage image) { - if (imageYup == null) - imageYup = new byte[height * width * depth * bytesPerPixelIfStored]; - imageDirty[index] = true; - storedYupFormat = internalFormat; - bytesPerYupPixelStored = bytesPerPixelIfStored; - copyImage(image, imageYup, true, index, storedYupFormat, - bytesPerYupPixelStored); - if (byReference) - bImage[index] = image; - } + void set(int index, BufferedImage image) { + + geomLock.getLock(); + + if(byReference) { + setRefImage(image,0); + } - final void set(int index, RenderedImage image) { + if(imageData == null) { + // Only do this once, on the first image + // Reset this flag to true, incase it was set to false due to + // the previous image type. + abgrSupported = true; + imageTypeIsSupported = isImageTypeSupported(image); + imageData = createRenderedImageDataObject(null); + } + else { + if(getImageType() != evaluateImageType(image)) { + // TODO need to throw illegal state exception + } + } + + if (imageTypeIsSupported) { + copySupportedImageToImageData(image, index, imageData); + } else { + // image type is unsupported, need to create a supported local copy. + // TODO : borrow code from JAI to convert to right format. + copyUnsupportedImageToImageData(image, index, imageData); + + } + + geomLock.unLock(); + + if (source.isLive()) { + // freeSurface(); + + // send a IMAGE_CHANGED message in order to + // notify all the users of the change + sendMessage(IMAGE_CHANGED, null); + } + } + + /** + * Copies the specified BufferedImage to this 3D image component + * object at the specified index. + * @param index the image index + * @param images BufferedImage object containing the image. + * The format and size must be the same as the current format in this + * ImageComponent3D object. The index must not exceed the depth of this + * ImageComponent3D object. + * + void set(int index, NioImageBuffer nioImage) { + + int width = nioImage.getWidth(); + int height = nioImage.getHeight(); + + if (!byReference) { + throw new IllegalArgumentException(J3dI18N.getString("Need_New_Message_XXXXXImageComponent2D7")); + } + if (!yUp) { + throw new IllegalArgumentException(J3dI18N.getString("Need_New_Message_XXXXXImageComponent2D8")); + } + + if (width != this.width) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent3D2")); + } + if (height != this.height) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent3D4")); + } + + geomLock.getLock(); + + setImageClass(nioImage); + + // This is a byRef image. + setRefImage(nioImage,0); + + if(imageData == null) { + // Only do this once, on the first image + // Reset this flag to true, incase it was set to false due to + // the previous image type. + abgrSupported = true; + + imageTypeIsSupported = isImageTypeSupported(nioImage); + + + // TODO : Need to handle null .... + imageData = createNioImageBufferDataObject(null); + } + else { + + //if(getImageType() != evaluateImageType(image)) { + // TODO need to throw illegal state exception + //} + + } + + if (imageTypeIsSupported) { + // TODO : Need to handle this ..... case .... + // copySupportedImageToImageData(image, index, imageData); + } else { + // System.err.println("Image format is unsupported -- illogical case"); + throw new AssertionError(); + } + + geomLock.unLock(); + + if (source.isLive()) { + // freeSurface(); + + // send a IMAGE_CHANGED message in order to + // notify all the users of the change + sendMessage(IMAGE_CHANGED, null); + } + } + */ + + void set(int index, RenderedImage image) { + + int width = image.getWidth(); + int height = image.getHeight(); + + if (width != this.width) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent3D2")); + } + if (height != this.height) { + throw new IllegalArgumentException(J3dI18N.getString("ImageComponent3D4")); + } + if (image instanceof BufferedImage) { set(index, ((BufferedImage)image)); } @@ -76,20 +191,21 @@ class ImageComponent3DRetained extends ImageComponentRetained { * @return a new array of new BufferedImage objects created from the * images in this ImageComponent3D object */ - final RenderedImage[] getRenderedImage() { + RenderedImage[] getRenderedImage() { int i; - RenderedImage bi[] = new RenderedImage[bImage.length]; + RenderedImage bi[] = new RenderedImage[depth]; + if (!byReference) { for (i=0; i<depth; i++) { - if (imageDirty[i]) { - retrieveBufferedImage(i); - } + bi[i] = imageData.createBufferedImage(i); } } - for (i = 0; i < bImage.length; i++) { - bi[i] = bImage[i]; - } - // If by reference, then the image should not be dirty + else { + for (i = 0; i < depth; i++) { + bi[i] = imageData.createBufferedImage(i); + } + } + return bi; } @@ -99,25 +215,24 @@ class ImageComponent3DRetained extends ImageComponentRetained { * @return a new array of new BufferedImage objects created from the * images in this ImageComponent3D object */ - final BufferedImage[] getImage() { + BufferedImage[] getImage() { int i; - BufferedImage bi[] = new BufferedImage[bImage.length]; + BufferedImage bi[] = new BufferedImage[depth]; if (!byReference) { for (i=0; i<depth; i++) { - if (imageDirty[i]) { - retrieveBufferedImage(i); - } + bi[i] = imageData.createBufferedImage(i); } } - - for (i = 0; i < bImage.length; i++) { - if (!(bImage[i] instanceof BufferedImage)) { - throw new IllegalStateException(J3dI18N.getString("ImageComponent3DRetained0")); - } - bi[i] = (BufferedImage) bImage[i]; - } - // If by reference, then the image should not be dirty + else { + for (i = 0; i < depth; i++) { + bi[i] = imageData.createBufferedImage(i); + if (!(bi[i] instanceof BufferedImage)) { + throw new IllegalStateException(J3dI18N.getString("ImageComponent3DRetained0")); + } + + } + } return bi; } @@ -127,13 +242,12 @@ class ImageComponent3DRetained extends ImageComponentRetained { * @return a new BufferedImage objects created from the * image at the specified index in this ImageComponent3D object */ - final RenderedImage getImage(int index) { + RenderedImage getImage(int index) { if (!byReference) { - if (imageDirty[index]) { - retrieveBufferedImage(index); - } + return imageData.createBufferedImage(index); } - return bImage[index]; + + return (RenderedImage) getRefImage(index); } /** @@ -149,17 +263,32 @@ class ImageComponent3DRetained extends ImageComponentRetained { // call the user supplied updateData method to update the data updater.updateData((ImageComponent3D)source, index, x, y, width, height); + RenderedImage refImage = (RenderedImage) getRefImage(index); + assert (refImage != null); + assert (imageData != null); + + // update the internal copy of the image data if a copy has been // made - if (imageYupAllocated) { - copyImage(bImage[0], (x + bImage[0].getMinX()), - (y + bImage[0].getMinY()), imageYup, x, y, - true, index, width, height, storedYupFormat, - bytesPerYupPixelStored); + int srcX = x + refImage.getMinX(); + int srcY = y + refImage.getMinY(); + + if (imageTypeIsSupported) { + if (refImage instanceof BufferedImage) { + copyImageLineByLine((BufferedImage)refImage, srcX, srcY, x, y, index, width, height, imageData); + } else { + copySupportedImageToImageData(refImage, srcX, srcY, x, y, index, width, height, imageData); + } + } else { + // image type is unsupported, need to create a supported local copy. + // TODO : Should look into borrow code from JAI to convert to right format. + if (refImage instanceof BufferedImage) { + copyUnsupportedImageToImageData((BufferedImage)refImage, srcX, srcY, x, y, index, width, height, imageData); + } else { + copyUnsupportedImageToImageData(refImage, srcX, srcY, x, y, index, width, height, imageData); + } } - - imageDirty[index] = true; - + geomLock.unLock(); @@ -170,7 +299,7 @@ class ImageComponent3DRetained extends ImageComponentRetained { ImageComponentUpdateInfo info; - info = VirtualUniverse.mc.getFreeImageUpdateInfo(); + info = new ImageComponentUpdateInfo(); info.x = x; info.y = y; info.z = index; @@ -184,15 +313,37 @@ class ImageComponent3DRetained extends ImageComponentRetained { void setSubImage(int index, RenderedImage image, int width, int height, int srcX, int srcY, int dstX, int dstY) { - geomLock.getLock(); - - if (imageYupAllocated) { - copyImage(image, srcX, srcY, imageYup, dstX, dstY, - true, index, width, height, storedYupFormat, - bytesPerYupPixelStored); + if(!isSubImageTypeEqual(image)) { + throw new IllegalStateException( + J3dI18N.getString("ImageComponent2D6")); } - imageDirty[index] = true; + // Can't be byReference + assert (!byReference); + assert (imageData != null); + + geomLock.getLock(); + + if (imageTypeIsSupported) { + // Either not byRef or not yUp or not both + // System.err.println("ImageComponen3DRetained.setSubImage() : (imageTypeSupported ) --- (1)"); + if (image instanceof BufferedImage) { + copyImageLineByLine((BufferedImage)image, srcX, srcY, dstX, dstY, index, width, height, imageData); + } + else { + copySupportedImageToImageData(image, srcX, srcY, dstX, dstY, index, width, height, imageData); + } + } else { + // image type is unsupported, need to create a supported local copy. + // TODO : Should look into borrow code from JAI to convert to right format. + // System.err.println("ImageComponent3DRetained.setSubImage() : (imageTypeSupported == false) --- (2)"); + if (image instanceof BufferedImage) { + copyUnsupportedImageToImageData((BufferedImage)image, srcX, srcY, dstX, dstY, index, width, height, imageData); + } + else { + copyUnsupportedImageToImageData(image, srcX, srcY, dstX, dstY, index, width, height, imageData); + } + } geomLock.unLock(); @@ -204,7 +355,7 @@ class ImageComponent3DRetained extends ImageComponentRetained { ImageComponentUpdateInfo info; - info = VirtualUniverse.mc.getFreeImageUpdateInfo(); + info = new ImageComponentUpdateInfo(); info.x = dstX; info.y = dstY; info.z = index; @@ -214,4 +365,35 @@ class ImageComponent3DRetained extends ImageComponentRetained { sendMessage(SUBIMAGE_CHANGED, info); } } + + ImageComponentRetained createNextLevelMipMapImage() { + + int xScale, yScale, newWidth, newHeight; + + if (width > 1) { + newWidth = width >> 1; + xScale = 2; + } else { + newWidth = 1; + xScale = 1; + } + if (height > 1) { + newHeight = height >> 1; + yScale = 2; + } else { + newHeight = 1; + yScale = 1; + } + + ImageComponent3DRetained newImage = new ImageComponent3DRetained(); + newImage.processParams(getFormat(), newWidth, newHeight, depth); + newImage.imageData = newImage.createRenderedImageDataObject(null); + + for (int i = 0; i < depth; i++) { + newImage.scaleImage(xScale, yScale, depth, this); + } + + return newImage; + + } } diff --git a/src/classes/share/javax/media/j3d/ImageComponentRetained.java b/src/classes/share/javax/media/j3d/ImageComponentRetained.java index c62ca24..2279b89 100644 --- a/src/classes/share/javax/media/j3d/ImageComponentRetained.java +++ b/src/classes/share/javax/media/j3d/ImageComponentRetained.java @@ -12,10 +12,17 @@ package javax.media.j3d; +import java.nio.Buffer; import java.util.*; import java.awt.image.*; import java.awt.color.ColorSpace; -import java.awt.Transparency; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.RenderedImage; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; + /** * Abstract class that is used to define 2D or 3D ImageComponent classes @@ -25,1033 +32,438 @@ import java.awt.Transparency; */ abstract class ImageComponentRetained extends NodeComponentRetained { - int format; // PixelArray format (RGB, RGBA, ALPHA, etc.) + + // change flag + static final int IMAGE_CHANGED = 0x01; + static final int SUBIMAGE_CHANGED = 0x02; + + static final int TYPE_BYTE_BGR = 0x1; + static final int TYPE_BYTE_RGB = 0x2; + static final int TYPE_BYTE_ABGR = 0x4; + static final int TYPE_BYTE_RGBA = 0x8; + static final int TYPE_BYTE_LA = 0x10; + static final int TYPE_BYTE_GRAY = 0x20; + static final int TYPE_USHORT_GRAY = 0x40; + static final int TYPE_INT_BGR = 0x80; + static final int TYPE_INT_RGB = 0x100; + static final int TYPE_INT_ARGB = 0x200; + + enum ImageFormatType { + TYPE_UNKNOWN, + TYPE_BYTE_BGR, + TYPE_BYTE_RGB, + TYPE_BYTE_ABGR, + TYPE_BYTE_RGBA, + TYPE_BYTE_LA, + TYPE_BYTE_GRAY, + TYPE_USHORT_GRAY, + TYPE_INT_BGR, + TYPE_INT_RGB, + TYPE_INT_ARGB + } + + static final int IMAGE_DATA_TYPE_BYTE_ARRAY = 0x1000; + static final int IMAGE_DATA_TYPE_INT_ARRAY = 0x2000; + static final int IMAGE_DATA_TYPE_BYTE_BUFFER = 0x4000; + static final int IMAGE_DATA_TYPE_INT_BUFFER = 0x8000; + + enum ImageDataType { + TYPE_NULL, + TYPE_BYTE_ARRAY, + TYPE_INT_ARRAY, + TYPE_BYTE_BUFFER, + TYPE_INT_BUFFER + } + + private int apiFormat; // The format set by user. int width; // Width of PixelArray int height; // Height of PixelArray - byte[][] imageYdown = new byte[1][]; // 2D array of pixel values in - // one of various formats - Y downwards - byte[] imageYup; // 2D or 3D array of pixel values in - // one of various formats - Y upwards - - int bytesPerPixel; // computed from input format - boolean usedByRaster = false; // used by a raster object? - boolean usedByTexture = false; // used by a texture object? - - boolean byReference = false; // Is the imageComponent by reference - boolean yUp = false; - - // array of Buffered image - // This will store the refImage array, if the imagecomponent - // is by reference - RenderedImage[] bImage; - boolean[] imageDirty; // array of image dirty flag - - boolean noAlpha = false; - - // Format of the Yup and Ydown image - // in the case of "by Copy" it is RGBA - // In the case of "by ref" it may be one of the original - // formats supported by OpenGL - /* - int storedFormat; - */ - int bytesPerPixelIfStored; // Number of bytes if a copy is made - int storedYupFormat; - int storedYdownFormat; - - int bytesPerYupPixelStored; - int bytesPerYdownPixelStored; + int depth; // Depth of PixelArray + boolean byReference = false; // Is the imageComponent by reference + boolean yUp = false; + boolean imageTypeIsSupported; + boolean abgrSupported = true; + boolean npotSupported = true; + private int unitsPerPixel; + private int numberOfComponents; - int internalFormat; // Used when a copy is made, RGBA, LA, L - boolean imageYupAllocated = false; - boolean imageYdownAllocated = false; - - // If cache is dirty (clearLive, setLive has occureed), then - // extension based cache needs to be re-evaluated - boolean imageYupCacheDirty = false; - boolean imageYdownCacheDirty = false; + // Note : This is unuse for NioImageBuffer. + // The image type of the input image. Using the constant in BufferedImage + private int imageType; - - static final int BYTE_RGBA = 0x1; - static final int BYTE_ABGR = 0x2; - static final int BYTE_GRAY = 0x4; - static final int USHORT_GRAY = 0x8; - static final int BYTE_LA = 0x10; - static final int BYTE_BGR = 0x20; - static final int BYTE_RGB = 0x40; - - int imageYupClass = 0; - int imageYdownClass = 0; - static final int BUFFERED_IMAGE = 0x1; - static final int RENDERED_IMAGE = 0x2; + private ImageFormatType imageFormatType = ImageFormatType.TYPE_UNKNOWN; + ImageData imageData; + private ImageComponent.ImageClass imageClass = ImageComponent.ImageClass.BUFFERED_IMAGE; - // change flag - static final int IMAGE_CHANGED = 0x01; - static final int SUBIMAGE_CHANGED = 0x02; + // To support Non power of 2 (NPOT) image + // if enforceNonPowerOfTwoSupport is true (for examples Raster and Background) + // and imageData is a non power of 2 image + // and graphics driver doesn't support NPOT extension. + private ImageData imageDataPowerOfTwo; + private AffineTransformOp powerOfTwoATOp; + private boolean enforceNonPowerOfTwoSupport = false; + private boolean usedByOffScreenCanvas = false; + + // This will store the referenced Images for reference case. + // private RenderedImage refImage[] = null; + private Object refImage[] = null; // Lock used in the "by ref case" GeometryLock geomLock = new GeometryLock(); - - int minTileX = 0; - int minTileY = 0; - int minTileZ = 0; - + int tilew = 0; int tileh = 0; - int tiled = 0; - int numXTiles = 0; int numYTiles = 0; - int numZTiles = 0; - - int tileGridXOffset = 0; - int tileGridYOffset = 0; - - - int minX = 0; - int minY = 0; // lists of Node Components that are referencing this ImageComponent // object. This list is used to notify the referencing node components // of any changes of this ImageComponent. - ArrayList userList = new ArrayList(); - + + abstract ImageComponentRetained createNextLevelMipMapImage(); + /** * Retrieves the width of this image component object. * @return the width of this image component object - */ - final int getWidth() { + */ + int getWidth() { return width; } - + /** * Retrieves the height of this image component object. * @return the height of this image component object - */ - final int getHeight() { + */ + int getHeight() { return height; } - - /** - * Retrieves the format of this image component object. - * @return the format of this image component object - */ - final int getFormat() { - return format; - } - + /** - * Check if ImageComponent parameters have valid values.. + * Retrieves the apiFormat of this image component object. + * + * @return the apiFormat of this image component object */ - void processParams(int format, int width, int height, int depth) { - if (width < 1) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponentRetained0")); - - if (height < 1) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponentRetained1")); - - if (depth < 1) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponentRetained2")); - - if (format < 1 || format > ImageComponent.FORMAT_TOTAL) - throw new IllegalArgumentException(J3dI18N.getString("ImageComponentRetained3")); - this.format = format; - this.width = width; - this.height = height; - imageDirty = new boolean[depth]; - for (int i=0; i< depth; i++) - imageDirty[i] = false; - bImage = new RenderedImage[depth]; - - noAlpha = (format == ImageComponent.FORMAT_RGB || - format == ImageComponent.FORMAT_RGB4 || - format == ImageComponent.FORMAT_R3_G3_B2 || - format == ImageComponent.FORMAT_RGB5); - - // If the format is 8bit per component, we may send it down - // to OpenGL directly if its by ref case - switch (format) { - case ImageComponent.FORMAT_RGB:// same as ImageComponent.FORMAT_RGB8 - bytesPerPixel = 3; - bytesPerPixelIfStored = 4; - internalFormat = BYTE_RGBA; - break; - case ImageComponent.FORMAT_RGBA:// same as ImageComponent.FORMAT_RGBA8 - bytesPerPixel = 4; - bytesPerPixelIfStored = 4; - internalFormat = BYTE_RGBA; - break; - case ImageComponent.FORMAT_RGB5: - bytesPerPixel = 2; - bytesPerPixelIfStored = 4; - internalFormat = BYTE_RGBA; - break; - case ImageComponent.FORMAT_RGB5_A1: - bytesPerPixel = 2; - bytesPerPixelIfStored = 4; - internalFormat = BYTE_RGBA; - break; - case ImageComponent.FORMAT_RGB4: - bytesPerPixel = 2; - bytesPerPixelIfStored = 4; - internalFormat = BYTE_RGBA; - break; - case ImageComponent.FORMAT_RGBA4: - bytesPerPixel = 2; - bytesPerPixelIfStored = 4; - internalFormat = BYTE_RGBA; - break; - case ImageComponent.FORMAT_R3_G3_B2: - bytesPerPixel = 1; - bytesPerPixelIfStored = 4; - internalFormat = BYTE_RGBA; - break; - case ImageComponent.FORMAT_LUM4_ALPHA4: - bytesPerPixel = 1; - bytesPerPixelIfStored = 2; - internalFormat = BYTE_LA; - break; - case ImageComponent.FORMAT_LUM8_ALPHA8: - bytesPerPixel = 2; - bytesPerPixelIfStored = 2; - internalFormat = BYTE_LA; - break; - case ImageComponent.FORMAT_CHANNEL8: - bytesPerPixel = 1; - bytesPerPixelIfStored = 1; - internalFormat = BYTE_GRAY; - break; - default: - // ERROR + int getFormat() { + return apiFormat; + } + + void setFormat(int format) { + this.apiFormat = format; + } + + void setByReference(boolean byReference) { + this.byReference = byReference; + } + + boolean isByReference() { + return byReference; + } + + void setYUp( boolean yUp) { + this.yUp = yUp; + } + + boolean isYUp() { + return yUp; + } + + int getUnitsPerPixel() { + return unitsPerPixel; + } + + void setUnitsPerPixel(int ipp) { + unitsPerPixel = ipp; + } + + ImageComponent.ImageClass getImageClass() { + return imageClass; + } + + void setImageClass(RenderedImage image) { + if(image instanceof BufferedImage) { + imageClass = ImageComponent.ImageClass.BUFFERED_IMAGE; + } else { + imageClass = ImageComponent.ImageClass.RENDERED_IMAGE; } } - - void setTextureRef() { - usedByTexture = true; + + void setImageClass(NioImageBuffer image) { + imageClass = ImageComponent.ImageClass.NIO_IMAGE_BUFFER; } - - void setRasterRef() { - usedByRaster = true; + + void setEnforceNonPowerOfTwoSupport(boolean npot) { + this.enforceNonPowerOfTwoSupport = npot; } - - - boolean formatMatches(int format, RenderedImage ri) { - - // there is no RenderedImage format that matches BYTE_LA - if (format == BYTE_LA) { - return false; - } - - int riFormat = getImageType(ri); - - if ((format == BYTE_ABGR && riFormat == BufferedImage.TYPE_4BYTE_ABGR) - || (format == BYTE_BGR && riFormat == BufferedImage.TYPE_3BYTE_BGR) - || (format == BYTE_GRAY && riFormat == BufferedImage.TYPE_BYTE_GRAY) - || (format == USHORT_GRAY && riFormat == - BufferedImage.TYPE_USHORT_GRAY)) { - return true; - } - - if (riFormat == BufferedImage.TYPE_CUSTOM) { - if (is4ByteRGBAOr3ByteRGB(ri)) { - int numBands = ri.getSampleModel().getNumBands(); - if (numBands == 3 && format == BYTE_RGB) { - return true; - } else if (numBands == 4 && format == BYTE_RGBA) { - return true; - } - } - } - - return false; + + void setUsedByOffScreen(boolean used) { + usedByOffScreenCanvas = used; } - - /** - * copy complete region of a RenderedImage - */ - final void copyImage(RenderedImage ri, byte[] image, - boolean usedByTexture, int depth, - int imageFormat, int imageBytesPerPixel) { - - if (ri instanceof BufferedImage) { - copyImage((BufferedImage)ri, 0, 0, image, 0, 0, - usedByTexture, depth, width, height, - imageFormat, imageBytesPerPixel); - } else { - copyImage(ri, ri.getMinX(), ri.getMinY(), - image, 0, 0, usedByTexture, depth, width, height, - imageFormat, imageBytesPerPixel); - } + + boolean getUsedByOffScreen() { + return usedByOffScreenCanvas; } - - - /** - * copy subregion of a RenderedImage - */ - final void copyImage(RenderedImage ri, int srcX, int srcY, - byte[] image, int dstX, int dstY, - boolean usedByTexture, int depth, - int copywidth, int copyheight, - int imageFormat, int imageBytesPerPixel) { - - if (ri instanceof BufferedImage) { - copyImage((BufferedImage)ri, srcX, srcY, image, dstX, dstY, - usedByTexture, depth, copywidth, copyheight, - imageFormat, imageBytesPerPixel); - return; - } - - - int w, h, i, j, m, n; - int dstBegin; - Object pixel = null; - java.awt.image.Raster ras; - int lineBytes = width * imageBytesPerPixel; // nbytes per line in - // dst image buffer - int sign; // -1 for going down - int dstLineBytes; // sign * lineBytes - int tileStart; // destination buffer offset - // at the next left most tile - - int offset; - - ColorModel cm = ri.getColorModel(); - - int xoff = ri.getTileGridXOffset(); // tile origin x offset - int yoff = ri.getTileGridYOffset(); // tile origin y offset - int minTileX = ri.getMinTileX(); // min tile x index - int minTileY = ri.getMinTileY(); // min tile y index - tilew = ri.getTileWidth(); // tile width in pixels - tileh = ri.getTileHeight(); // tile height in pixels - - - // determine the first tile of the image - - float mt; - - mt = (float)(srcX - xoff) / (float)tilew; - if (mt < 0) { - minTileX = (int)(mt - 1); - } else { - minTileX = (int)mt; - } - - mt = (float)(srcY - yoff) / (float)tileh; - if (mt < 0) { - minTileY = (int)(mt - 1); - } else { - minTileY = (int)mt; - } - - - // determine the pixel offset of the upper-left corner of the - // first tile - - int startXTile = minTileX * tilew + xoff; - int startYTile = minTileY * tileh + yoff; - - - // image dimension in the first tile - - int curw = (startXTile + tilew - srcX); - int curh = (startYTile + tileh - srcY); - - - // check if the to-be-copied region is less than the tile image - // if so, update the to-be-copied dimension of this tile - - if (curw > copywidth) { - curw = copywidth; - } - - if (curh > copyheight) { - curh = copyheight; - } - - - // save the to-be-copied width of the left most tile - - int startw = curw; - - - // temporary variable for dimension of the to-be-copied region - - int tmpw = copywidth; - int tmph = copyheight; - - - // offset of the first pixel of the tile to be copied; offset is - // relative to the upper left corner of the title - - int x = srcX - startXTile; - int y = srcY - startYTile; - - - // determine the number of tiles in each direction that the - // image spans - - numXTiles = (copywidth + x) / tilew; - numYTiles = (copyheight + y) / tileh; - - if (((float)(copywidth + x ) % (float)tilew) > 0) { - numXTiles += 1; - } - - if (((float)(copyheight + y ) % (float)tileh) > 0) { - numYTiles += 1; - } - -/* - System.out.println("-----------------------------------------------"); - System.out.println("minTileX= " + minTileX + " minTileY= " + minTileY); - System.out.println("numXTiles= " + numXTiles + " numYTiles= " + numYTiles); - System.out.println("tilew= " + tilew + " tileh= " + tileh); - System.out.println("xoff= " + xoff + " yoff= " + yoff); - System.out.println("startXTile= " + startXTile + " startYTile= " + startYTile); - System.out.println("srcX= " + srcX + " srcY= " + srcY); - System.out.println("copywidth= " + copywidth + " copyheight= " + copyheight); - - System.out.println("rminTileX= " + ri.getMinTileX() + " rminTileY= " + ri.getMinTileY()); - System.out.println("rnumXTiles= " + ri.getNumXTiles() + " rnumYTiles= " + ri.getNumYTiles()); -*/ - - if ((!yUp && usedByTexture) || - (yUp && !usedByTexture)) { - - // destination buffer offset - - tileStart = ((height - dstY - 1) * width + dstX) - * imageBytesPerPixel; - - sign = -1; - dstLineBytes = -lineBytes; - } else { - - // destination buffer offset - - tileStart = (dstY * width + dstX) * imageBytesPerPixel; - sign = 1; - dstLineBytes = lineBytes; - } - -/* - System.out.println("tileStart= " + tileStart + " dstLineBytes= " + dstLineBytes); - System.out.println("startw= " + startw); -*/ - - // allocate memory for a pixel - - ras = ri.getTile(minTileX,minTileY); - pixel = getDataElementBuffer(ras); - - if (formatMatches(imageFormat, ri)) { - byte[] src; - int srcOffset, dstOffset; - int tileLineBytes= tilew * imageBytesPerPixel; - int copyBytes; - - for (n = minTileY; n < minTileY+numYTiles; n++) { - - dstBegin = tileStart; // destination buffer offset - tmpw = copywidth; // reset the width to be copied - curw = startw; // reset the width to be copied of - // the left most tile - x = srcX - startXTile; // reset the starting x offset of - // the left most tile - - for (m = minTileX; m < minTileX+numXTiles; m++) { - - // retrieve the raster for the next tile - ras = ri.getTile(m,n); - src = ((DataBufferByte)ras.getDataBuffer()).getData(); - - srcOffset = (y * tilew + x) * imageBytesPerPixel; - dstOffset = dstBegin; - - copyBytes = curw * imageBytesPerPixel; - - //System.out.println("curh = "+curh+" curw = "+curw); - //System.out.println("x = "+x+" y = "+y); - - for (h = 0; h < curh; h++) { - System.arraycopy(src, srcOffset, image, dstOffset, - copyBytes); - srcOffset += tileLineBytes; - dstOffset += dstLineBytes; - } - - // advance the destination buffer offset - dstBegin += curw * imageBytesPerPixel; - - // move to the next tile in x direction - x = 0; - - // determine the width of copy region of the next tile - - tmpw -= curw; - if (tmpw < tilew) { - curw = tmpw; - } else { - curw = tilew; - } - } - - - // we are done copying an array of tiles in the x direction - // advance the tileStart offset - - tileStart += width * imageBytesPerPixel * curh * sign; - - - // move to the next set of tiles in y direction - y = 0; - - // determine the height of copy region for the next set - // of tiles - tmph -= curh; - if (tmph < tileh) { - curh = tmph; - } else { - curh = tileh; - } - } - return; - } - - switch(format) { - case ImageComponent.FORMAT_RGBA8: - case ImageComponent.FORMAT_RGB5_A1: - case ImageComponent.FORMAT_RGBA4: { - // System.out.println("Case 1: byReference = "+byReference); - for (n = minTileY; n < minTileY+numYTiles; n++) { - - dstBegin = tileStart; // destination buffer offset - tmpw = copywidth; // reset the width to be copied - curw = startw; // reset the width to be copied of - // the left most tile - x = srcX - startXTile; // reset the starting x offset of - // the left most tile - - for (m = minTileX; m < minTileX+numXTiles; m++) { - - // retrieve the raster for the next tile - ras = ri.getTile(m,n); - - j = dstBegin; - offset = 0; - - //System.out.println("curh = "+curh+" curw = "+curw); - //System.out.println("x = "+x+" y = "+y); - - for (h = y; h < (y + curh); h++) { - // System.out.println("j = "+j); - for (w = x; w < (x + curw); w++) { - ras.getDataElements(w, h, pixel); - image[j++] = (byte)cm.getRed(pixel); - image[j++] = (byte)cm.getGreen(pixel); - image[j++] = (byte)cm.getBlue(pixel); - image[j++] = (byte)cm.getAlpha(pixel); - } - offset += dstLineBytes; - j = dstBegin + offset; - } - - // advance the destination buffer offset - dstBegin += curw * imageBytesPerPixel; - - // move to the next tile in x direction - x = 0; - - // determine the width of copy region of the next tile - - tmpw -= curw; - if (tmpw < tilew) { - curw = tmpw; - } else { - curw = tilew; - } - } - - - // we are done copying an array of tiles in the x direction - // advance the tileStart offset - - tileStart += width * imageBytesPerPixel * curh * sign; - - - // move to the next set of tiles in y direction - y = 0; - - // determine the height of copy region for the next set - // of tiles - tmph -= curh; - if (tmph < tileh) { - curh = tmph; - } else { - curh = tileh; - } - } - } - break; - case ImageComponent.FORMAT_RGB8: - case ImageComponent.FORMAT_RGB5: - case ImageComponent.FORMAT_RGB4: - case ImageComponent.FORMAT_R3_G3_B2: { - for (n = minTileY; n < minTileY+numYTiles; n++) { - - dstBegin = tileStart; // destination buffer offset - tmpw = copywidth; // reset the width to be copied - curw = startw; // reset the width to be copied of - // the left most tile - x = srcX - startXTile; // reset the starting x offset of - // the left most tile - - for (m = minTileX; m < minTileX+numXTiles; m++) { - - // retrieve the raster for the next tile - ras = ri.getTile(m,n); - - j = dstBegin; - offset = 0; - - //System.out.println("curh = "+curh+" curw = "+curw); - //System.out.println("x = "+x+" y = "+y); - - for (h = y; h < (y + curh); h++) { - // System.out.println("j = "+j); - for (w = x; w < (x + curw); w++) { - ras.getDataElements(w, h, pixel); - image[j++] = (byte)cm.getRed(pixel); - image[j++] = (byte)cm.getGreen(pixel); - image[j++] = (byte)cm.getBlue(pixel); - image[j++] = (byte)255; - } - offset += dstLineBytes; - j = dstBegin + offset; - } - - // advance the destination buffer offset - dstBegin += curw * imageBytesPerPixel; - - // move to the next tile in x direction - x = 0; - - // determine the width of copy region of the next tile - - tmpw -= curw; - if (tmpw < tilew) { - curw = tmpw; - } else { - curw = tilew; - } - } - - - // we are done copying an array of tiles in the x direction - // advance the tileStart offset - - tileStart += width * imageBytesPerPixel * curh * sign; - - - // move to the next set of tiles in y direction - y = 0; - - // determine the height of copy region for the next set - // of tiles - tmph -= curh; - if (tmph < tileh) { - curh = tmph; - } else { - curh = tileh; - } - } - } - break; - case ImageComponent.FORMAT_LUM8_ALPHA8: - case ImageComponent.FORMAT_LUM4_ALPHA4: { - for (n = minTileY; n < minTileY+numYTiles; n++) { - - dstBegin = tileStart; // destination buffer offset - tmpw = copywidth; // reset the width to be copied - curw = startw; // reset the width to be copied of - // the left most tile - x = srcX - startXTile; // reset the starting x offset of - // the left most tile - - for (m = minTileX; m < minTileX+numXTiles; m++) { - - // retrieve the raster for the next tile - ras = ri.getTile(m,n); - - j = dstBegin; - offset = 0; - - //System.out.println("curh = "+curh+" curw = "+curw); - //System.out.println("x = "+x+" y = "+y); - - for (h = y; h < (y + curh); h++) { - // System.out.println("j = "+j); - for (w = x; w < (x + curw); w++) { - ras.getDataElements(w, h, pixel); - image[j++] = (byte)cm.getRed(pixel); - image[j++] = (byte)cm.getAlpha(pixel); - } - offset += dstLineBytes; - j = dstBegin + offset; - } - - // advance the destination buffer offset - dstBegin += curw * imageBytesPerPixel; - - // move to the next tile in x direction - x = 0; - - // determine the width of copy region of the next tile - - tmpw -= curw; - if (tmpw < tilew) { - curw = tmpw; - } else { - curw = tilew; - } - } - - - // we are done copying an array of tiles in the x direction - // advance the tileStart offset - - tileStart += width * imageBytesPerPixel * curh * sign; - - - // move to the next set of tiles in y direction - y = 0; - - // determine the height of copy region for the next set - // of tiles - tmph -= curh; - if (tmph < tileh) { - curh = tmph; - } else { - curh = tileh; - } - } - } - break; - case ImageComponent.FORMAT_CHANNEL8: { - for (n = minTileY; n < minTileY+numYTiles; n++) { - - dstBegin = tileStart; // destination buffer offset - tmpw = copywidth; // reset the width to be copied - curw = startw; // reset the width to be copied of - // the left most tile - x = srcX - startXTile; // reset the starting x offset of - // the left most tile - - for (m = minTileX; m < minTileX+numXTiles; m++) { - - // retrieve the raster for the next tile - ras = ri.getTile(m,n); - - j = dstBegin; - offset = 0; - - //System.out.println("curh = "+curh+" curw = "+curw); - //System.out.println("x = "+x+" y = "+y); - - for (h = y; h < (y + curh); h++) { - // System.out.println("j = "+j); - for (w = x; w < (x + curw); w++) { - ras.getDataElements(w, h, pixel); - image[j++] = (byte)cm.getRed(pixel); - } - offset += dstLineBytes; - j = dstBegin + offset; - } - - // advance the destination buffer offset - dstBegin += curw * imageBytesPerPixel; - - // move to the next tile in x direction - x = 0; - - // determine the width of copy region of the next tile - - tmpw -= curw; - if (tmpw < tilew) { - curw = tmpw; - } else { - curw = tilew; - } - } - - - // we are done copying an array of tiles in the x direction - // advance the tileStart offset - - tileStart += width * imageBytesPerPixel * curh * sign; - - - // move to the next set of tiles in y direction - y = 0; - - // determine the height of copy region for the next set - // of tiles - tmph -= curh; - if (tmph < tileh) { - curh = tmph; - } else { - curh = tileh; - } - } - } - break; - default: - break; - } + + int getNumberOfComponents() { + return numberOfComponents; } - - - /** - * Copy entire image data from Buffered Image to - * ImageComponent's internal representation - */ - final void copyImage(BufferedImage bi, byte[] image, - boolean usedByTexture, int depth, - int imageFormat, int imageBytesPerPixel) { - copyImage(bi, 0, 0, image, 0, 0, usedByTexture, depth, - width, height, imageFormat, imageBytesPerPixel); + + void setNumberOfComponents(int numberOfComponents) { + this.numberOfComponents = numberOfComponents; } - - /** - * Copy specified region of image data from Buffered Image to - * ImageComponent's internal representation - */ - final void copyImage(BufferedImage bi, int srcX, int srcY, - byte[] image, int dstX, int dstY, boolean usedByTexture, - int depth, int copywidth, int copyheight, - int imageFormat, int imageBytesPerPixel) { - - int w, h, i, j; - int rowBegin, // src begin row index - srcBegin, // src begin offset - dstBegin, // dst begin offset - rowInc, // row increment - // -1 --- ydown - // 1 --- yup - row; - Object pixel = null; - - rowBegin = srcY; - rowInc = 1; - - int dstBytesPerRow = width * imageBytesPerPixel; // bytes per row - // in dst image - - if ((!yUp && usedByTexture) || (yUp && !usedByTexture)) { - dstBegin = (depth * width * height + - (height - dstY - 1) * width + dstX) * - imageBytesPerPixel; - - dstBytesPerRow = - 1 * dstBytesPerRow; - - } else { - dstBegin = (dstY * width + dstX) * imageBytesPerPixel; - } - - // if the image format matches the format of the incoming - // buffered image, then do a straight copy, else do the - // format conversion while copying the data - - if (formatMatches(imageFormat, bi)) { - byte[] byteData = - ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); - int copyBytes = copywidth * imageBytesPerPixel; - int scanline = width * imageBytesPerPixel; - - srcBegin = (rowBegin * width + srcX) * imageBytesPerPixel; - for (h = 0; h < copyheight; h++) { - System.arraycopy(byteData, srcBegin, image, dstBegin, copyBytes); - dstBegin += dstBytesPerRow; - srcBegin += scanline; - } - } else { - - int biType = bi.getType(); - if ((biType == BufferedImage.TYPE_INT_ARGB || - biType == BufferedImage.TYPE_INT_RGB) && - (format == ImageComponent.FORMAT_RGBA8 || - format == ImageComponent.FORMAT_RGB8)) { - - // optimized cases - - int[] intData = - ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); - int rowOffset = rowInc * width; - int intPixel; - - srcBegin = rowBegin * width + srcX; - - if (biType == BufferedImage.TYPE_INT_ARGB && - format == ImageComponent.FORMAT_RGBA8) { - for (h = 0; h < copyheight; h++) { - i = srcBegin; - j = dstBegin; - for (w = 0; w < copywidth; w++, i++) { - intPixel = intData[i]; - image[j++] = (byte)((intPixel >> 16) & 0xff); - image[j++] = (byte)((intPixel >> 8) & 0xff); - image[j++] = (byte)(intPixel & 0xff); - image[j++] = (byte)((intPixel >> 24) & 0xff); - } - srcBegin += rowOffset; - dstBegin += dstBytesPerRow; - } - } else { // format == ImageComponent.FORMAT_RGB8 - for (h = 0; h < copyheight; h++) { - i = srcBegin; - j = dstBegin; - for (w = 0; w < copywidth; w++, i++) { - intPixel = intData[i]; - image[j++] = (byte)((intPixel >> 16) & 0xff); - image[j++] = (byte)((intPixel >> 8) & 0xff); - image[j++] = (byte)(intPixel & 0xff); - image[j++] = (byte)255; - } - srcBegin += rowOffset; - dstBegin += dstBytesPerRow; - } - } - - } else if ((biType == BufferedImage.TYPE_BYTE_GRAY) && - (format == ImageComponent.FORMAT_CHANNEL8)) { - - byte[] byteData = - ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); - int rowOffset = rowInc * width; - - j = dstBegin; - srcBegin = rowBegin * width + srcX; - - for (h = 0; h < copyheight; - h++, j += width, srcBegin += rowOffset) { - System.arraycopy(byteData, srcBegin, image, j, copywidth); - } - } else { - // non-optimized cases - - WritableRaster ras = bi.getRaster(); - ColorModel cm = bi.getColorModel(); - pixel = getDataElementBuffer(ras); - - switch(format) { - case ImageComponent.FORMAT_RGBA8: - case ImageComponent.FORMAT_RGB5_A1: - case ImageComponent.FORMAT_RGBA4: { - for (row = rowBegin, h = 0; - h < copyheight; h++, row += rowInc) { - j = dstBegin; - for (w = srcX; w < (copywidth + srcX); w++) { - ras.getDataElements(w, row, pixel); - image[j++] = (byte)cm.getRed(pixel); - image[j++] = (byte)cm.getGreen(pixel); - image[j++] = (byte)cm.getBlue(pixel); - image[j++] = (byte)cm.getAlpha(pixel); - } - dstBegin += dstBytesPerRow; - } - } + + int getImageDataTypeIntValue() { + int idtValue = -1; + switch(imageData.imageDataType) { + case TYPE_BYTE_ARRAY: + idtValue = IMAGE_DATA_TYPE_BYTE_ARRAY; break; - - case ImageComponent.FORMAT_RGB8: - case ImageComponent.FORMAT_RGB5: - case ImageComponent.FORMAT_RGB4: - case ImageComponent.FORMAT_R3_G3_B2: { - for (row = rowBegin, h = 0; - h < copyheight; h++, row += rowInc) { - j = dstBegin; - for (w = srcX; w < (copywidth + srcX); w++) { - ras.getDataElements(w, row, pixel); - image[j++] = (byte)cm.getRed(pixel); - image[j++] = (byte)cm.getGreen(pixel); - image[j++] = (byte)cm.getBlue(pixel); - image[j++] = (byte)255; - } - dstBegin += dstBytesPerRow; - } - } + case TYPE_INT_ARRAY: + idtValue = IMAGE_DATA_TYPE_INT_ARRAY; break; - - case ImageComponent.FORMAT_LUM8_ALPHA8: - case ImageComponent.FORMAT_LUM4_ALPHA4: { - for (row = rowBegin, h = 0; - h < copyheight; h++, row += rowInc) { - j = dstBegin; - for (w = srcX; w < (copywidth + srcX); w++) { - ras.getDataElements(w, row, pixel); - image[j++] = (byte)cm.getRed(pixel); - image[j++] = (byte)cm.getAlpha(pixel); - } - dstBegin += dstBytesPerRow; - } - } - break; - - case ImageComponent.FORMAT_CHANNEL8: { - for (row = rowBegin, h = 0; - h < copyheight; h++, row += rowInc) { - j = dstBegin; - for (w = srcX; w < (copywidth + srcX); w++) { - ras.getDataElements(w, row, pixel); - image[j++] = (byte)cm.getRed(pixel); - } - dstBegin += dstBytesPerRow; - } + case TYPE_BYTE_BUFFER: + idtValue = IMAGE_DATA_TYPE_BYTE_BUFFER; + break; + case TYPE_INT_BUFFER: + idtValue = IMAGE_DATA_TYPE_INT_BUFFER; + break; + default : + assert false; + } + return idtValue; + + } + + int getImageFormatTypeIntValue(boolean powerOfTwoData) { + int iftValue = -1; + switch(imageFormatType) { + case TYPE_BYTE_BGR: + iftValue = TYPE_BYTE_BGR; + break; + case TYPE_BYTE_RGB: + iftValue = TYPE_BYTE_RGB; + break; + case TYPE_BYTE_ABGR: + iftValue = TYPE_BYTE_ABGR; + break; + case TYPE_BYTE_RGBA: + if((imageDataPowerOfTwo != null) && (powerOfTwoData)) { + iftValue = TYPE_BYTE_ABGR; } - break; + else { + iftValue = TYPE_BYTE_RGBA; } + break; + case TYPE_BYTE_LA: + iftValue = TYPE_BYTE_LA; + break; + case TYPE_BYTE_GRAY: + iftValue = TYPE_BYTE_GRAY; + break; + case TYPE_USHORT_GRAY: + iftValue = TYPE_USHORT_GRAY; + break; + case TYPE_INT_BGR: + iftValue = TYPE_INT_BGR; + break; + case TYPE_INT_RGB: + iftValue = TYPE_INT_RGB; + break; + case TYPE_INT_ARGB: + iftValue = TYPE_INT_ARGB; + break; + default: + throw new AssertionError(); + } + return iftValue; + } + + // Note: This method for RenderedImage, can't be used by NioImageBuffer. + int getImageType() { + return imageType; + } + + void setImageFormatType(ImageFormatType ift) { + this.imageFormatType = ift; + } + + ImageFormatType getImageFormatType() { + return this.imageFormatType; + } + + void setRefImage(Object image, int index) { + this.refImage[index] = image; + } + + Object getRefImage(int index) { + return this.refImage[index]; + } + + ImageData getImageData(boolean npotSupportNeeded) { + if(npotSupportNeeded) { + assert enforceNonPowerOfTwoSupport; + if(imageDataPowerOfTwo != null) { + return imageDataPowerOfTwo; } - } - } - + } + return imageData; + } - - - final int getBytesStored(int f) { - int val = 0; - switch(f) { - case BYTE_RGBA: - val = 4; - break; - case BYTE_ABGR: - val = 4; - break; - case BYTE_GRAY: - val = 1; - break; - case USHORT_GRAY: - val = 2; - break; - case BYTE_LA: - val = 2; - break; - case BYTE_BGR:; - val = 3; - break; - case BYTE_RGB:; - val = 3; - break; - } - return val; + boolean isImageTypeSupported() { + return imageTypeIsSupported; } - - - boolean is4ByteRGBAOr3ByteRGB(RenderedImage ri) { + + /** + * Check if ImageComponent parameters have valid values. + */ + void processParams(int format, int width, int height, int depth) { + if (width < 1) + throw new IllegalArgumentException(J3dI18N.getString("ImageComponentRetained0")); + + if (height < 1) + throw new IllegalArgumentException(J3dI18N.getString("ImageComponentRetained1")); + + if (depth < 1) + throw new IllegalArgumentException(J3dI18N.getString("ImageComponentRetained2")); + + // If the format is 8bit per component, we may send it down + // to OpenGL directly if its by ref case + switch (format) { + case ImageComponent.FORMAT_RGB:// same as ImageComponent.FORMAT_RGB8 + case ImageComponent.FORMAT_RGB4: // Need to be Deprecated + case ImageComponent.FORMAT_RGB5: // Need to be Deprecated + case ImageComponent.FORMAT_R3_G3_B2: // Need to be Deprecated + numberOfComponents = 3; + break; + case ImageComponent.FORMAT_RGBA:// same as ImageComponent.FORMAT_RGBA8 + case ImageComponent.FORMAT_RGB5_A1: // Need to be Deprecated + case ImageComponent.FORMAT_RGBA4: // Need to be Deprecated + numberOfComponents = 4; + break; + case ImageComponent.FORMAT_LUM4_ALPHA4: // Need to be Deprecated + case ImageComponent.FORMAT_LUM8_ALPHA8: + numberOfComponents = 2; + break; + case ImageComponent.FORMAT_CHANNEL8: + numberOfComponents = 1; + break; + default: + throw new IllegalArgumentException(J3dI18N.getString("ImageComponentRetained3")); + } + + this.setFormat(format); + this.width = width; + this.height = height; + this.depth = depth; + refImage = new Object[depth]; + } + + int evaluateImageType(RenderedImage ri) { + int imageType = BufferedImage.TYPE_CUSTOM; + + if (ri instanceof BufferedImage) { + imageType = ((BufferedImage)ri).getType(); + + if(imageType != BufferedImage.TYPE_CUSTOM) { + return imageType; + } + } + + // System.err.println("This is a RenderedImage or BufferedImage with TYPE_CUSTOM. It imageType classification may not be correct."); + + ColorModel cm = ri.getColorModel(); + ColorSpace cs = cm.getColorSpace(); + SampleModel sm = ri.getSampleModel(); + + int csType = cs.getType(); + boolean isAlphaPre = cm.isAlphaPremultiplied(); + + + if (csType == ColorSpace.TYPE_GRAY && cm instanceof ComponentColorModel) { + if (sm.getDataType() == DataBuffer.TYPE_BYTE) { + imageType = BufferedImage.TYPE_BYTE_GRAY; + } else if (sm.getDataType() == DataBuffer.TYPE_USHORT) { + imageType = BufferedImage.TYPE_USHORT_GRAY; + } + } + + // RGB , only interested in BYTE ABGR and BGR for now + // all others will be copied to a buffered image + else if(csType == ColorSpace.TYPE_RGB) { + int comparedBit = 0; + int smDataType = sm.getDataType(); + if(smDataType == DataBuffer.TYPE_BYTE) { + comparedBit = 8; + } else if(smDataType == DataBuffer.TYPE_INT) { + comparedBit = 32; + } + + if(comparedBit != 0) { + int numBands = sm.getNumBands(); + if (cm instanceof ComponentColorModel && + sm instanceof PixelInterleavedSampleModel) { + PixelInterleavedSampleModel csm = + (PixelInterleavedSampleModel) sm; + int[] offs = csm.getBandOffsets(); + ComponentColorModel ccm = (ComponentColorModel)cm; + int[] nBits = ccm.getComponentSize(); + boolean isNBit = true; + for (int i=0; i < numBands; i++) { + if (nBits[i] != comparedBit) { + isNBit = false; + break; + } + } + + // Handle TYPE_BYTE + if( comparedBit == 8) { + if (isNBit && + offs[0] == numBands-1 && + offs[1] == numBands-2 && + offs[2] == numBands-3) { + if (numBands == 3) { + imageType = BufferedImage.TYPE_3BYTE_BGR; + } else if (offs[3] == 0) { + imageType = (isAlphaPre + ? BufferedImage.TYPE_4BYTE_ABGR_PRE + : BufferedImage.TYPE_4BYTE_ABGR); + } + } + } + //Handle TYPE_INT + else { + if (isNBit) { + if (numBands == 3) { + if(offs[0] == numBands-1 && + offs[1] == numBands-2 && + offs[2] == numBands-3) { + imageType = BufferedImage.TYPE_INT_BGR; + } else if(offs[0] == 0 && + offs[1] == 1 && + offs[2] == 2) { + imageType = BufferedImage.TYPE_INT_RGB; + } + } else if(offs[0] == 3 && + offs[1] == 0 && + offs[2] == 1 && + offs[3] == 2) { + imageType = (isAlphaPre + ? BufferedImage.TYPE_INT_ARGB_PRE + : BufferedImage.TYPE_INT_ARGB); + } + } + } + } + } + } + + return imageType; + } + + // Assume ri's imageType is BufferedImage.TYPE_CUSTOM + boolean is3ByteRGB(RenderedImage ri) { boolean value = false; int i; - int biType = getImageType(ri); - if (biType != BufferedImage.TYPE_CUSTOM) - return false; ColorModel cm = ri.getColorModel(); ColorSpace cs = cm.getColorSpace(); SampleModel sm = ri.getSampleModel(); @@ -1059,11 +471,11 @@ abstract class ImageComponentRetained extends NodeComponentRetained { int csType = cs.getType(); if ( csType == ColorSpace.TYPE_RGB) { int numBands = sm.getNumBands(); - if (sm.getDataType() == DataBuffer.TYPE_BYTE) { + if ((numBands == 3) && (sm.getDataType() == DataBuffer.TYPE_BYTE)) { if (cm instanceof ComponentColorModel && - sm instanceof PixelInterleavedSampleModel) { - PixelInterleavedSampleModel csm = - (PixelInterleavedSampleModel) sm; + sm instanceof PixelInterleavedSampleModel) { + PixelInterleavedSampleModel csm = + (PixelInterleavedSampleModel) sm; int[] offs = csm.getBandOffsets(); ComponentColorModel ccm = (ComponentColorModel)cm; int[] nBits = ccm.getComponentSize(); @@ -1075,55 +487,33 @@ abstract class ImageComponentRetained extends NodeComponentRetained { } } if (is8Bit && - offs[0] == 0 && - offs[1] == 1 && - offs[2] == 2) { - if (numBands == 3) { - if (format == ImageComponent.FORMAT_RGB) - value = true; - } - else if (offs[3] == 3 && !isAlphaPre) { - if (format == ImageComponent.FORMAT_RGBA) - value = true; - } + offs[0] == 0 && + offs[1] == 1 && + offs[2] == 2) { + value = true; } } } } return value; } - - final int getImageType(RenderedImage ri) { - int imageType = BufferedImage.TYPE_CUSTOM; + + // Assume ri's imageType is BufferedImage.TYPE_CUSTOM + boolean is4ByteRGBA(RenderedImage ri) { + boolean value = false; int i; - - if (ri instanceof BufferedImage) { - return ((BufferedImage)ri).getType(); - } ColorModel cm = ri.getColorModel(); ColorSpace cs = cm.getColorSpace(); SampleModel sm = ri.getSampleModel(); - int csType = cs.getType(); boolean isAlphaPre = cm.isAlphaPremultiplied(); - if ( csType != ColorSpace.TYPE_RGB) { - if (csType == ColorSpace.TYPE_GRAY && - cm instanceof ComponentColorModel) { - if (sm.getDataType() == DataBuffer.TYPE_BYTE) { - imageType = BufferedImage.TYPE_BYTE_GRAY; - } else if (sm.getDataType() == DataBuffer.TYPE_USHORT) { - imageType = BufferedImage.TYPE_USHORT_GRAY; - } - } - } - // RGB , only interested in BYTE ABGR and BGR for now - // all others will be copied to a buffered image - else { + int csType = cs.getType(); + if ( csType == ColorSpace.TYPE_RGB) { int numBands = sm.getNumBands(); - if (sm.getDataType() == DataBuffer.TYPE_BYTE) { + if ((numBands == 4) && (sm.getDataType() == DataBuffer.TYPE_BYTE)) { if (cm instanceof ComponentColorModel && - sm instanceof PixelInterleavedSampleModel) { - PixelInterleavedSampleModel csm = - (PixelInterleavedSampleModel) sm; + sm instanceof PixelInterleavedSampleModel) { + PixelInterleavedSampleModel csm = + (PixelInterleavedSampleModel) sm; int[] offs = csm.getBandOffsets(); ComponentColorModel ccm = (ComponentColorModel)cm; int[] nBits = ccm.getComponentSize(); @@ -1135,425 +525,2209 @@ abstract class ImageComponentRetained extends NodeComponentRetained { } } if (is8Bit && - offs[0] == numBands-1 && - offs[1] == numBands-2 && - offs[2] == numBands-3) { - if (numBands == 3) { - imageType = BufferedImage.TYPE_3BYTE_BGR; + offs[0] == 0 && + offs[1] == 1 && + offs[2] == 2 && + offs[3] == 3 && !isAlphaPre) { + value = true; + } + } + } + } + return value; + } + + // Note: This method for RenderedImage, can't be used by NioImageBuffer. + /* Check if sub-image type matches image type */ + boolean isSubImageTypeEqual(RenderedImage ri) { + int subImageType = evaluateImageType(ri); + + // This test is likely too loose, but the specification isn't clear either. + // Assuming TYPE_CUSTOM of sub-image == the TYPE_CUSTOM of existing image. + if(imageType == subImageType) { + return true; + } else { + return false; + } + + } + + // This method only support caller of offScreenBuffer and readRaster. + void createBlankImageData() { + + assert (imageData == null); + + switch(numberOfComponents) { + case 4: + imageType = BufferedImage.TYPE_INT_ARGB; + imageFormatType = ImageFormatType.TYPE_INT_ARGB; + unitsPerPixel = 1; + break; + + case 3: + imageType = BufferedImage.TYPE_INT_RGB; + imageFormatType = ImageFormatType.TYPE_INT_RGB; + unitsPerPixel = 1; + break; + default: + // Only valid for 3 and 4 channel case. ( Read back from framebuffer ) + assert false; + } + + imageTypeIsSupported = true; + imageData = createRenderedImageDataObject(null); + + } + + // This method will set imageType, imageFormatType, and unitsPerPixel + // as it evaluates NioImageBuffer is supported. It will also reset + // abgrSupported. + boolean isImageTypeSupported(NioImageBuffer nioImgBuf) { + + boolean isSupported = true; + NioImageBuffer.ImageType nioImageType = nioImgBuf.getImageType(); + + switch(numberOfComponents) { + case 4: + if(nioImageType == NioImageBuffer.ImageType.TYPE_4BYTE_ABGR) { + // TODO : This approach will lead to a very slow path + // for unsupported case. + if(abgrSupported) { + imageFormatType = ImageFormatType.TYPE_BYTE_ABGR; + } else { + // Unsupported format on HW, switch to slow copy. + imageFormatType = ImageFormatType.TYPE_BYTE_RGBA; + isSupported = false; + } + unitsPerPixel = 4; + } else if(nioImageType == NioImageBuffer.ImageType.TYPE_4BYTE_RGBA) { + imageFormatType = ImageFormatType.TYPE_BYTE_RGBA; + unitsPerPixel = 4; + } else if(nioImageType == NioImageBuffer.ImageType.TYPE_INT_ARGB) { + imageFormatType = ImageFormatType.TYPE_INT_ARGB; + unitsPerPixel = 1; + } else { + throw new RuntimeException("Not yet implemented"); + } + break; + + case 3: + if(nioImageType == NioImageBuffer.ImageType.TYPE_3BYTE_BGR) { + imageFormatType = ImageFormatType.TYPE_BYTE_BGR; + unitsPerPixel = 3; + } else if(nioImageType == NioImageBuffer.ImageType.TYPE_3BYTE_RGB) { + imageFormatType = ImageFormatType.TYPE_BYTE_RGB; + unitsPerPixel = 3; + } else if(nioImageType == NioImageBuffer.ImageType.TYPE_INT_BGR) { + imageFormatType = ImageFormatType.TYPE_INT_BGR; + unitsPerPixel = 1; + } else if(nioImageType == NioImageBuffer.ImageType.TYPE_INT_RGB) { + imageFormatType = ImageFormatType.TYPE_INT_RGB; + unitsPerPixel = 1; + } else { + throw new RuntimeException("Not yet implemented"); + } + break; + + case 2: + throw new RuntimeException("Not yet implemented"); + case 1: + if(nioImageType == NioImageBuffer.ImageType.TYPE_BYTE_GRAY) { + imageFormatType = ImageFormatType.TYPE_BYTE_GRAY; + unitsPerPixel = 1; + } else { + throw new RuntimeException("Not yet implemented"); + } + break; + + default: + throw new AssertionError(); + } + + return isSupported; + } + + // This method will set imageType, imageFormatType, and unitsPerPixel + // as it evaluates RenderedImage is supported. It will also reset + // abgrSupported. + boolean isImageTypeSupported(RenderedImage ri) { + + boolean isSupported = true; + imageType = evaluateImageType(ri); + + switch(numberOfComponents) { + case 4: + if(imageType == BufferedImage.TYPE_4BYTE_ABGR) { + + // TODO : This approach will lead to a very slow path + // for unsupported case. + if(abgrSupported) { + imageFormatType = ImageFormatType.TYPE_BYTE_ABGR; + } else { + // Unsupported format on HW, switch to slow copy. + imageFormatType = ImageFormatType.TYPE_BYTE_RGBA; + isSupported = false; + } + unitsPerPixel = 4; + } else if(imageType == BufferedImage.TYPE_INT_ARGB) { + imageFormatType = ImageFormatType.TYPE_INT_ARGB; + unitsPerPixel = 1; + } else if(is4ByteRGBA(ri)) { + imageFormatType = ImageFormatType.TYPE_BYTE_RGBA; + unitsPerPixel = 4; + } else { + // System.err.println("Image format is unsupported --- Case 4"); + // Convert unsupported format to TYPE_BYTE_RGBA. + imageFormatType = ImageFormatType.TYPE_BYTE_RGBA; + isSupported = false; + unitsPerPixel = 4; + } + break; + + case 3: + if(imageType == BufferedImage.TYPE_3BYTE_BGR) { + imageFormatType = ImageFormatType.TYPE_BYTE_BGR; + unitsPerPixel = 3; + } else if(imageType == BufferedImage.TYPE_INT_BGR) { + imageFormatType = ImageFormatType.TYPE_INT_BGR; + unitsPerPixel = 1; + } else if(imageType == BufferedImage.TYPE_INT_RGB) { + imageFormatType = ImageFormatType.TYPE_INT_RGB; + unitsPerPixel = 1; + } else if(is3ByteRGB(ri)) { + imageFormatType = ImageFormatType.TYPE_BYTE_RGB; + unitsPerPixel = 3; + } else { + // System.err.println("Image format is unsupported --- Case 3"); + // Convert unsupported format to TYPE_BYTE_RGB. + imageFormatType = ImageFormatType.TYPE_BYTE_RGB; + isSupported = false; + unitsPerPixel = 3; + } + break; + + case 2: + // System.err.println("Image format is unsupported --- Case 2"); + // Convert unsupported format to TYPE_BYTE_LA. + imageFormatType = ImageFormatType.TYPE_BYTE_LA; + isSupported = false; + unitsPerPixel = 2; + break; + + case 1: + if(imageType == BufferedImage.TYPE_BYTE_GRAY) { + imageFormatType = ImageFormatType.TYPE_BYTE_GRAY; + unitsPerPixel = 1; + } else { + // System.err.println("Image format is unsupported --- Case 1"); + // Convert unsupported format to TYPE_BYTE_GRAY. + imageFormatType = ImageFormatType.TYPE_BYTE_GRAY; + isSupported = false; + unitsPerPixel = 1; + } + break; + + default: + throw new AssertionError(); + } + + return isSupported; + } + + /* + * This method assume that the following members have been initialized : + * width, height, depth, imageFormatType, and unitsPerPixel. + */ + ImageData createNioImageBufferDataObject(NioImageBuffer nioImageBuffer) { + + switch(imageFormatType) { + case TYPE_BYTE_GRAY: + case TYPE_BYTE_LA: + case TYPE_BYTE_RGB: + case TYPE_BYTE_BGR: + case TYPE_BYTE_RGBA: + case TYPE_BYTE_ABGR: + if(nioImageBuffer != null) { + return new ImageData(ImageDataType.TYPE_BYTE_BUFFER, + width * height * depth * unitsPerPixel, + width, height, nioImageBuffer); + } else { + // This is needed only if abgr is unsupported. + return new ImageData(ImageDataType.TYPE_BYTE_BUFFER, + width * height * depth * unitsPerPixel, + width, height); + } + case TYPE_INT_RGB: + case TYPE_INT_BGR: + case TYPE_INT_ARGB: + return new ImageData(ImageDataType.TYPE_INT_BUFFER, + width * height * depth * unitsPerPixel, + width, height, nioImageBuffer); + default: + throw new AssertionError(); + } + } + + /* + * This method assume that the following members have been initialized : + * depth, imageType, imageFormatType, and unitsPerPixel. + */ + ImageData createRenderedImageDataObject(RenderedImage byRefImage, int dataWidth, int dataHeight) { + switch(imageFormatType) { + case TYPE_BYTE_GRAY: + case TYPE_BYTE_LA: + case TYPE_BYTE_RGB: + case TYPE_BYTE_BGR: + case TYPE_BYTE_RGBA: + case TYPE_BYTE_ABGR: + if(byRefImage != null) { + return new ImageData(ImageDataType.TYPE_BYTE_ARRAY, + dataWidth * dataHeight * depth * unitsPerPixel, + dataWidth, dataHeight, byRefImage); + } else { + return new ImageData(ImageDataType.TYPE_BYTE_ARRAY, + dataWidth * dataHeight * depth * unitsPerPixel, + dataWidth, dataHeight); + } + case TYPE_INT_RGB: + case TYPE_INT_BGR: + case TYPE_INT_ARGB: + if(byRefImage != null) { + return new ImageData(ImageDataType.TYPE_INT_ARRAY, + dataWidth * dataHeight * depth * unitsPerPixel, + dataWidth, dataHeight, byRefImage); + } else { + return new ImageData(ImageDataType.TYPE_INT_ARRAY, + dataWidth * dataHeight * depth * unitsPerPixel, + dataWidth, dataHeight); + } + default: + throw new AssertionError(); + } + } + + private void updateImageDataPowerOfTwo(int depthIndex) { + assert enforceNonPowerOfTwoSupport; + BufferedImage bufImage = imageData.createBufferedImage(depthIndex); + BufferedImage scaledImg = powerOfTwoATOp.filter(bufImage, null); + copySupportedImageToImageData(scaledImg, 0, imageDataPowerOfTwo); + } + + /* + * This method assume that the following members have been initialized : + * width, height, depth, imageType, imageFormatType, and bytesPerPixel. + */ + ImageData createRenderedImageDataObject(RenderedImage byRefImage) { + + return createRenderedImageDataObject(byRefImage, width, height); + + } + + + /** + * Copy specified region of image data from RenderedImage to + * ImageComponent's imageData object + */ + void copySupportedImageToImageData(RenderedImage ri, int srcX, int srcY, + int dstX, int dstY, int depthIndex, int copyWidth, int copyHeight, ImageData data) { + + assert (data != null); + + ColorModel cm = ri.getColorModel(); + + int xoff = ri.getTileGridXOffset(); // tile origin x offset + int yoff = ri.getTileGridYOffset(); // tile origin y offset + int minTileX = ri.getMinTileX(); // min tile x index + int minTileY = ri.getMinTileY(); // min tile y index + tilew = ri.getTileWidth(); // tile width in pixels + tileh = ri.getTileHeight(); // tile height in pixels + + // determine the first tile of the image + float mt; + + mt = (float)(srcX - xoff) / (float)tilew; + if (mt < 0) { + minTileX = (int)(mt - 1); + } else { + minTileX = (int)mt; + } + + mt = (float)(srcY - yoff) / (float)tileh; + if (mt < 0) { + minTileY = (int)(mt - 1); + } else { + minTileY = (int)mt; + } + + // determine the pixel offset of the upper-left corner of the + // first tile + int startXTile = minTileX * tilew + xoff; + int startYTile = minTileY * tileh + yoff; + + // image dimension in the first tile + int curw = (startXTile + tilew - srcX); + int curh = (startYTile + tileh - srcY); + + // check if the to-be-copied region is less than the tile image + // if so, update the to-be-copied dimension of this tile + if (curw > copyWidth) { + curw = copyWidth; + } + + if (curh > copyHeight) { + curh = copyHeight; + } + + // save the to-be-copied width of the left most tile + int startw = curw; + + // temporary variable for dimension of the to-be-copied region + int tmpw = copyWidth; + int tmph = copyHeight; + + // offset of the first pixel of the tile to be copied; offset is + // relative to the upper left corner of the title + int x = srcX - startXTile; + int y = srcY - startYTile; + + // determine the number of tiles in each direction that the + // image spans + numXTiles = (copyWidth + x) / tilew; + numYTiles = (copyHeight + y) / tileh; + + if (((float)(copyWidth + x ) % (float)tilew) > 0) { + numXTiles += 1; + } + + if (((float)(copyHeight + y ) % (float)tileh) > 0) { + numYTiles += 1; + } + + int offset; + int w, h, i, j, m, n; + int dstBegin; + Object pixel = null; + java.awt.image.Raster ras; + int lineUnits; // nbytes per line in dst image buffer + int sign; // -1 for going down + int dstLineUnits; // sign * lineUnits + int tileStart; // destination buffer offset + // at the next left most tile + + byte[] dstByteBuffer = null; + int[] dstIntBuffer = null; + + switch(data.getType()) { + case TYPE_BYTE_ARRAY: + dstByteBuffer = data.getAsByteArray(); + break; + case TYPE_INT_ARRAY: + dstIntBuffer = data.getAsIntArray(); + break; + default: + assert false; + } + + int dataWidth = data.dataWidth; + int dataHeight = data.dataHeight; + + lineUnits = dataWidth * unitsPerPixel; + if (yUp) { + // destination buffer offset + tileStart = (depthIndex * dataWidth * dataHeight + dstY * dataWidth + dstX) * unitsPerPixel; + sign = 1; + dstLineUnits = lineUnits; + } else { + // destination buffer offset + tileStart = (depthIndex * dataWidth * dataHeight + (dataHeight - dstY - 1) * dataWidth + dstX) * unitsPerPixel; + sign = -1; + dstLineUnits = -lineUnits; + } + +/* + System.err.println("tileStart= " + tileStart + " dstLineUnits= " + dstLineUnits); + System.err.println("startw= " + startw); + */ + + // allocate memory for a pixel + ras = ri.getTile(minTileX,minTileY); + pixel = getDataElementBuffer(ras); + + int srcOffset, dstOffset; + int tileLineUnits = tilew * unitsPerPixel; + int copyUnits; + + for (n = minTileY; n < minTileY+numYTiles; n++) { + + dstBegin = tileStart; // destination buffer offset + tmpw = copyWidth; // reset the width to be copied + curw = startw; // reset the width to be copied of + // the left most tile + x = srcX - startXTile; // reset the starting x offset of + // the left most tile + + for (m = minTileX; m < minTileX+numXTiles; m++) { + + // retrieve the raster for the next tile + ras = ri.getTile(m,n); + + srcOffset = (y * tilew + x) * unitsPerPixel; + dstOffset = dstBegin; + + copyUnits = curw * unitsPerPixel; + + //System.err.println("curh = "+curh+" curw = "+curw); + //System.err.println("x = "+x+" y = "+y); + + switch(data.getType()) { + case TYPE_BYTE_ARRAY: + byte[] srcByteBuffer = ((DataBufferByte)ras.getDataBuffer()).getData(); + for (h = 0; h < curh; h++) { + System.arraycopy(srcByteBuffer, srcOffset, dstByteBuffer, dstOffset, + copyUnits); + srcOffset += tileLineUnits; + dstOffset += dstLineUnits; } - else if (offs[3] == 0) { - imageType = (isAlphaPre - ? BufferedImage.TYPE_4BYTE_ABGR_PRE - : BufferedImage.TYPE_4BYTE_ABGR); + break; + case TYPE_INT_ARRAY: + int[] srcIntBuffer = ((DataBufferInt)ras.getDataBuffer()).getData(); + for (h = 0; h < curh; h++) { + System.arraycopy(srcIntBuffer, srcOffset, dstIntBuffer, dstOffset, + copyUnits); + srcOffset += tileLineUnits; + dstOffset += dstLineUnits; } + break; + default: + assert false; + } + + // advance the destination buffer offset + dstBegin += curw * unitsPerPixel; + + // move to the next tile in x direction + x = 0; + + // determine the width of copy region of the next tile + + tmpw -= curw; + if (tmpw < tilew) { + curw = tmpw; + } else { + curw = tilew; + } + } + + // we are done copying an array of tiles in the x direction + // advance the tileStart offset + tileStart += dataWidth * unitsPerPixel * curh * sign; + + // move to the next set of tiles in y direction + y = 0; + + // determine the height of copy region for the next set + // of tiles + tmph -= curh; + if (tmph < tileh) { + curh = tmph; + } else { + curh = tileh; + } + } + + if((imageData == data) && (imageDataPowerOfTwo != null)) { + updateImageDataPowerOfTwo(depthIndex); + } + } + + // Quick line by line copy + void copyImageLineByLine(BufferedImage bi, int srcX, int srcY, + int dstX, int dstY, int depthIndex, int copyWidth, int copyHeight, ImageData data) { + + assert (data != null); + + int h; + int rowBegin, // src begin row index + srcBegin, // src begin offset + dstBegin; // dst begin offset + + int dataWidth = data.dataWidth; + int dataHeight = data.dataHeight; + int dstUnitsPerRow = dataWidth * unitsPerPixel; // bytes per row in dst image + rowBegin = srcY; + + if (yUp) { + dstBegin = (depthIndex * dataWidth * dataHeight + dstY * dataWidth + dstX) * unitsPerPixel; + } else { + dstBegin = (depthIndex * dataWidth * dataHeight + (dataHeight - dstY - 1) * dataWidth + dstX) * unitsPerPixel; + dstUnitsPerRow = - 1 * dstUnitsPerRow; + } + + int copyUnits = copyWidth * unitsPerPixel; + int srcWidth = bi.getWidth(); + int srcUnitsPerRow = srcWidth * unitsPerPixel; + srcBegin = (rowBegin * srcWidth + srcX) * unitsPerPixel; + + switch(data.getType()) { + case TYPE_BYTE_ARRAY: + byte[] srcByteBuffer = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + byte[] dstByteBuffer = data.getAsByteArray(); + for (h = 0; h < copyHeight; h++) { + System.arraycopy(srcByteBuffer, srcBegin, dstByteBuffer, dstBegin, copyUnits); + dstBegin += dstUnitsPerRow; + srcBegin += srcUnitsPerRow; + } + break; + + case TYPE_INT_ARRAY: + int[] srcIntBuffer = ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + int[] dstIntBuffer = data.getAsIntArray(); + for (h = 0; h < copyHeight; h++) { + System.arraycopy(srcIntBuffer, srcBegin, dstIntBuffer, dstBegin, copyUnits); + dstBegin += dstUnitsPerRow; + srcBegin += srcUnitsPerRow; + } + break; + default: + assert false; + } + + if((imageData == data) && (imageDataPowerOfTwo != null)) { + updateImageDataPowerOfTwo(depthIndex); + } + } + + // Quick block copy for yUp image + void copyImageByBlock(BufferedImage bi, int depthIndex, ImageData data) { + + assert ((data != null) && yUp); + + int dataWidth = data.dataWidth; + int dataHeight = data.dataHeight; + + int dstBegin; // dst begin offset + dstBegin = depthIndex * dataWidth * dataHeight * unitsPerPixel; + + switch(imageData.getType()) { + case TYPE_BYTE_ARRAY: + byte[] srcByteBuffer = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + byte[] dstByteBuffer = data.getAsByteArray(); + System.arraycopy(srcByteBuffer, 0, dstByteBuffer, dstBegin, (dataWidth * dataHeight * unitsPerPixel)); + break; + case TYPE_INT_ARRAY: + int[] srcIntBuffer = ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + int[] dstIntBuffer = data.getAsIntArray(); + System.arraycopy(srcIntBuffer, 0, dstIntBuffer, dstBegin, (dataWidth * dataHeight * unitsPerPixel)); + break; + default: + assert false; + } + + if((imageData == data) && (imageDataPowerOfTwo != null)) { + updateImageDataPowerOfTwo(depthIndex); + } + + } + + /** + * copy complete region of a RenderedImage to ImageComponent's imageData object. + */ + void copySupportedImageToImageData(RenderedImage ri, int depthIndex, ImageData data) { + + if (ri instanceof BufferedImage) { + if(yUp) { + /* Use quick block copy when ( format is OK, Yup is true, and byRef is false). */ + // System.err.println("ImageComponentRetained.copySupportedImageToImageData() : (imageTypeSupported && !byReference && yUp) --- (2 BI)"); + copyImageByBlock((BufferedImage)ri, depthIndex, data); + } else { + /* Use quick inverse line by line copy when (format is OK and Yup is false). */ + // System.err.println("ImageComponentRetained.copySupportedImageToImageData() : (imageTypeSupported && !yUp) --- (3 BI)"); + copyImageLineByLine((BufferedImage)ri, 0, 0, 0, 0, depthIndex, data.dataWidth, data.dataHeight, data); + } + } else { + // System.err.println("ImageComponentRetained.copySupportedImageToImageData() : (imageTypeSupported && !byReference ) --- (2 RI)"); + copySupportedImageToImageData(ri, ri.getMinX(), ri.getMinY(), 0, 0, depthIndex, data.dataWidth, data.dataHeight, data); + + /* + * An alternative approach. + * + // Create a buffered image from renderImage + ColorModel cm = ri.getColorModel(); + WritableRaster wRaster = ri.copyData(null); + BufferedImage bi = new BufferedImage(cm, + wRaster, + cm.isAlphaPremultiplied() + ,null); + + copySupportedImageToImageData((BufferedImage)ri, 0, 0, 0, 0, depthIndex, data.dataWidth, data.dataHeight, data); + + * + * + */ + } + } + + /* + * copy the complete unsupported NioImageBuffer into a supported BYTE_BUFFER format + */ + void copyUnsupportedNioImageToImageData(NioImageBuffer nioImage, int srcX, int srcY, + int dstX, int dstY, int copyWidth, int copyHeight, ImageData iData) { + + assert (iData.getType() == ImageDataType.TYPE_BYTE_BUFFER); + assert (getImageFormatType() == ImageFormatType.TYPE_BYTE_RGBA); + + int length = copyWidth * copyHeight; + ByteBuffer srcBuffer = (ByteBuffer) nioImage.getDataBuffer(); + srcBuffer.rewind(); + ByteBuffer dstBuffer = iData.getAsByteBuffer(); + dstBuffer.rewind(); + + // Do copy and swap. + for(int i = 0; i < length; i +=4) { + dstBuffer.put(i, srcBuffer.get(i+3)); + dstBuffer.put(i+1, srcBuffer.get(i+2)); + dstBuffer.put(i+2, srcBuffer.get(i+1)); + dstBuffer.put(i+3, srcBuffer.get(i)); + } + } + + /* + * copy the complete unsupported image into a supported BYTE_ARRAY format + */ + void copyUnsupportedImageToImageData(RenderedImage ri, int depthIndex, ImageData data) { + + assert (data.getType() == ImageDataType.TYPE_BYTE_ARRAY); + + if (ri instanceof BufferedImage) { + copyUnsupportedImageToImageData((BufferedImage)ri, 0, 0, 0, 0, + depthIndex, data.dataWidth, data.dataHeight, data); + } else { + copyUnsupportedImageToImageData(ri, ri.getMinX(), ri.getMinY(), + 0, 0, depthIndex, data.dataWidth, data.dataHeight, data); + } + } + + void copyUnsupportedImageToImageData(BufferedImage bi, int srcX, int srcY, + int dstX, int dstY, int depthIndex, int copyWidth, int copyHeight, ImageData data) { + + int w, h, i, j; + int rowBegin, // src begin row index + srcBegin, // src begin offset + dstBegin, // dst begin offset + rowInc, // row increment + // -1 --- ydown + // 1 --- yup + row; + + rowBegin = srcY; + rowInc = 1; + + assert (data != null); + + int dataWidth = data.dataWidth; + int dataHeight = data.dataHeight; + int dstBytesPerRow = dataWidth * unitsPerPixel; // bytes per row in dst image + + if (yUp) { + dstBegin = (depthIndex * dataWidth * dataHeight + dstY * dataWidth + dstX) * unitsPerPixel; + } else { + dstBegin = (depthIndex * dataWidth * dataHeight + (dataHeight - dstY - 1) * dataWidth + dstX) * unitsPerPixel; + dstBytesPerRow = - 1 * dstBytesPerRow; + } + + WritableRaster ras = bi.getRaster(); + ColorModel cm = bi.getColorModel(); + Object pixel = getDataElementBuffer(ras); + + byte[] dstBuffer = data.getAsByteArray(); + + switch(numberOfComponents) { + case 4: { + for (row = rowBegin, h = 0; + h < copyHeight; h++, row += rowInc) { + j = dstBegin; + for (w = srcX; w < (copyWidth + srcX); w++) { + ras.getDataElements(w, row, pixel); + dstBuffer[j++] = (byte)cm.getRed(pixel); + dstBuffer[j++] = (byte)cm.getGreen(pixel); + dstBuffer[j++] = (byte)cm.getBlue(pixel); + dstBuffer[j++] = (byte)cm.getAlpha(pixel); + } + dstBegin += dstBytesPerRow; + } + } + break; + + case 3: { + for (row = rowBegin, h = 0; + h < copyHeight; h++, row += rowInc) { + j = dstBegin; + for (w = srcX; w < (copyWidth + srcX); w++) { + ras.getDataElements(w, row, pixel); + dstBuffer[j++] = (byte)cm.getRed(pixel); + dstBuffer[j++] = (byte)cm.getGreen(pixel); + dstBuffer[j++] = (byte)cm.getBlue(pixel); + } + dstBegin += dstBytesPerRow; + } + } + break; + + case 2: { + for (row = rowBegin, h = 0; + h < copyHeight; h++, row += rowInc) { + j = dstBegin; + for (w = srcX; w < (copyWidth + srcX); w++) { + ras.getDataElements(w, row, pixel); + dstBuffer[j++] = (byte)cm.getRed(pixel); + dstBuffer[j++] = (byte)cm.getAlpha(pixel); } + dstBegin += dstBytesPerRow; } } + break; + + case 1: { + for (row = rowBegin, h = 0; + h < copyHeight; h++, row += rowInc) { + j = dstBegin; + for (w = srcX; w < (copyWidth + srcX); w++) { + ras.getDataElements(w, row, pixel); + dstBuffer[j++] = (byte)cm.getRed(pixel); + } + dstBegin += dstBytesPerRow; + } + } + break; + default: + assert false; + } + + if((imageData == data) && (imageDataPowerOfTwo != null)) { + updateImageDataPowerOfTwo(depthIndex); } - return imageType; } + + void copyUnsupportedImageToImageData(RenderedImage ri, int srcX, int srcY, + int dstX, int dstY, int depthIndex, int copyWidth, int copyHeight, ImageData data) { + + int w, h, i, j, m, n; + int dstBegin; + Object pixel = null; + java.awt.image.Raster ras; + // dst image buffer + int sign; // -1 for going down + int dstLineBytes; // sign * lineBytes + int tileStart; // destination buffer offset + // at the next left most tile + + int offset; + + ColorModel cm = ri.getColorModel(); + + int xoff = ri.getTileGridXOffset(); // tile origin x offset + int yoff = ri.getTileGridYOffset(); // tile origin y offset + int minTileX = ri.getMinTileX(); // min tile x index + int minTileY = ri.getMinTileY(); // min tile y index + tilew = ri.getTileWidth(); // tile width in pixels + tileh = ri.getTileHeight(); // tile height in pixels + + // determine the first tile of the image + + float mt; + + mt = (float)(srcX - xoff) / (float)tilew; + if (mt < 0) { + minTileX = (int)(mt - 1); + } else { + minTileX = (int)mt; + } + + mt = (float)(srcY - yoff) / (float)tileh; + if (mt < 0) { + minTileY = (int)(mt - 1); + } else { + minTileY = (int)mt; + } + + // determine the pixel offset of the upper-left corner of the + // first tile + int startXTile = minTileX * tilew + xoff; + int startYTile = minTileY * tileh + yoff; + + + // image dimension in the first tile + int curw = (startXTile + tilew - srcX); + int curh = (startYTile + tileh - srcY); + + // check if the to-be-copied region is less than the tile image + // if so, update the to-be-copied dimension of this tile + if (curw > copyWidth) { + curw = copyWidth; + } + + if (curh > copyHeight) { + curh = copyHeight; + } + + // save the to-be-copied width of the left most tile + int startw = curw; + + + // temporary variable for dimension of the to-be-copied region + int tmpw = copyWidth; + int tmph = copyHeight; + + + // offset of the first pixel of the tile to be copied; offset is + // relative to the upper left corner of the title + int x = srcX - startXTile; + int y = srcY - startYTile; + + + // determine the number of tiles in each direction that the + // image spans + + numXTiles = (copyWidth + x) / tilew; + numYTiles = (copyHeight + y) / tileh; + + if (((float)(copyWidth + x ) % (float)tilew) > 0) { + numXTiles += 1; + } + + if (((float)(copyHeight + y ) % (float)tileh) > 0) { + numYTiles += 1; + } + + assert (data != null); + int dataWidth = data.dataWidth; + int dataHeight = data.dataHeight; + int lineBytes = dataWidth * unitsPerPixel; // nbytes per line in + + if (yUp) { + // destination buffer offset + tileStart = (depthIndex * dataWidth * dataHeight + dstY * dataWidth + dstX) * unitsPerPixel; + sign = 1; + dstLineBytes = lineBytes; + } else { + // destination buffer offset + tileStart = (depthIndex * dataWidth * dataHeight + (dataHeight - dstY - 1) * dataWidth + dstX) * unitsPerPixel; + sign = -1; + dstLineBytes = -lineBytes; + } + +/* + System.err.println("tileStart= " + tileStart + " dstLineBytes= " + dstLineBytes); + System.err.println("startw= " + startw); + */ + + // allocate memory for a pixel + ras = ri.getTile(minTileX,minTileY); + pixel = getDataElementBuffer(ras); + byte[] dstBuffer = imageData.getAsByteArray(); + + switch(numberOfComponents) { + case 4: { + // System.err.println("Case 1: byReference = "+byReference); + for (n = minTileY; n < minTileY+numYTiles; n++) { + + dstBegin = tileStart; // destination buffer offset + tmpw = copyWidth; // reset the width to be copied + curw = startw; // reset the width to be copied of + // the left most tile + x = srcX - startXTile; // reset the starting x offset of + // the left most tile + + for (m = minTileX; m < minTileX+numXTiles; m++) { + + // retrieve the raster for the next tile + ras = ri.getTile(m,n); + + j = dstBegin; + offset = 0; + + //System.err.println("curh = "+curh+" curw = "+curw); + //System.err.println("x = "+x+" y = "+y); + + for (h = y; h < (y + curh); h++) { + // System.err.println("j = "+j); + for (w = x; w < (x + curw); w++) { + ras.getDataElements(w, h, pixel); + dstBuffer[j++] = (byte)cm.getRed(pixel); + dstBuffer[j++] = (byte)cm.getGreen(pixel); + dstBuffer[j++] = (byte)cm.getBlue(pixel); + dstBuffer[j++] = (byte)cm.getAlpha(pixel); + } + offset += dstLineBytes; + j = dstBegin + offset; + } + + // advance the destination buffer offset + dstBegin += curw * unitsPerPixel; + + // move to the next tile in x direction + x = 0; + + // determine the width of copy region of the next tile + + tmpw -= curw; + if (tmpw < tilew) { + curw = tmpw; + } else { + curw = tilew; + } + } + + // we are done copying an array of tiles in the x direction + // advance the tileStart offset + + tileStart += dataWidth * unitsPerPixel * curh * sign; + + // move to the next set of tiles in y direction + y = 0; + + // determine the height of copy region for the next set + // of tiles + tmph -= curh; + if (tmph < tileh) { + curh = tmph; + } else { + curh = tileh; + } + } + } + break; + case 3: { + for (n = minTileY; n < minTileY+numYTiles; n++) { + + dstBegin = tileStart; // destination buffer offset + tmpw = copyWidth; // reset the width to be copied + curw = startw; // reset the width to be copied of + // the left most tile + x = srcX - startXTile; // reset the starting x offset of + // the left most tile + + for (m = minTileX; m < minTileX+numXTiles; m++) { + + // retrieve the raster for the next tile + ras = ri.getTile(m,n); + + j = dstBegin; + offset = 0; + + //System.err.println("curh = "+curh+" curw = "+curw); + //System.err.println("x = "+x+" y = "+y); + + for (h = y; h < (y + curh); h++) { + // System.err.println("j = "+j); + for (w = x; w < (x + curw); w++) { + ras.getDataElements(w, h, pixel); + dstBuffer[j++] = (byte)cm.getRed(pixel); + dstBuffer[j++] = (byte)cm.getGreen(pixel); + dstBuffer[j++] = (byte)cm.getBlue(pixel); + } + offset += dstLineBytes; + j = dstBegin + offset; + } + + // advance the destination buffer offset + dstBegin += curw * unitsPerPixel; + + // move to the next tile in x direction + x = 0; + + // determine the width of copy region of the next tile + + tmpw -= curw; + if (tmpw < tilew) { + curw = tmpw; + } else { + curw = tilew; + } + } + + // we are done copying an array of tiles in the x direction + // advance the tileStart offset + + tileStart += dataWidth * unitsPerPixel * curh * sign; + + // move to the next set of tiles in y direction + y = 0; + + // determine the height of copy region for the next set + // of tiles + tmph -= curh; + if (tmph < tileh) { + curh = tmph; + } else { + curh = tileh; + } + } + } + break; + case 2: { + for (n = minTileY; n < minTileY+numYTiles; n++) { + + dstBegin = tileStart; // destination buffer offset + tmpw = copyWidth; // reset the width to be copied + curw = startw; // reset the width to be copied of + // the left most tile + x = srcX - startXTile; // reset the starting x offset of + // the left most tile + + for (m = minTileX; m < minTileX+numXTiles; m++) { + + // retrieve the raster for the next tile + ras = ri.getTile(m,n); + + j = dstBegin; + offset = 0; + + //System.err.println("curh = "+curh+" curw = "+curw); + //System.err.println("x = "+x+" y = "+y); + + for (h = y; h < (y + curh); h++) { + // System.err.println("j = "+j); + for (w = x; w < (x + curw); w++) { + ras.getDataElements(w, h, pixel); + dstBuffer[j++] = (byte)cm.getRed(pixel); + dstBuffer[j++] = (byte)cm.getAlpha(pixel); + } + offset += dstLineBytes; + j = dstBegin + offset; + } + + // advance the destination buffer offset + dstBegin += curw * unitsPerPixel; + + // move to the next tile in x direction + x = 0; + + // determine the width of copy region of the next tile + + tmpw -= curw; + if (tmpw < tilew) { + curw = tmpw; + } else { + curw = tilew; + } + } + + + // we are done copying an array of tiles in the x direction + // advance the tileStart offset + + tileStart += dataWidth * unitsPerPixel * curh * sign; + + + // move to the next set of tiles in y direction + y = 0; + + // determine the height of copy region for the next set + // of tiles + tmph -= curh; + if (tmph < tileh) { + curh = tmph; + } else { + curh = tileh; + } + } + } + break; + case 1: { + for (n = minTileY; n < minTileY+numYTiles; n++) { + + dstBegin = tileStart; // destination buffer offset + tmpw = copyWidth; // reset the width to be copied + curw = startw; // reset the width to be copied of + // the left most tile + x = srcX - startXTile; // reset the starting x offset of + // the left most tile + + for (m = minTileX; m < minTileX+numXTiles; m++) { + + // retrieve the raster for the next tile + ras = ri.getTile(m,n); + + j = dstBegin; + offset = 0; + + //System.err.println("curh = "+curh+" curw = "+curw); + //System.err.println("x = "+x+" y = "+y); + + for (h = y; h < (y + curh); h++) { + // System.err.println("j = "+j); + for (w = x; w < (x + curw); w++) { + ras.getDataElements(w, h, pixel); + dstBuffer[j++] = (byte)cm.getRed(pixel); + } + offset += dstLineBytes; + j = dstBegin + offset; + } + + // advance the destination buffer offset + dstBegin += curw * unitsPerPixel; + + // move to the next tile in x direction + x = 0; + + // determine the width of copy region of the next tile + + tmpw -= curw; + if (tmpw < tilew) { + curw = tmpw; + } else { + curw = tilew; + } + } + + // we are done copying an array of tiles in the x direction + // advance the tileStart offset + tileStart += dataWidth * unitsPerPixel * curh * sign; + + // move to the next set of tiles in y direction + y = 0; + + // determine the height of copy region for the next set + // of tiles + tmph -= curh; + if (tmph < tileh) { + curh = tmph; + } else { + curh = tileh; + } + } + } + break; + + default: + assert false; + } + + if((imageData == data) && (imageDataPowerOfTwo != null)) { + updateImageDataPowerOfTwo(depthIndex); + } + } + + // Lock out user thread from modifying variables by using synchronized routines + void evaluateExtensions(Canvas3D canvas) { + // For performance reason the ordering of the following 2 statements is intentional. + // So that we only need to do format conversion for imageData only + evaluateExtABGR(canvas.extensionsSupported); + evaluateExtNonPowerOfTwo(canvas.textureExtendedFeatures); + + } + + + void evaluateExtABGR(int ext) { + + + // If abgrSupported is false, a copy has been created so + // we don't have to check again. + if(!abgrSupported) { + return; + } + + if(getImageFormatType() != ImageFormatType.TYPE_BYTE_ABGR) { + return; + } + + if((ext & Canvas3D.EXT_ABGR) != 0) { + return; + } + + // ABGR is unsupported, set flag to false. + abgrSupported = false; + convertImageDataFromABGRToRGBA(); + + } + + private int getClosestPowerOf2(int value) { + + if (value < 1) + return value; + + int powerValue = 1; + for (;;) { + powerValue *= 2; + if (value < powerValue) { + // Found max bound of power, determine which is closest + int minBound = powerValue/2; + if ((powerValue - value) > + (value - minBound)) + return minBound; + else + return powerValue; + } + } + } + + void evaluateExtNonPowerOfTwo(int ext) { + + // If npotSupported is false, a copy power of two image has been created + // so we don't have to check again. + if(!npotSupported) { + return; + } + if (imageData == null && !isByReference()) { + return; + } + if((ext & Canvas3D.TEXTURE_NON_POWER_OF_TWO) != 0) { + return; + } + + // NPOT is unsupported, set flag to false. + npotSupported = false; + + // scale to power of 2 for texture mapping + //xmax and ymax are in BackgroundRetained. + /* xmax = width; + ymax = height; */ + int npotWidth = getClosestPowerOf2(width); + int npotHeight = getClosestPowerOf2(height); + float xScale = (float)npotWidth/(float)width; + float yScale = (float)npotHeight/(float)height; + + // scale if scales aren't 1.0 + if (!(xScale == 1.0f && yScale == 1.0f)) { + RenderedImage ri = null; + + if (imageData == null) { + // This is a byRef, support format and is a RenderedImage case. + // See ImageComponent2DRetained.set(RenderedImage image) + ri = (RenderedImage) getRefImage(0); + if(!(ri instanceof BufferedImage)) { + // Create a buffered image from renderImage + ColorModel cm = ri.getColorModel(); + WritableRaster wRaster = ri.copyData(null); + ri = new BufferedImage(cm, + wRaster, + cm.isAlphaPremultiplied() + ,null); + + // Create image data object with buffer for image. */ + imageData = createRenderedImageDataObject(null); + copySupportedImageToImageData(ri, 0, imageData); + } + } + + assert imageData != null; + ri = imageData.createBufferedImage(0); + + AffineTransform at = AffineTransform.getScaleInstance(xScale, + yScale); + powerOfTwoATOp = new AffineTransformOp(at, + AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + BufferedImage scaledImg = powerOfTwoATOp.filter((BufferedImage)ri, null); + + imageDataPowerOfTwo = createRenderedImageDataObject(null, npotWidth, npotHeight); + // Since ri is created from imageData, it's imageType is supported. + copySupportedImageToImageData(scaledImg, 0, imageDataPowerOfTwo); + + } else { + imageDataPowerOfTwo = null; + } + } + + void convertImageDataFromABGRToRGBA() { + + // Unsupported format on HW, switch to slow copy. + imageFormatType = ImageFormatType.TYPE_BYTE_RGBA; + imageTypeIsSupported = false; + + // Only need to convert imageData + imageData.convertFromABGRToRGBA(); + + } - /** - * Retrieves the bufferedImage at the specified depth level - */ - final void retrieveBufferedImage(int depth) { - - // create BufferedImage if one doesn't exist - if (bImage[depth] == null) { - if (format == ImageComponent.FORMAT_RGBA || - format == ImageComponent.FORMAT_RGBA4 || - format == ImageComponent.FORMAT_RGB5_A1 || - format == ImageComponent.FORMAT_LUM4_ALPHA4 || - format == ImageComponent.FORMAT_LUM8_ALPHA8) { - bImage[depth] = new BufferedImage(width, height, - BufferedImage.TYPE_INT_ARGB); - } - else - bImage[depth] = new BufferedImage(width, height, - BufferedImage.TYPE_INT_RGB); + * Copy supported ImageType from ImageData to the user defined bufferedImage + */ + void copyToRefImage(int depth) { + int h; + int rowBegin, // src begin row index + srcBegin, // src begin offset + dstBegin; // dst begin offset + + // refImage has to be a BufferedImage for off screen and read raster + assert refImage[depth] != null; + assert (refImage[depth] instanceof BufferedImage); + + BufferedImage bi = (BufferedImage)refImage[depth]; + int dstUnitsPerRow = width * unitsPerPixel; // bytes per row in dst image + rowBegin = 0; + + if (yUp) { + dstBegin = (depth * width * height) * unitsPerPixel; + } else { + dstBegin = (depth * width * height + (height - 1) * width ) * unitsPerPixel; + dstUnitsPerRow = - 1 * dstUnitsPerRow; } - - if (usedByTexture || !usedByRaster) { - copyToBufferedImage(imageYup, depth, true); - } else { - copyToBufferedImage(imageYdown[0], depth, false); - } - imageDirty[depth] = false; - + + int scanline = width * unitsPerPixel; + srcBegin = (rowBegin * width ) * unitsPerPixel; + + switch(imageData.getType()) { + case TYPE_BYTE_ARRAY: + byte[] dstByteBuffer = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + byte[] srcByteBuffer = imageData.getAsByteArray(); + for (h = 0; h < height; h++) { + System.arraycopy(srcByteBuffer, srcBegin, dstByteBuffer, dstBegin, scanline); + dstBegin += dstUnitsPerRow; + srcBegin += scanline; + } + break; + + case TYPE_INT_ARRAY: + int[] dstIntBuffer = ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + int[] srcIntBuffer = imageData.getAsIntArray(); + for (h = 0; h < height; h++) { + System.arraycopy(srcIntBuffer, srcBegin, dstIntBuffer, dstBegin, scanline); + dstBegin += dstUnitsPerRow; + srcBegin += scanline; + } + break; + default: + assert false; + } + } - + /** * Copy Image from RGBA to the user defined bufferedImage */ - final void copyBufferedImageWithFormatConversion(boolean usedByTexture, int depth) { + void copyToRefImageWithFormatConversion(int depth) { int w, h, i, j; int dstBegin, dstInc, dstIndex, dstIndexInc; - // Note that if a copy has been made, then its always a bufferedImage - // and not a renderedImage - BufferedImage bi = (BufferedImage)bImage[depth]; - int biType = bi.getType(); - byte[] buf; - - // convert from Ydown to Yup for texture - if (!yUp) { - if (usedByTexture == true) { - dstInc = -1 * width; - dstBegin = (height - 1) * width; - dstIndex = height -1; - dstIndexInc = -1; - buf = imageYup; - } else { - dstInc = width; - dstBegin = 0; - dstIndex = 0; - dstIndexInc = 1; - buf = imageYdown[0]; - } - } - else { - if (usedByTexture == true) { - dstInc = width; - dstBegin = 0; - dstIndex = 0; - dstIndexInc = 1; - buf = imageYup; - } - else { - dstInc = -1 * width; - dstBegin = (height - 1) * width; - dstIndex = height -1; - dstIndexInc = -1; - buf = imageYdown[0]; - } - } - - switch (biType) { - case BufferedImage.TYPE_INT_ARGB: - int[] intData = - ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); - // Multiply by 4 to get the byte incr and start point - j = 0; - for(h = 0; h < height; h++, dstBegin += dstInc) { - i = dstBegin; - for (w = 0; w < width; w++, j+=4, i++) { - intData[i] = (((buf[j+3] &0xff) << 24) | // a - ((buf[j] &0xff) << 16) | // r - ((buf[j+1] &0xff) << 8) | // g - (buf[j+2] & 0xff)); // b - - - } - } - break; - - case BufferedImage.TYPE_INT_RGB: - intData = - ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); - // Multiply by 4 to get the byte incr and start point - j = 0; - for(h = 0; h < height; h++, dstBegin += dstInc) { - i = dstBegin; - for (w = 0; w < width; w++, j+=4, i++) { - intData[i] = (0xff000000 | // a - ((buf[j] &0xff) << 16) | // r - ((buf[j+1] &0xff) << 8) | // g - (buf[j+2] & 0xff)); // b - - - } - } - break; - - case BufferedImage.TYPE_4BYTE_ABGR: - byte[] byteData = - ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); - // Multiply by 4 to get the byte incr and start point - j = 0; - for(h = 0; h < height; h++, dstBegin += (dstInc << 2)) { - i = dstBegin; - for (w = 0; w < width; w++, j+=4) { - - byteData[i++] = buf[j+3]; // a - byteData[i++] = buf[j+2]; // b - byteData[i++] = buf[j+1];// g - byteData[i++] = buf[j]; // r - } - } - break; - case BufferedImage.TYPE_INT_BGR: - intData = - ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); - // Multiply by 4 to get the byte incr and start point - j = 0; - - for(h = 0; h < height; h++, dstBegin += dstInc) { - i = dstBegin; - for (w = 0; w < width; w++, j+=4, i++) { - intData[i] = (0xff000000 | // a - ((buf[j] &0xff) ) | // r - ((buf[j+1] &0xff) << 8) | // g - (buf[j+2] & 0xff)<< 16); // b - - - } - } - break; - case BufferedImage.TYPE_BYTE_GRAY: - byteData = - ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); - j = 0; - for( h = 0; h < height; h++, dstBegin += dstInc) { - System.arraycopy(byteData, dstBegin, buf, j, width); - j += width; - } - break; - case BufferedImage.TYPE_USHORT_GRAY: - int pixel; - j = 0; - short[] shortData = - ((DataBufferShort)bi.getRaster().getDataBuffer()).getData(); - // Multiply by 4 to get the byte incr and start point - for(h = 0; h < height; h++, dstBegin+= dstInc) { - i = dstBegin; - for (w = 0; w < width; w++, i++, j++) { - shortData[i] = (short)buf[j]; - } - } - break; - - default: - j = 0; - for( h = 0; h < height; h++, dstIndex += dstIndexInc) { - i = dstIndex; - for (w = 0; w < width; w++, j+=4) { - pixel = (((buf[j+3] &0xff) << 24) | // a - ((buf[j] &0xff) << 16) | // r - ((buf[j+1] &0xff) << 8) | // g - (buf[j+2] & 0xff)); // b - bi.setRGB(w, i, pixel); - - } - } - break; - } - + // refImage has to be a BufferedImage for off screen and read raster + assert refImage[depth] != null; + assert (refImage[depth] instanceof BufferedImage); + + BufferedImage bi = (BufferedImage)refImage[depth]; + int biType = bi.getType(); + byte[] buf = imageData.getAsByteArray(); + + // convert from Ydown to Yup for texture + if (!yUp) { + dstInc = -1 * width; + dstBegin = (height - 1) * width; + dstIndex = height -1; + dstIndexInc = -1; + } else { + dstInc = width; + dstBegin = 0; + dstIndex = 0; + dstIndexInc = 1; + } + + switch (biType) { + case BufferedImage.TYPE_INT_ARGB: + int[] intData = + ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + // Multiply by 4 to get the byte incr and start point + j = 0; + for(h = 0; h < height; h++, dstBegin += dstInc) { + i = dstBegin; + for (w = 0; w < width; w++, j+=4, i++) { + intData[i] = (((buf[j+3] &0xff) << 24) | // a + ((buf[j] &0xff) << 16) | // r + ((buf[j+1] &0xff) << 8) | // g + (buf[j+2] & 0xff)); // b + + + } + } + break; + + case BufferedImage.TYPE_INT_RGB: + intData = + ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + // Multiply by 4 to get the byte incr and start point + j = 0; + for(h = 0; h < height; h++, dstBegin += dstInc) { + i = dstBegin; + for (w = 0; w < width; w++, j+=4, i++) { + intData[i] = (0xff000000 | // a + ((buf[j] &0xff) << 16) | // r + ((buf[j+1] &0xff) << 8) | // g + (buf[j+2] & 0xff)); // b + + + } + } + break; + + case BufferedImage.TYPE_4BYTE_ABGR: + byte[] byteData = + ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + // Multiply by 4 to get the byte incr and start point + j = 0; + for(h = 0; h < height; h++, dstBegin += (dstInc << 2)) { + i = dstBegin; + for (w = 0; w < width; w++, j+=4) { + + byteData[i++] = buf[j+3]; // a + byteData[i++] = buf[j+2]; // b + byteData[i++] = buf[j+1];// g + byteData[i++] = buf[j]; // r + } + } + break; + case BufferedImage.TYPE_INT_BGR: + intData = + ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + // Multiply by 4 to get the byte incr and start point + j = 0; + + for(h = 0; h < height; h++, dstBegin += dstInc) { + i = dstBegin; + for (w = 0; w < width; w++, j+=4, i++) { + intData[i] = (0xff000000 | // a + ((buf[j] &0xff) ) | // r + ((buf[j+1] &0xff) << 8) | // g + (buf[j+2] & 0xff)<< 16); // b + + + } + } + break; + case BufferedImage.TYPE_BYTE_GRAY: + byteData = + ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + j = 0; + for( h = 0; h < height; h++, dstBegin += dstInc) { + System.arraycopy(byteData, dstBegin, buf, j, width); + j += width; + } + break; + case BufferedImage.TYPE_USHORT_GRAY: + int pixel; + j = 0; + short[] shortData = + ((DataBufferShort)bi.getRaster().getDataBuffer()).getData(); + // Multiply by 4 to get the byte incr and start point + for(h = 0; h < height; h++, dstBegin+= dstInc) { + i = dstBegin; + for (w = 0; w < width; w++, i++, j++) { + shortData[i] = (short)buf[j]; + } + } + break; + + default: + j = 0; + for( h = 0; h < height; h++, dstIndex += dstIndexInc) { + i = dstIndex; + for (w = 0; w < width; w++, j+=4) { + pixel = (((buf[j+3] &0xff) << 24) | // a + ((buf[j] &0xff) << 16) | // r + ((buf[j+1] &0xff) << 8) | // g + (buf[j+2] & 0xff)); // b + bi.setRGB(w, i, pixel); + + } + } + break; + } + } - /** - * Copy image data from ImageComponent's internal representation - * to Buffered Image - */ - final void copyToBufferedImage(byte[] buf, int depth, - boolean usedByTexture) { - - int w, h, i, j; - int dstBegin, dstInc, srcBegin; - - - // convert from Ydown to Yup for texture - if (!yUp) { - if (usedByTexture == true) { - srcBegin = depth * width * height * bytesPerYupPixelStored; - dstInc = -1 * width; - dstBegin = (height - 1) * width; - } else { - srcBegin = 0; - dstInc = width; - dstBegin = 0; - } - } - else { - if (usedByTexture == true) { - srcBegin = 0; - dstInc = width; - dstBegin = 0; - } - else { - srcBegin = depth * width * height * bytesPerYdownPixelStored; - dstInc = -1 * width; - dstBegin = (height - 1) * width; - } - } - - // Note that if a copy has been made, then its always a bufferedImage - // and not a renderedImage - int[] intData = ((DataBufferInt) - ((BufferedImage)bImage[depth]).getRaster().getDataBuffer()).getData(); - - switch(format) { - case ImageComponent.FORMAT_RGBA8: - case ImageComponent.FORMAT_RGB5_A1: - case ImageComponent.FORMAT_RGBA4: - - for (j = srcBegin, h = 0; h < height; h++, dstBegin += dstInc) { - i = dstBegin; - for (w = 0; w < width; w++, j+=4, i++) { - intData[i] = ((buf[j+3] & 0xff) << 24) | - ((buf[j] & 0xff) << 16) | - ((buf[j+1] & 0xff) << 8) | - (buf[j+2] & 0xff); + void scaleImage(int xScale, int yScale, int depthIndex, ImageComponentRetained origImage) { + + byte[] dstByteBuffer = null; + byte[] srcByteBuffer = null; + int[] dstIntBuffer = null; + int[] srcIntBuffer = null; + int dStart, sStart; + + switch(imageData.getType()) { + case TYPE_BYTE_ARRAY: + dstByteBuffer = imageData.getAsByteArray(); + srcByteBuffer = origImage.imageData.getAsByteArray(); + dStart = depthIndex * width * height * unitsPerPixel; + sStart = depthIndex * origImage.width * origImage.height * unitsPerPixel; + scaleImage(xScale, yScale, dStart, sStart, origImage, dstByteBuffer, srcByteBuffer); + break; + case TYPE_INT_ARRAY: + dstIntBuffer = imageData.getAsIntArray(); + srcIntBuffer = origImage.imageData.getAsIntArray(); + dStart = depthIndex * width * height * unitsPerPixel; + sStart = depthIndex * origImage.width * origImage.height * unitsPerPixel; + scaleImage(xScale, yScale, dStart, sStart, origImage, dstIntBuffer, srcIntBuffer); + break; + default: + assert false; + } + + } + + void scaleImage(int xScale, int yScale, int dStart, int sStart, ImageComponentRetained origImage, + byte[] dData, byte[] sData) { + + int dOffset = 0; + int sOffset = 0; + int sLineIncr = unitsPerPixel * origImage.width; + int sPixelIncr = unitsPerPixel << 1; + + assert ((xScale != 1) || (yScale != 1)); + + if (yScale == 1) { + for (int x = 0; x < width; x++) { + for (int k = 0; k < unitsPerPixel; k++) { + dData[dStart + dOffset + k] = (byte) + (((int)(sData[sStart + sOffset + k] & 0xff) + + (int)(sData[sStart + sOffset + k + + unitsPerPixel] & 0xff) + 1) >> 1); } + dOffset += unitsPerPixel; + sOffset += sPixelIncr; } - break; - - - case ImageComponent.FORMAT_RGB8: - case ImageComponent.FORMAT_RGB5: - case ImageComponent.FORMAT_RGB4: - case ImageComponent.FORMAT_R3_G3_B2: - for (j = srcBegin, h = 0; h < height; h++, dstBegin += dstInc) { - i = dstBegin; - for (w = 0; w < width; w++, j+=4, i++) { - intData[i] = ((buf[j] & 0xff) << 16) | - ((buf[j+1] & 0xff) << 8) | - (buf[j+2] & 0xff); - } - } - break; - - case ImageComponent.FORMAT_LUM8_ALPHA8: - case ImageComponent.FORMAT_LUM4_ALPHA4: - for (j = srcBegin, h = 0; h < height; h++, dstBegin += dstInc) { - i = dstBegin; - for (w = 0; w < width; w++, j+=2, i++) { - intData[i] = ((buf[j+1] & 0xff) << 24) | - ((buf[j] & 0xff) << 16); + } else if (xScale == 1) { + for (int y = 0; y < height; y++) { + for (int k = 0; k < unitsPerPixel; k++) { + dData[dStart + dOffset + k] = (byte) + (((int)(sData[sStart + sOffset + k] & 0xff) + + (int)(sData[sStart + sOffset + k + + sLineIncr] & 0xff) + 1) >> 1); } - } - break; - - case ImageComponent.FORMAT_CHANNEL8: - for (j = srcBegin, h = 0; h < height; h++, dstBegin += dstInc) { - i = dstBegin; - for (w = 0; w < width; w++, j++, i++) { - intData[i] = ((buf[j] & 0xff) << 16); + dOffset += unitsPerPixel; + sOffset += sLineIncr; + } + } else { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + for (int k = 0; k < unitsPerPixel; k++) { + dData[dStart + dOffset + k] = (byte) + (((int)(sData[sStart + sOffset + k] & 0xff) + + (int)(sData[sStart + sOffset + k + + unitsPerPixel] & 0xff) + + (int)(sData[sStart + sOffset + k + + sLineIncr] & 0xff) + + (int)(sData[sStart + sOffset + k + sLineIncr + + + unitsPerPixel] & 0xff) + 2) >> 2); + } + dOffset += unitsPerPixel; + sOffset += sPixelIncr; } - } - break; - } + sOffset += sLineIncr; + } + } } - - Object getData(DataBuffer buffer) { - Object data = null; - switch (buffer.getDataType()) { - case DataBuffer.TYPE_BYTE: - data = ((DataBufferByte)buffer).getData(); - break; - case DataBuffer.TYPE_INT: - data = ((DataBufferInt)buffer).getData(); - break; - case DataBuffer.TYPE_SHORT: - data = ((DataBufferShort)buffer).getData(); - break; - } - return data; + + void scaleImage(int xScale, int yScale, int dStart, int sStart, ImageComponentRetained origImage, + int[] dData, int[] sData) { + + int dOffset = 0; + int sOffset = 0; + int sLineIncr = origImage.width; + int sPixelIncr = 2; + + assert ((xScale != 1) || (yScale != 1)); + + int sTemp1, sTemp2; + int[] comp = new int[4]; + if (yScale == 1) { + for (int x = 0; x < width; x++) { + sTemp1 = sData[sStart + sOffset]; + sTemp2 = sData[sStart + sOffset + 1]; + // Unpack and compute + for (int k = 0; k < numberOfComponents; k++) { + comp[k] = ((sTemp1 & 0xff) + (sTemp2 & 0xff) + 1) >> 1; + sTemp1 = sTemp1 >> 8; + sTemp2 = sTemp2 >> 8; + } + // Pack back computed value. + sTemp1 = comp[numberOfComponents - 1]; + if(numberOfComponents > 1) { + for (int k = numberOfComponents - 2; k >= 0; k--) { + sTemp1 = (sTemp1 << 8) + comp[k]; + } + } + dData[dStart + dOffset] = sTemp1; + + dOffset += 1; + sOffset += sPixelIncr; + } + } else if (xScale == 1) { + for (int y = 0; y < height; y++) { + sTemp1 = sData[sStart + sOffset]; + sTemp2 = sData[sStart + sOffset + sLineIncr]; + // Unpack and compute + for (int k = 0; k < numberOfComponents; k++) { + comp[k] = ((sTemp1 & 0xff) + (sTemp2 & 0xff) + 1) >> 1; + sTemp1 = sTemp1 >> 8; + sTemp2 = sTemp2 >> 8; + } + // Pack back computed value. + sTemp1 = comp[numberOfComponents - 1]; + if(numberOfComponents > 1) { + for (int k = numberOfComponents - 2; k >= 0; k--) { + sTemp1 = (sTemp1 << 8) + comp[k]; + } + } + dData[dStart + dOffset] = sTemp1; + + dOffset += 1; + sOffset += sLineIncr; + } + } else { + int sTemp3, sTemp4; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + sTemp1 = sData[sStart + sOffset]; + sTemp2 = sData[sStart + sOffset + 1]; + sTemp3 = sData[sStart + sOffset + sLineIncr]; + sTemp4 = sData[sStart + sOffset + sLineIncr + 1]; + // Unpack and compute + for (int k = 0; k < numberOfComponents; k++) { + comp[k] = ((sTemp1 & 0xff) + (sTemp2 & 0xff) + + (sTemp3 & 0xff) + (sTemp4 & 0xff) + 2) >> 2; + sTemp1 = sTemp1 >> 8; + sTemp2 = sTemp2 >> 8; + sTemp3 = sTemp3 >> 8; + sTemp4 = sTemp4 >> 8; + } + // Pack back computed value. + sTemp1 = comp[numberOfComponents - 1]; + if(numberOfComponents > 1) { + for (int k = numberOfComponents - 2; k >= 0; k--) { + sTemp1 = (sTemp1 << 8) + comp[k]; + } + } + dData[dStart + dOffset] = sTemp1; + + dOffset += 1; + sOffset += sPixelIncr; + } + sOffset += sLineIncr; + } + } } - - final void setByReference(boolean byReference) { - this.byReference = byReference; - } - - final boolean isByReference() { - return byReference; - } - - final void setYUp( boolean yUp) { - this.yUp = yUp; - } - - final boolean isYUp() { - return yUp; - } - - // Add a user to the userList - synchronized void addUser(NodeComponentRetained node) { + + + // Add a user to the userList + synchronized void addUser(NodeComponentRetained node) { userList.add(node); - } - - // Add a user to the userList - synchronized void removeUser(NodeComponentRetained node) { - int i = userList.indexOf(node); - if (i >= 0) { - userList.remove(i); - } - } - - /** - * ImageComponent object doesn't really have mirror object. - * But it's using the updateMirrorObject interface to propagate - * the changes to the users - */ - synchronized void updateMirrorObject(int component, Object value) { - - //System.out.println("ImageComponent.updateMirrorObject"); - - Object user; - - if (((component & IMAGE_CHANGED) != 0) || - ((component & SUBIMAGE_CHANGED) != 0)) { - synchronized(userList) { + } + + // Add a user to the userList + synchronized void removeUser(NodeComponentRetained node) { + int i = userList.indexOf(node); + if (i >= 0) { + userList.remove(i); + } + } + + /* + * + * @exception IllegalSharingException if this image is + * being used by a Canvas3D as an off-screen buffer. + */ + void setLive(boolean inBackgroundGroup, int refCount) { + // Do illegalSharing check. + if(getUsedByOffScreen()) { + throw new IllegalSharingException(J3dI18N.getString("ImageComponent3")); + } + super.setLive(inBackgroundGroup, refCount); + } + + /** + * ImageComponent object doesn't really have mirror object. + * But it's using the updateMirrorObject interface to propagate + * the changes to the users + */ + synchronized void updateMirrorObject(int component, Object value) { + + //System.err.println("ImageComponent.updateMirrorObject"); + + Object user; + + if (((component & IMAGE_CHANGED) != 0) || + ((component & SUBIMAGE_CHANGED) != 0)) { + synchronized(userList) { for (int i = userList.size()-1; i >=0; i--) { - user = userList.get(i); - if (user != null) { - if (user instanceof TextureRetained) { - ((TextureRetained)user).notifyImageComponentImageChanged(this, (ImageComponentUpdateInfo)value); - } else if (user instanceof RasterRetained) { - ((RasterRetained)user).notifyImageComponentImageChanged(this, (ImageComponentUpdateInfo)value); - } else if (user instanceof BackgroundRetained) { - ((BackgroundRetained)user).notifyImageComponentImageChanged(this, (ImageComponentUpdateInfo)value); - } - } - } - } - - // return the subimage update info to the free list - if (value != null) { - VirtualUniverse.mc.addFreeImageUpdateInfo( - (ImageComponentUpdateInfo)value); - } - } - } - - final void sendMessage(int attrMask, Object attr) { - - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + user = userList.get(i); + if (user != null) { + if (user instanceof TextureRetained) { + ((TextureRetained)user).notifyImageComponentImageChanged(this, (ImageComponentUpdateInfo)value); + } else if (user instanceof RasterRetained) { + ((RasterRetained)user).notifyImageComponentImageChanged(this, (ImageComponentUpdateInfo)value); + } else if (user instanceof BackgroundRetained) { + ((BackgroundRetained)user).notifyImageComponentImageChanged(this, (ImageComponentUpdateInfo)value); + } + } + } + } + } + } + + final void sendMessage(int attrMask, Object attr) { + + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES | - J3dThread.UPDATE_RENDER; + J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.IMAGE_COMPONENT_CHANGED; createMessage.universe = null; createMessage.args[0] = this; createMessage.args[1]= new Integer(attrMask); createMessage.args[2] = attr; - createMessage.args[3] = new Integer(changedFrequent); + createMessage.args[3] = new Integer(changedFrequent); VirtualUniverse.mc.processMessage(createMessage); - } - + } + void handleFrequencyChange(int bit) { - if (bit == ImageComponent.ALLOW_IMAGE_WRITE) { - setFrequencyChangeMask(ImageComponent.ALLOW_IMAGE_WRITE, 0x1); - } + if (bit == ImageComponent.ALLOW_IMAGE_WRITE) { + setFrequencyChangeMask(ImageComponent.ALLOW_IMAGE_WRITE, 0x1); + } } - + static Object getDataElementBuffer(java.awt.image.Raster ras) { - int nc = ras.getNumDataElements(); - + int nc = ras.getNumDataElements(); + switch (ras.getTransferType()) { - case DataBuffer.TYPE_INT: - return new int[nc]; - case DataBuffer.TYPE_BYTE: - return new byte[nc]; - case DataBuffer.TYPE_USHORT: - case DataBuffer.TYPE_SHORT: - return new short[nc]; - case DataBuffer.TYPE_FLOAT: - return new float[nc]; - case DataBuffer.TYPE_DOUBLE: - return new double[nc]; - } - // Should not happen - return null; - } -} + case DataBuffer.TYPE_INT: + return new int[nc]; + case DataBuffer.TYPE_BYTE: + return new byte[nc]; + case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_SHORT: + return new short[nc]; + case DataBuffer.TYPE_FLOAT: + return new float[nc]; + case DataBuffer.TYPE_DOUBLE: + return new double[nc]; + } + // Should not happen + return null; + } + + /** + * Wrapper class for image data. + * Currently supports byte array and int array. + * Will eventually support NIO ByteBuffer and IntBuffer. + */ + class ImageData { + + private Object data = null; + private ImageDataType imageDataType = ImageDataType.TYPE_NULL; + private int length = 0; + private boolean dataIsByRef = false; + private int dataWidth, dataHeight; + + /** + * Constructs a new ImageData buffer of the specified type with the + * specified length. + */ + ImageData(ImageDataType imageDataType, int length, int dataWidth, int dataHeight) { + this.imageDataType = imageDataType; + this.length = length; + this.dataWidth = dataWidth; + this.dataHeight = dataHeight; + this.dataIsByRef = false; + + switch (imageDataType) { + case TYPE_BYTE_ARRAY: + data = new byte[length]; + break; + case TYPE_INT_ARRAY: + data = new int[length]; + break; + case TYPE_BYTE_BUFFER: + ByteOrder order = ByteOrder.nativeOrder(); + data = ByteBuffer.allocateDirect(length).order(order); + break; + case TYPE_INT_BUFFER: + default: + throw new AssertionError(); + } + } + + /** + * Constructs a new ImageData buffer of the specified type with the + * specified length and the specified byRefImage as data. + */ + ImageData(ImageDataType imageDataType, int length, int dataWidth, int dataHeight, + Object byRefImage) { + BufferedImage bi; + NioImageBuffer nio; + + this.imageDataType = imageDataType; + this.length = length; + this.dataWidth = dataWidth; + this.dataHeight = dataHeight; + this.dataIsByRef = true; + + switch (imageDataType) { + case TYPE_BYTE_ARRAY: + bi = (BufferedImage) byRefImage; + data = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + break; + case TYPE_INT_ARRAY: + bi = (BufferedImage) byRefImage; + data = ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + break; + case TYPE_BYTE_BUFFER: + case TYPE_INT_BUFFER: + nio = (NioImageBuffer) byRefImage; + data = nio.getDataBuffer(); + break; + default: + throw new AssertionError(); + } + } + + /** + * Constructs a new ImageData buffer from the specified + * object. This object stores a reference to the input image data. + */ + ImageData(Object data, boolean isByRef) { + this.data = data; + dataIsByRef = isByRef; + dataWidth = ((ImageData) data).dataWidth; + dataHeight = ((ImageData) data).dataHeight; + + if (data == null) { + imageDataType = ImageDataType.TYPE_NULL; + length = 0; + } else if (data instanceof byte[]) { + imageDataType = ImageDataType.TYPE_BYTE_ARRAY; + length = ((byte[]) data).length; + } else if (data instanceof int[]) { + imageDataType = ImageDataType.TYPE_INT_ARRAY; + length = ((int[]) data).length; + } else if (data instanceof ByteBuffer) { + imageDataType = ImageDataType.TYPE_BYTE_BUFFER; + length = ((ByteBuffer) data).limit(); + } else if (data instanceof IntBuffer) { + imageDataType = ImageDataType.TYPE_INT_BUFFER; + length = ((IntBuffer) data).limit(); + } else { + assert false; + } + } + + /** + * Returns the type of this DataBuffer. + */ + ImageDataType getType() { + return imageDataType; + } + + /** + * Returns the number of elements in this DataBuffer. + */ + int length() { + return length; + } + + /** + * Returns the width of this DataBuffer. + */ + int getWidth() { + return dataWidth; + } + + /** + * Returns the height of this DataBuffer. + */ + int getHeight() { + return dataHeight; + } + + /** + * Returns this DataBuffer as an Object. + */ + Object get() { + return data; + } + + /** + * Returns is this data is byRef. No internal data is made. + */ + boolean isDataByRef() { + return dataIsByRef; + } + + + /** + * Returns this DataBuffer as a byte array. + */ + byte[] getAsByteArray() { + return (byte[]) data; + } + + /** + * Returns this DataBuffer as an int array. + */ + int[] getAsIntArray() { + return (int[]) data; + } + + /** + * Returns this DataBuffer as an nio ByteBuffer. + */ + ByteBuffer getAsByteBuffer() { + return (ByteBuffer) data; + } + + /** + * Returns this DataBuffer as an nio IntBuffer. + */ + IntBuffer getAsIntBuffer() { + return (IntBuffer) data; + } + + // Handle TYPE_BYTE_LA only + void copyByLineAndExpand(BufferedImage bi, int depthIndex) { + int h; + int srcBegin, // src begin offset + dstBegin; // dst begin offset + + assert (imageData.getType() == ImageDataType.TYPE_BYTE_ARRAY); + assert (imageFormatType == ImageFormatType.TYPE_BYTE_LA); + + int unitsPerRow = width * unitsPerPixel; // bytes per row + int scanline = unitsPerRow; + if (yUp) { + srcBegin = (depthIndex * width * height) * unitsPerPixel; + } else { + srcBegin = (depthIndex * width * height + (height - 1) * width) * unitsPerPixel; + unitsPerRow = - 1 * unitsPerRow; + } + + dstBegin = 0; + // ABGR is 4 bytes per pixel + int dstUnitsPerRow = width * 4; + + byte[] dstByteBuffer = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + byte[] srcByteBuffer = imageData.getAsByteArray(); + for (h = 0; h < height; h++) { + for( int v = 0, w = 0; w < scanline; w += unitsPerPixel, v += 4) { + dstByteBuffer[dstBegin+v] = srcByteBuffer[srcBegin+w+1]; // Alpha + dstByteBuffer[dstBegin+v+1] = 0; + dstByteBuffer[dstBegin+v+2] = 0; + dstByteBuffer[dstBegin+v+3] = srcByteBuffer[srcBegin+w]; // Red + } + + dstBegin += dstUnitsPerRow; + srcBegin += unitsPerRow; + } + + } + + // Quick line by line copy + void copyByLine(BufferedImage bi, int depthIndex, boolean swapNeeded) { + + int h; + int srcBegin, // src begin offset + dstBegin; // dst begin offset + + int unitsPerRow = width * unitsPerPixel; // bytes per row + int copyUnits = unitsPerRow; + if (yUp) { + srcBegin = (depthIndex * width * height) * unitsPerPixel; + } else { + srcBegin = (depthIndex * width * height + (height - 1) * width) * unitsPerPixel; + unitsPerRow = - 1 * unitsPerRow; + } + + dstBegin = 0; + + switch(imageData.getType()) { + case TYPE_BYTE_ARRAY: + byte[] dstByteBuffer = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + byte[] srcByteBuffer = imageData.getAsByteArray(); + for (h = 0; h < height; h++) { + if(!swapNeeded) { + System.arraycopy(srcByteBuffer, srcBegin, + dstByteBuffer, dstBegin, copyUnits); + } else { + if(imageFormatType == ImageFormatType.TYPE_BYTE_RGB) { + assert (unitsPerPixel == 3); + for(int w = 0; w < copyUnits; w += unitsPerPixel) { + dstByteBuffer[dstBegin+w] = srcByteBuffer[srcBegin+w+2]; + dstByteBuffer[dstBegin+w+1] = srcByteBuffer[srcBegin+w+1]; + dstByteBuffer[dstBegin+w+2] = srcByteBuffer[srcBegin+w]; + } + } else if(imageFormatType == ImageFormatType.TYPE_BYTE_RGBA) { + assert (unitsPerPixel == 4); + for(int w = 0; w < copyUnits; w += unitsPerPixel) { + dstByteBuffer[dstBegin+w] = srcByteBuffer[srcBegin+w+3]; + dstByteBuffer[dstBegin+w+1] = srcByteBuffer[srcBegin+w+2]; + dstByteBuffer[dstBegin+w+2] = srcByteBuffer[srcBegin+w+1]; + dstByteBuffer[dstBegin+w+3] = srcByteBuffer[srcBegin+w]; + } + } else { + assert false; + } + } + dstBegin += copyUnits; + srcBegin += unitsPerRow; + } + break; + + // INT case doesn't required to handle swapNeeded + case TYPE_INT_ARRAY: + assert (!swapNeeded); + int[] dstIntBuffer = ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + int[] srcIntBuffer = imageData.getAsIntArray(); + for (h = 0; h < height; h++) { + System.arraycopy(srcIntBuffer, srcBegin, dstIntBuffer, dstBegin, copyUnits); + dstBegin += copyUnits; + srcBegin += unitsPerRow; + } + break; + default: + assert false; + } + } + + void copyByBlock(BufferedImage bi, int depthIndex) { + // src begin offset + int srcBegin = depthIndex * width * height * unitsPerPixel; + + switch(imageData.getType()) { + case TYPE_BYTE_ARRAY: + byte[] dstByteBuffer = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); + byte[] srcByteBuffer = imageData.getAsByteArray(); + System.arraycopy(srcByteBuffer, srcBegin, dstByteBuffer, 0, (height * width * unitsPerPixel)); + break; + case TYPE_INT_ARRAY: + int[] dstIntBuffer = ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + int[] srcIntBuffer = imageData.getAsIntArray(); + System.arraycopy(srcIntBuffer, srcBegin, dstIntBuffer, 0, (height * width * unitsPerPixel)); + break; + default: + assert false; + } + } + + // Need to check for imageData is null. if it is null return null. + BufferedImage createBufferedImage(int depthIndex) { + if(data != null) { + int bufferType = BufferedImage.TYPE_CUSTOM; + boolean swapNeeded = false; + + switch(imageFormatType) { + case TYPE_BYTE_BGR: + bufferType = BufferedImage.TYPE_3BYTE_BGR; + break; + case TYPE_BYTE_RGB: + bufferType = BufferedImage.TYPE_3BYTE_BGR; + swapNeeded = true; + break; + case TYPE_BYTE_ABGR: + bufferType = BufferedImage.TYPE_4BYTE_ABGR; + break; + case TYPE_BYTE_RGBA: + bufferType = BufferedImage.TYPE_4BYTE_ABGR; + swapNeeded = true; + break; + // This is a special case. Need to handle separately. + case TYPE_BYTE_LA: + bufferType = BufferedImage.TYPE_4BYTE_ABGR; + break; + case TYPE_BYTE_GRAY: + bufferType = BufferedImage.TYPE_BYTE_GRAY; + break; + case TYPE_INT_BGR: + bufferType = BufferedImage.TYPE_INT_BGR; + break; + case TYPE_INT_RGB: + bufferType = BufferedImage.TYPE_INT_RGB; + break; + case TYPE_INT_ARGB: + bufferType = BufferedImage.TYPE_INT_ARGB; + break; + // Unsupported case, so shouldn't be here. + case TYPE_USHORT_GRAY: + bufferType = BufferedImage.TYPE_USHORT_GRAY; + default: + assert false; + + } + + BufferedImage bi = new BufferedImage(width, height, bufferType); + if((!swapNeeded) && (imageFormatType != ImageFormatType.TYPE_BYTE_LA)) { + if(yUp) { + copyByBlock(bi, depthIndex); + } else { + copyByLine(bi, depthIndex, false); + } + } else if(swapNeeded) { + copyByLine(bi, depthIndex, swapNeeded); + } else if(imageFormatType == ImageFormatType.TYPE_BYTE_LA) { + copyByLineAndExpand(bi, depthIndex); + } else { + assert false; + } + + return bi; + + } + return null; + } + + void convertFromABGRToRGBA() { + int i; + + if(imageDataType == ImageComponentRetained.ImageDataType.TYPE_BYTE_ARRAY) { + // Note : Highly inefficient for depth > 0 case. + // This method doesn't take into account of depth, it is assuming that + // depth == 0, which is true for ImageComponent2D. + byte[] srcBuffer, dstBuffer; + srcBuffer = getAsByteArray(); + + if(dataIsByRef) { + dstBuffer = new byte[length]; + // Do copy and swap. + for(i = 0; i < length; i +=4) { + dstBuffer[i] = srcBuffer[i+3]; + dstBuffer[i+1] = srcBuffer[i+2]; + dstBuffer[i+2] = srcBuffer[i+1]; + dstBuffer[i+3] = srcBuffer[i]; + } + data = dstBuffer; + dataIsByRef = false; + + } else { + byte a, b; + // Do swap in place. + for(i = 0; i < length; i +=4) { + a = srcBuffer[i]; + b = srcBuffer[i+1]; + srcBuffer[i] = srcBuffer[i+3]; + srcBuffer[i+1] = srcBuffer[i+2]; + srcBuffer[i+2] = b; + srcBuffer[i+3] = a; + } + } + } + else if(imageDataType == ImageComponentRetained.ImageDataType.TYPE_BYTE_BUFFER) { + + assert dataIsByRef; + ByteBuffer srcBuffer, dstBuffer; + + srcBuffer = getAsByteBuffer(); + srcBuffer.rewind(); + + ByteOrder order = ByteOrder.nativeOrder(); + dstBuffer = ByteBuffer.allocateDirect(length).order(order); + dstBuffer.rewind(); + + // Do copy and swap. + for(i = 0; i < length; i +=4) { + dstBuffer.put(i, srcBuffer.get(i+3)); + dstBuffer.put(i+1, srcBuffer.get(i+2)); + dstBuffer.put(i+2, srcBuffer.get(i+1)); + dstBuffer.put(i+3, srcBuffer.get(i)); + } + + dataIsByRef = false; + + } + } + } +}
\ No newline at end of file diff --git a/src/classes/share/javax/media/j3d/IndexedGeometryArray.java b/src/classes/share/javax/media/j3d/IndexedGeometryArray.java index 67f8914..ae51edc 100644 --- a/src/classes/share/javax/media/j3d/IndexedGeometryArray.java +++ b/src/classes/share/javax/media/j3d/IndexedGeometryArray.java @@ -286,6 +286,10 @@ public abstract class IndexedGeometryArray extends GeometryArray { * than or equal to the number of vertices actually defined for * the particular component's array. * + * @exception ArrayIndexOutOfBoundsException if the data mode for this geometry + * array object is <code>BY_REFERENCE_INDICES</code> and + * <code>coordIndices.length < (initialIndexIndex + validIndexCount)</code>. + * * @since Java 3D 1.3 */ public void setValidIndexCount(int validIndexCount) { @@ -341,6 +345,10 @@ public abstract class IndexedGeometryArray extends GeometryArray { * than or equal to the number of vertices actually defined for * the particular component's array. * + * @exception ArrayIndexOutOfBoundsException if the data mode for this geometry + * array object is <code>BY_REFERENCE_INDICES</code> and + * <code>coordIndices.length < (initialIndexIndex + validIndexCount)</code>. + * * @since Java 3D 1.3 */ public void setInitialIndexIndex(int initialIndexIndex) { @@ -470,6 +478,7 @@ public abstract class IndexedGeometryArray extends GeometryArray { } + //NVaidya /** * Sets the coordinate index associated with the vertex at * the specified index for this object. @@ -488,15 +497,25 @@ public abstract class IndexedGeometryArray extends GeometryArray { * coordinateIndex is out of range if it is less than 0 or is * greater than or equal to the number of vertices actually * defined for the coordinate array. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE_INDICES</code>. */ public void setCoordinateIndex(int index, int coordinateIndex) { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_COORDINATE_INDEX_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray1")); + + //NVaidya + int format = ((IndexedGeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE_INDICES) != 0) + throw new IllegalStateException(J3dI18N.getString("IndexedGeometryArray31")); ((IndexedGeometryArrayRetained)this.retained).setCoordinateIndex(index, coordinateIndex); } + + //NVaidya /** * Sets the coordinate indices associated with the vertices starting at * the specified index for this object. @@ -515,15 +534,64 @@ public abstract class IndexedGeometryArray extends GeometryArray { * is out of range. An element is out of range if it is less than 0 * or is greater than or equal to the number of vertices actually * defined for the coordinate array. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE_INDICES</code>. */ public void setCoordinateIndices(int index, int coordinateIndices[]) { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_COORDINATE_INDEX_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray1")); + + //NVaidya + int format = ((IndexedGeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE_INDICES) != 0) + throw new IllegalStateException(J3dI18N.getString("IndexedGeometryArray31")); ((IndexedGeometryArrayRetained)this.retained).setCoordinateIndices(index, coordinateIndices); } + //NVaidya + /** + * Sets the coordinate indices array reference to the specified array. + * If the coordinate indices array reference is null, the entire + * geometry array object is treated as if it were null--any + * Shape3D or Morph node that uses this geometry array will not be drawn. + * + * @param coordIndices an array of indices to which a reference + * will be set. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalStateException if the data mode for this geometry + * array object is not <code>BY_REFERENCE_INDICES</code>. + * + * @exception ArrayIndexOutOfBoundsException if any element of the + * coordIndices array whose destination position is in the range + * <code>[initialIndexIndex, initialIndexIndex+validIndexCount-1]</code> + * is out of range. An element is out of range if it is less than 0 + * or is greater than or equal to the number of vertices actually + * defined for the coordinate array. + * + * @exception ArrayIndexOutOfBoundsException if + * <code>coordIndices.length < (initialIndexIndex + validIndexCount)</code>. + * + * @since Java 3D 1.5 + */ + public void setCoordIndicesRef(int coordIndices[]) { + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_REF_DATA_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray86")); + + //NVaidya + int format = ((IndexedGeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE_INDICES) == 0) + throw new IllegalStateException(J3dI18N.getString("IndexedGeometryArray32")); + + ((IndexedGeometryArrayRetained)this.retained).setCoordIndicesRef(coordIndices); + } + /** * Sets the color index associated with the vertex at * the specified index for this object. @@ -816,38 +884,81 @@ public abstract class IndexedGeometryArray extends GeometryArray { ((IndexedGeometryArrayRetained)this.retained).setVertexAttrIndices(vertexAttrNum, index, vertexAttrIndices); } + //NVaidya /** - * Retrieves the coordinate index associated with the vertex at - * the specified index for this object. - * @param index the vertex index - * @return the coordinate index + * Retrieves the coordinate index associated with the vertex at + * the specified index for this object. + * @param index the vertex index + * @return the coordinate index * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph - */ + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE_INDICES</code>. + */ public int getCoordinateIndex(int index) { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_COORDINATE_INDEX_READ)) throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray9")); + + //NVaidya + int format = ((IndexedGeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE_INDICES) != 0) + throw new IllegalStateException(J3dI18N.getString("IndexedGeometryArray31")); return ((IndexedGeometryArrayRetained)this.retained).getCoordinateIndex(index); } - /** - * Retrieves the coordinate indices associated with the vertices starting at - * the specified index for this object. - * @param index the vertex index - * @param coordinateIndices array that will receive the coordinate indices + //NVaidya + /** + * Retrieves the coordinate indices associated with the vertices starting at + * the specified index for this object. + * @param index the vertex index + * @param coordinateIndices array that will receive the coordinate indices * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph - */ + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE_INDICES</code>. + */ public void getCoordinateIndices(int index, int coordinateIndices[]) { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_COORDINATE_INDEX_READ)) throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray9")); + + //NVaidya + int format = ((IndexedGeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE_INDICES) != 0) + throw new IllegalStateException(J3dI18N.getString("IndexedGeometryArray31")); ((IndexedGeometryArrayRetained)this.retained).getCoordinateIndices(index, coordinateIndices); } + //NVaidya + /** + * Returns a reference to the coordinate indices associated with + * the vertices + * @return the coordinate indices array + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalStateException if the data mode for this geometry + * array object is not <code>BY_REFERENCE_INDICES</code>. + * + * @since Java 3D 1.5 + */ + public int[] getCoordIndicesRef() { + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_REF_DATA_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray87")); + + int format = ((IndexedGeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE_INDICES) == 0) + throw new IllegalStateException(J3dI18N.getString("IndexedGeometryArray32")); + + return ((IndexedGeometryArrayRetained)this.retained).getCoordIndicesRef(); + } + /** * Retrieves the color index associated with the vertex at * the specified index for this object. diff --git a/src/classes/share/javax/media/j3d/IndexedGeometryArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedGeometryArrayRetained.java index 5fb7ba7..e53565b 100644 --- a/src/classes/share/javax/media/j3d/IndexedGeometryArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedGeometryArrayRetained.java @@ -13,13 +13,8 @@ package javax.media.j3d; import javax.vecmath.*; -import java.util.Vector; import java.util.ArrayList; -import com.sun.j3d.internal.ByteBufferWrapper; -import com.sun.j3d.internal.BufferWrapper; import com.sun.j3d.internal.FloatBufferWrapper; -import com.sun.j3d.internal.DoubleBufferWrapper; - /** * The IndexedGeometryArray object contains arrays of positional coordinates, @@ -60,7 +55,10 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { // index arrays if USE_COORD_INDEX_ONLY is not set boolean notUCIO = (this.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0; - if((this.vertexFormat & GeometryArray.COORDINATES) != 0) + //NVaidya + // Only allocate indexCoord if BY_REFERENCE_INDICES not set + if(((this.vertexFormat & GeometryArray.COORDINATES) != 0) && + ((this.vertexFormat & GeometryArray.BY_REFERENCE_INDICES) == 0)) this.indexCoord = new int[indexCount]; if(((this.vertexFormat & GeometryArray.NORMALS) != 0) && notUCIO) @@ -626,6 +624,120 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { } } + //NVaidya + /** + * Sets the coordinate indices by reference to the specified array + * @param coordinateIndices an array of coordinate indices + */ + final void setCoordIndicesRef(int coordinateIndices[]) { + int newMax = 0; + + if (coordinateIndices != null) { + if (coordinateIndices.length < initialIndexIndex + validIndexCount) { + throw new IllegalArgumentException(J3dI18N.getString("IndexedGeometryArray33")); + } + + // + // option 1: could fake the args to "re-use" doIndicesCheck() + //NVaidya + // newMax = doIndicesCheck(0, maxCoordIndex, coordinateIndices, coordinateIndices); + // if (newMax > maxCoordIndex) { + // doErrorCheck(newMax); + // } + // + // option 2: same logic as in setInitialIndexIndex: Better, I Think ? + // computeMaxIndex() doesn't check for index < 0 while doIndicesCheck() does. + // So, a new method computeMaxIndexWithCheck + //NVaidya + newMax = computeMaxIndexWithCheck(initialIndexIndex, validIndexCount, coordinateIndices); + if (newMax > maxCoordIndex) { + doErrorCheck(newMax); + } + } + + if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) { + if ((vertexFormat & GeometryArray.COLOR) != 0) { + maxColorIndex = newMax; + } + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + for (int i = 0; i < texCoordSetCount; i++) { + maxTexCoordIndices[i] = newMax; + } + } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = newMax; + } + } + if ((vertexFormat & GeometryArray.NORMALS) != 0) { + maxNormalIndex = newMax; + } + } + + geomLock.getLock(); + dirtyFlag |= INDEX_CHANGED; + maxCoordIndex = newMax; + this.indexCoord = coordinateIndices; + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(true); + } + } + + //NVaidya + /** + * trigger from GeometryArrayRetained#updateData() + * to recompute maxCoordIndex and perform index integrity checks + */ + final void doPostUpdaterUpdate() { + // user may have called setCoordIndicesRef and/or + // changed contents of indexCoord array. Thus, need to + // recompute maxCoordIndex unconditionally (and redundantly + // if user had only invoked setCoordIndicesRef but not also + // changed contents). geomLock is currently locked. + + // Option 1: + // simply call setCoordIndicesRef(indexCoord); but this seems to cause + // deadlock or freeze - probably because the !inUpdater branch sends + // out too many sendDataChangedMessage(true) - occurs if updateData + // method is called rapidly. + // setCoordIndicesRef(indexCoord); + + // Option 2: + // use only necessary code from setCoordIndicesRef + // System.out.println("IndexedGeometryArrayretained#doUpdaterUpdate"); + int newMax = 0; + + if (indexCoord != null) { + newMax = computeMaxIndexWithCheck(initialIndexIndex, validIndexCount, indexCoord); + if (newMax > maxCoordIndex) { + doErrorCheck(newMax); + } + } + + if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) { + if ((vertexFormat & GeometryArray.COLOR) != 0) { + maxColorIndex = newMax; + } + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + for (int i = 0; i < texCoordSetCount; i++) { + maxTexCoordIndices[i] = newMax; + } + } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = newMax; + } + } + if ((vertexFormat & GeometryArray.NORMALS) != 0) { + maxNormalIndex = newMax; + } + } + + dirtyFlag |= INDEX_CHANGED; + maxCoordIndex = newMax; + } + /** * Sets the color index associated with the vertex at * the specified index for this object. @@ -781,9 +893,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * the specified index for the specified vertex attribute number * for this object. */ - public void setVertexAttrIndex(int vertexAttrNum, - int index, - int vertexAttrIndex) { + void setVertexAttrIndex(int vertexAttrNum, + int index, + int vertexAttrIndex) { int newMax; int [] indices = this.indexVertexAttr[vertexAttrNum]; @@ -806,9 +918,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * starting at the specified index for the specified vertex attribute number * for this object. */ - public void setVertexAttrIndices(int vertexAttrNum, - int index, - int[] vertexAttrIndices) { + void setVertexAttrIndices(int vertexAttrNum, + int index, + int[] vertexAttrIndices) { int i, j, num = vertexAttrIndices.length; int [] indices = this.indexVertexAttr[vertexAttrNum]; @@ -854,6 +966,15 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { } } + //NVaidya + /** + * Returns a reference to the coordinate indices associated + * with the vertices + */ + final int[] getCoordIndicesRef() { + return this.indexCoord; + } + /** * Retrieves the color index associated with the vertex at * the specified index for this object. @@ -936,8 +1057,8 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * the specified index for the specified vertex attribute number * for this object. */ - public int getVertexAttrIndex(int vertexAttrNum, - int index) { + int getVertexAttrIndex(int vertexAttrNum, + int index) { int [] indices = this.indexVertexAttr[vertexAttrNum]; @@ -949,9 +1070,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * starting at the specified index for the specified vertex attribute number * for this object. */ - public void getVertexAttrIndices(int vertexAttrNum, - int index, - int[] vertexAttrIndices) { + void getVertexAttrIndices(int vertexAttrNum, + int index, + int[] vertexAttrIndices) { int i, j, num = vertexAttrIndices.length; int [] indices = this.indexVertexAttr[vertexAttrNum]; @@ -961,124 +1082,26 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { } } - // by-copy or interleaved, by reference, Java arrays - private native void executeIndexedGeometry(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean useAlpha, - boolean multiScreen, - boolean ignoreVertexColors, - int initialIndexIndex, - int indexCount, - int vertexCount, int vformat, - int vertexAttrCount, int[] vertexAttrSizes, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetOffset, - int numActiveTexUnitState, - int[] texUnitStateMap, - float[] varray, float[] cdata, - int texUnitIndex, int cdirty, - int[] indexCoord); - - // interleaved, by reference, nio buffer - private native void executeIndexedGeometryBuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean useAlpha, - boolean multiScreen, - boolean ignoreVertexColors, - int initialIndexIndex, - int indexCount, - int vertexCount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetOffset, - int numActiveTexUnitState, - int[] texUnitStateMap, - Object varray, float[] cdata, - int texUnitIndex, int cdirty, - int[] indexCoord); - - // non interleaved, by reference, Java arrays - private native void executeIndexedGeometryVA(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean multiScreen, - boolean ignoreVertexColors, - int initialIndexIndex, - int validIndexCount, - int vertexCount, - int vformat, - int vdefined, - float[] vfcoords, double[] vdcoords, - float[] cfdata, byte[] cbdata, - float[] ndata, - int vertexAttrCount, int[] vertexAttrSizes, - float[][] vertexAttrData, - int pass, int texcoordmaplength, - int[] texcoordoffset, - int numActiveTexUnitState, int[] texunitstatemap, - int texstride, Object[] texCoords, - int cdirty, - int[] indexCoord); - - // non interleaved, by reference, nio buffer - private native void executeIndexedGeometryVABuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean multiScreen, - boolean ignoreVertexColors, - int initialIndexIndex, - int validIndexCount, - int vertexCount, - int vformat, - int vdefined, - Object vcoords, - Object cdataBuffer, - float[] cfdata, byte[] cbdata, - Object normal, - int vertexAttrCount, int[] vertexAttrSizes, - Object[] vertexAttrData, - int pass, int texcoordmaplength, - int[] texcoordoffset, - int numActiveTexUnitState, int[] texunitstatemap, - int texstride, Object[] texCoords, - int cdirty, - int[] indexCoord); - - // by-copy geometry - private native void buildIndexedGeometry(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, boolean updateAlpha, - float alpha, - boolean ignoreVertexColors, - int initialIndexIndex, - int validIndexCount, - int vertexCount, - int vformat, - int vertexAttrCount, int[] vertexAttrSizes, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetMapOffset, - double[] xform, double[] nxform, - float[] varray, int[] indexCoord); - void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, - boolean multiScreen, int screen, - boolean ignoreVertexColors, int pass) { + int screen, boolean ignoreVertexColors) { + int cdirty; boolean useAlpha = false; Object[] retVal; if (mirrorGeometry != null) { mirrorGeometry.execute(cv, ra, isNonUniformScale, updateAlpha, alpha, - multiScreen, screen, - ignoreVertexColors, pass); + screen, ignoreVertexColors); return; } - //By reference with java array + + // Check if index array is null; if yes, don't draw anything + if (indexCoord == null) { + return; + } + + //By reference with java array if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) { if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { float[] vdata; @@ -1111,9 +1134,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { dirtyFlag = 0; } - executeIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, + Pipeline.getPipeline().executeIndexedGeometry(cv.ctx, + this, geoType, isNonUniformScale, useAlpha, - multiScreen, ignoreVertexColors, initialIndexIndex, validIndexCount, @@ -1124,16 +1147,16 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { texCoordSetCount, texCoordSetMap, (texCoordSetMap == null) ? 0 : texCoordSetMap.length, texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, + cv.numActiveTexUnit, vdata, null, - pass, cdirty, indexCoord); + cdirty, indexCoord); } // end of non by reference else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) { if(interLeavedVertexData == null) return; - + float[] cdata = null; synchronized (this) { @@ -1157,9 +1180,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { dirtyFlag = 0; } - executeIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, + Pipeline.getPipeline().executeIndexedGeometry(cv.ctx, + this, geoType, isNonUniformScale, useAlpha, - multiScreen, ignoreVertexColors, initialIndexIndex, validIndexCount, @@ -1169,9 +1192,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { texCoordSetCount, texCoordSetMap, (texCoordSetMap == null) ? 0 : texCoordSetMap.length, texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, + cv.numActiveTexUnit, interLeavedVertexData, cdata, - pass, cdirty, indexCoord); + cdirty, indexCoord); } //end of interleaved else { // Check if a vertexformat is set, but the array is null @@ -1252,8 +1275,8 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { if((vertexType & TEXCOORD_DEFINED) != 0) vdefined |= TEXCOORD_FLOAT; - executeIndexedGeometryVA(cv.ctx, this, geoType, isNonUniformScale, - multiScreen, + Pipeline.getPipeline().executeIndexedGeometryVA(cv.ctx, + this, geoType, isNonUniformScale, ignoreVertexColors, initialIndexIndex, validIndexCount, @@ -1265,11 +1288,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { mirrorFloatRefNormals, vertexAttrCount, vertexAttrSizes, mirrorFloatRefVertexAttrs, - pass, ((texCoordSetMap == null) ? 0:texCoordSetMap.length), texCoordSetMap, cv.numActiveTexUnit, - cv.texUnitStateMap, texCoordStride, mirrorRefTexCoords, cdirty, indexCoord); } @@ -1304,20 +1325,20 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { dirtyFlag = 0; } - executeIndexedGeometryBuffer(cv.ctx, this, geoType, isNonUniformScale, - useAlpha, - multiScreen, - ignoreVertexColors, - initialIndexIndex, - validIndexCount, - maxCoordIndex + 1, - vertexFormat, - texCoordSetCount, texCoordSetMap, - (texCoordSetMap == null) ? 0 : texCoordSetMap.length, - texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, - interleavedFloatBufferImpl.getBufferAsObject(), cdata, - pass, cdirty, indexCoord); + Pipeline.getPipeline().executeIndexedGeometryBuffer(cv.ctx, + this, geoType, isNonUniformScale, + useAlpha, + ignoreVertexColors, + initialIndexIndex, + validIndexCount, + maxCoordIndex + 1, + vertexFormat, + texCoordSetCount, texCoordSetMap, + (texCoordSetMap == null) ? 0 : texCoordSetMap.length, + texCoordSetMapOffset, + cv.numActiveTexUnit, + interleavedFloatBufferImpl.getBufferAsObject(), cdata, + cdirty, indexCoord); } //end of interleaved else { // Check if a vertexformat is set, but the array is null @@ -1417,9 +1438,8 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { vdefined |= TEXCOORD_FLOAT; } - executeIndexedGeometryVABuffer(cv.ctx, + Pipeline.getPipeline().executeIndexedGeometryVABuffer(cv.ctx, this, geoType, isNonUniformScale, - multiScreen, ignoreVertexColors, initialIndexIndex, validIndexCount, @@ -1432,11 +1452,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { normal, vertexAttrCount, vertexAttrSizes, nioFloatBufferRefVertexAttrs, - pass, ((texCoordSetMap == null) ? 0:texCoordSetMap.length), texCoordSetMap, cv.numActiveTexUnit, - cv.texUnitStateMap, texCoordStride, refTexCoords, cdirty, indexCoord); @@ -1488,7 +1506,8 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { dirtyFlag = 0; } - buildIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, + Pipeline.getPipeline().buildIndexedGeometry(cv.ctx, + this, geoType, isNonUniformScale, updateAlpha, alpha, ignoreVertexColors, initialIndexIndex, validIndexCount, @@ -1601,6 +1620,22 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { } + //NVaidya + // same as computeMaxIndex method but checks for index < 0 + int computeMaxIndexWithCheck(int initial, int count, int[] indices) { + int maxIndex = 0; + for (int i = initial; i < (initial+count); i++) { + // Throw an exception, since index is negative + if (indices[i] < 0) + throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray27")); + if (indices[i] > maxIndex) { + maxIndex = indices[i]; + } + } + return maxIndex; + + } + void setValidIndexCount(int validIndexCount) { if (validIndexCount < 0) { throw new IllegalArgumentException(J3dI18N.getString("IndexedGeometryArray21")); @@ -1608,6 +1643,11 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { if ((initialIndexIndex + validIndexCount) > indexCount) { throw new IllegalArgumentException(J3dI18N.getString("IndexedGeometryArray22")); } + if ((vertexFormat & GeometryArray.BY_REFERENCE_INDICES) != 0) { + if (indexCoord != null && indexCoord.length < initialIndexIndex + validIndexCount) { + throw new IllegalArgumentException(J3dI18N.getString("IndexedGeometryArray33")); + } + } int newCoordMax =0; int newColorIndex=0; int newNormalIndex=0; @@ -1688,12 +1728,18 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { if ((initialIndexIndex + validIndexCount) > indexCount) { throw new IllegalArgumentException(J3dI18N.getString("IndexedGeometryArray22")); } + if ((vertexFormat & GeometryArray.BY_REFERENCE_INDICES) != 0) { + if (indexCoord != null && indexCoord.length < initialIndexIndex + validIndexCount) { + throw new IllegalArgumentException(J3dI18N.getString("IndexedGeometryArray33")); + } + } + int newCoordMax =0; int newColorIndex=0; int newNormalIndex=0; int[] newTexCoordIndex = null; int[] newVertexAttrIndex = null; - + newCoordMax = computeMaxIndex(initialIndexIndex, validIndexCount, indexCoord); doErrorCheck(newCoordMax); if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { diff --git a/src/classes/share/javax/media/j3d/InputDeviceBlockingThread.java b/src/classes/share/javax/media/j3d/InputDeviceBlockingThread.java index f0fdd26..b96e824 100644 --- a/src/classes/share/javax/media/j3d/InputDeviceBlockingThread.java +++ b/src/classes/share/javax/media/j3d/InputDeviceBlockingThread.java @@ -21,9 +21,10 @@ class InputDeviceBlockingThread extends Thread { // blocking device that this thread manages private InputDevice device; - private boolean running = true; - private boolean waiting = false; + private volatile boolean running = true; private volatile boolean stop = false; + private boolean waiting = false; + private boolean ready = false; private static int numInstances = 0; private int instanceNum = -1; @@ -69,30 +70,35 @@ class InputDeviceBlockingThread extends Thread { } void finish() { - stop = true; - while (!waiting) { - MasterControl.threadYield(); - } - - runMonitor(STOP); + stop = true; + runMonitor(STOP); } synchronized void runMonitor(int action) { switch (action) { case WAIT: - try { - waiting = true; - wait(); - } catch (InterruptedException e) {} - waiting = false; + // Issue 279 - loop until ready + while (running && !ready) { + waiting = true; + try { + wait(); + } catch (InterruptedException e) {} + waiting = false; + } + ready = false; break; case NOTIFY: - notify(); + ready = true; + if (waiting) { + notify(); + } break; case STOP: running = false; - notify(); + if (waiting) { + notify(); + } break; } } diff --git a/src/classes/share/javax/media/j3d/J3DBuffer.java b/src/classes/share/javax/media/j3d/J3DBuffer.java index 7cd5bf9..27f70ed 100644 --- a/src/classes/share/javax/media/j3d/J3DBuffer.java +++ b/src/classes/share/javax/media/j3d/J3DBuffer.java @@ -207,13 +207,8 @@ public class J3DBuffer { return bufferImpl; } - // Native method to verify that we can access a direct NIO buffer - // from native code - private native static long getNativeAddress(java.nio.Buffer buffer); - private static boolean checkNativeBufferAccess(java.nio.Buffer buffer) { - // TODO: uncomment out the call to getNativeAddress and implement it - if (buffer == null /*|| getNativeAddress(buffer) == 0L*/) { + if (buffer == null /*|| !Pipeline.getPipeline().checkNativeBufferAccess(buffer)*/) { return false; } else { diff --git a/src/classes/share/javax/media/j3d/J3DGraphics2DImpl.java b/src/classes/share/javax/media/j3d/J3DGraphics2DImpl.java index d52381c..7521434 100644 --- a/src/classes/share/javax/media/j3d/J3DGraphics2DImpl.java +++ b/src/classes/share/javax/media/j3d/J3DGraphics2DImpl.java @@ -28,6 +28,7 @@ import java.awt.font.*; */ final class J3DGraphics2DImpl extends J3DGraphics2D { + private boolean hasBeenDisposed = false; private Graphics2D offScreenGraphics2D; private BufferedImage g3dImage = null; private byte[] data = null; @@ -45,9 +46,8 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { private Point2D.Float ptDst2 = new Point2D.Float(); private Color xOrModeColor = null; private volatile boolean initCtx = false; - private boolean threadWaiting = false; + private volatile boolean threadWaiting = false; static final Color blackTransparent = new Color(0,0,0,0); - private boolean useDrawPixel = VirtualUniverse.mc.isJ3dG2dDrawPixel; int objectId = -1; // Package scope contructor @@ -55,7 +55,7 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { canvas3d = c; synchronized (VirtualUniverse.mc.contextCreationLock) { - if (c.ctx == 0) { + if (c.ctx == null) { // create a dummy bufferImage width = 1; height = 1; @@ -117,6 +117,10 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { * rendering to be complete before returning from this call. */ public void flush(boolean waiting) { + + if (hasBeenDisposed) { + throw new IllegalStateException(J3dI18N.getString("J3DGraphics2D0")); + } if (!isFlushed) { // Composite g3dImage into Canvas3D @@ -162,8 +166,10 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { // copy the data into a byte buffer that will be passed to opengl void doFlush() { + assert !hasBeenDisposed; + // clip to offscreen buffer size - if (canvas3d.ctx == 0) { + if (canvas3d.ctx == null) { canvas3d.getGraphicsContext3D().doClear(); } @@ -208,7 +214,10 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { final void copyImage(BufferedImage bi, byte[] image, int width, int height, int x1, int y1, int x2, int y2) { - int biType = bi.getType(); + + assert !hasBeenDisposed; + + int biType = bi.getType(); int w, h, i, j; int row, rowBegin, rowInc, dstBegin; @@ -286,7 +295,7 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { void sendRenderMessage(boolean renderRun, int command, Object arg1, Object arg2, Object arg3) { // send a message to the request renderer - J3dMessage renderMessage = VirtualUniverse.mc.getMessage(); + J3dMessage renderMessage = new J3dMessage(); renderMessage.threads = J3dThread.RENDER_THREAD; renderMessage.type = J3dMessage.RENDER_IMMEDIATE; renderMessage.universe = null; @@ -575,10 +584,6 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { offScreenGraphics2D.copyArea(x, y, width, height, dx, dy); } - public final void dispose() { - offScreenGraphics2D.dispose(); - } - public final void draw(Shape s) { Rectangle rect = s.getBounds(); validate(rect.x, rect.y, @@ -867,17 +872,52 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { offScreenGraphics2D.fillRect(x, y, width, height); } - public void finalize() { - if (objectId >= 0) { - VirtualUniverse.mc.freeTexture2DId(objectId); - } - offScreenGraphics2D.finalize(); + // Issue 121 - release all resources, mark as disposed + public void dispose() { + + if (Thread.currentThread() == canvas3d.screen.renderer) { + doDispose(); + } else { + // Behavior Scheduler or other threads + // XXXX: may not be legal for behaviorScheduler + // May cause deadlock if it is in behaviorScheduler + // and we wait for Renderer to finish + boolean renderRun = (Thread.currentThread() != + canvas3d.view.universe.behaviorScheduler); + sendRenderMessage(renderRun, GraphicsContext3D.DISPOSE2D, + null, null, null); + } + + + } + + public void doDispose() { + + if (hasBeenDisposed) { + return; + } + + if (objectId != -1) { + canvas3d.freeTexture(canvas3d.ctx, objectId); + VirtualUniverse.mc.freeTexture2DId(objectId); + objectId = -1; + } + + // Dispose of the underlying Graphics2D + offScreenGraphics2D.dispose(); + + // Mark as disposed + hasBeenDisposed = true; } public void drawAndFlushImage(BufferedImage img, int x, int y, ImageObserver observer) { - if (!(initCtx && abgr && + if (hasBeenDisposed) { + throw new IllegalStateException(J3dI18N.getString("J3DGraphics2D0")); + } + + if (!(initCtx && abgr && (img.getType() == BufferedImage.TYPE_4BYTE_ABGR))) { drawImage(img, x, y, observer); flush(false); @@ -900,11 +940,14 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { void doDrawAndFlushImage(BufferedImage img, int x, int y, ImageObserver observer) { - int imgWidth = img.getWidth(observer); + + assert !hasBeenDisposed; + + int imgWidth = img.getWidth(observer); int imgHeight = img.getHeight(observer); int px, py, x1, y1, x2, y2; - if (canvas3d.ctx == 0) { + if (canvas3d.ctx == null) { canvas3d.getGraphicsContext3D().doClear(); } @@ -961,50 +1004,41 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { try { if (!canvas3d.drawingSurfaceObject.renderLock()) { return; - } + } + + if (!initTexMap) { + if (objectId == -1) { + objectId = VirtualUniverse.mc.getTexture2DId(); + } + texWidth = getGreaterPowerOf2(w); + texHeight = getGreaterPowerOf2(h); + + // Canvas got resize, need to init texture map again + // in Renderer thread + if (!canvas3d.initTexturemapping(canvas3d.ctx, + texWidth, texHeight, + objectId)) { + // Fail to get the texture surface, most likely + // there is not enough texture memory + initTexMap = false; + VirtualUniverse.mc.freeTexture2DId(objectId); + objectId = -1; + // TODO : Need to find a better way to report no resource problem --- Chien. + System.err.println("J3DGraphics2DImpl.copyDataToCanvas() : Fail to get texture resources ..."); + + } else { + initTexMap = true; + } + } + if (initTexMap) { + canvas3d.texturemapping(canvas3d.ctx, px, py, + x1, y1, x2, y2, + texWidth, texHeight, w, + (abgr ? ImageComponentRetained.TYPE_BYTE_ABGR: + ImageComponentRetained.TYPE_BYTE_RGBA), + objectId, data, width, height); + } - if (useDrawPixel) { - canvas3d.composite(canvas3d.ctx, px, py, - x1, y1, x2, y2, w, data, width, height); - } else { - if (!initTexMap) { - if (objectId == -1) { - objectId = VirtualUniverse.mc.getTexture2DId(); - } - texWidth = getGreaterPowerOf2(w); - texHeight = getGreaterPowerOf2(h); - - // Canvas got resize, need to init texture map again - // in Renderer thread - if (!canvas3d.initTexturemapping(canvas3d.ctx, - texWidth, texHeight, - objectId)) { - // Fail to get the texture surface, most likely - // there is not enough texture memory - initTexMap = false; - VirtualUniverse.mc.freeTexture2DId(objectId); - objectId = -1; - // Use DrawPixel next time - useDrawPixel = true; - } else { - initTexMap = true; - } - } - if (initTexMap) { - canvas3d.texturemapping(canvas3d.ctx, px, py, - x1, y1, x2, y2, - texWidth, texHeight, w, - (abgr ? ImageComponentRetained.BYTE_ABGR: - ImageComponentRetained.BYTE_RGBA), - objectId, data, width, height); - } else { - // Fall back to composite for this round - canvas3d.composite(canvas3d.ctx, px, py, - x1, y1, x2, y2, w, data, - width, height); - - } - } canvas3d.drawingSurfaceObject.unLock(); } catch (NullPointerException ne) { canvas3d.drawingSurfaceObject.unLock(); @@ -1043,7 +1077,8 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { */ synchronized void runMonitor(int action) { if (action == J3dThread.WAIT) { - if (threadWaiting) { + // Issue 279 - loop until ready + while (threadWaiting) { try { wait(); } catch (InterruptedException e){} diff --git a/src/classes/share/javax/media/j3d/J3dClock.java b/src/classes/share/javax/media/j3d/J3dClock.java index 307f988..438b945 100644 --- a/src/classes/share/javax/media/j3d/J3dClock.java +++ b/src/classes/share/javax/media/j3d/J3dClock.java @@ -28,16 +28,6 @@ class J3dClock { } /** - * Method to return a high-resolution timer value. - * - * NOTE: when we no longer support JDK 1.4.2 we can replace this - * method with System.nanoTime(). - */ - private static long getHiResTimerValue() { - return MasterControl.getNativeTimerValue(); - } - - /** * Returns the current time in milliseconds. This is a more * accurate version of System.currentTimeMillis and should be used in * its place. @@ -45,19 +35,15 @@ class J3dClock { * @return the current time in milliseconds. */ static long currentTimeMillis() { - return (getHiResTimerValue() / nsecPerMsec) + deltaTime; + return (System.nanoTime() / nsecPerMsec) + deltaTime; } static { - // Ensure that the native libraries are loaded (this can be removed - // once we switch to using System.nanoTime() - VirtualUniverse.loadLibraries(); - // Call time methods once without using their values to ensure that // the methods are "warmed up". We need to make sure that the actual // calls that we use take place as close together as possible in time. System.currentTimeMillis(); - getHiResTimerValue(); + System.nanoTime(); // Compute deltaTime between System.currentTimeMillis() // and the high-res timer, use a synchronized block to force both calls @@ -65,7 +51,7 @@ class J3dClock { long baseTime, baseTimerValue; synchronized (J3dClock.class) { baseTime = System.currentTimeMillis(); - baseTimerValue = getHiResTimerValue(); + baseTimerValue = System.nanoTime(); } deltaTime = baseTime - (baseTimerValue / nsecPerMsec); } diff --git a/src/classes/share/javax/media/j3d/J3dMessage.java b/src/classes/share/javax/media/j3d/J3dMessage.java index 41fa2bc..0838c54 100644 --- a/src/classes/share/javax/media/j3d/J3dMessage.java +++ b/src/classes/share/javax/media/j3d/J3dMessage.java @@ -160,8 +160,7 @@ class J3dMessage extends Object { final synchronized void decRefcount() { if (--refcount == 0) { clear(); - FreeListManager.freeObject(FreeListManager.MESSAGE, this); - } + } } final synchronized int getRefcount() { diff --git a/src/classes/share/javax/media/j3d/J3dNotification.java b/src/classes/share/javax/media/j3d/J3dNotification.java index 807cadf..34ba699 100644 --- a/src/classes/share/javax/media/j3d/J3dNotification.java +++ b/src/classes/share/javax/media/j3d/J3dNotification.java @@ -22,6 +22,7 @@ class J3dNotification extends Object { */ static final int INVALID_TYPE = -1; static final int SHADER_ERROR = 0; + static final int RENDERING_ERROR = 1; /** * This holds the type of this message @@ -39,4 +40,5 @@ class J3dNotification extends Object { static final int MAX_ARGS = 6; Object[] args = new Object[MAX_ARGS]; + } diff --git a/src/classes/share/javax/media/j3d/J3dThread.java b/src/classes/share/javax/media/j3d/J3dThread.java index c585d62..a650ded 100644 --- a/src/classes/share/javax/media/j3d/J3dThread.java +++ b/src/classes/share/javax/media/j3d/J3dThread.java @@ -76,7 +76,13 @@ abstract class J3dThread extends Thread { /** * This indicates that this thread is alive and running */ - private boolean running = true; + private volatile boolean running = true; + + /** + * This flag is set by the RUN action of runMonitor to indicate that the + * waiting thread has work to do. + */ + private volatile boolean ready = false; /** * The thread data for this thread @@ -84,7 +90,7 @@ abstract class J3dThread extends Thread { private J3dThreadData[] data = null; /** - * This indicates that this thread is ready + * This indicates that this thread is started and able to accept work */ private volatile boolean started = false; @@ -121,7 +127,7 @@ abstract class J3dThread extends Thread { /** * Flag to indicate that this thread is waiting to be notify */ - volatile boolean waiting = false; + private volatile boolean waiting = false; /** * Some variables used to name threads correctly @@ -220,7 +226,7 @@ abstract class J3dThread extends Thread { /** * This initializes this thread. Once this method returns, the thread is - * ready to do work. + * able to accept work. */ void initialize() { this.start(); @@ -233,11 +239,11 @@ abstract class J3dThread extends Thread { * This causes the threads run method to exit. */ void finish() { + // NOTE: This spin loop is probably not necessary. while (!waiting) { MasterControl.threadYield(); } runMonitor(STOP, 0,null); - } /** @@ -257,36 +263,52 @@ abstract class J3dThread extends Thread { synchronized void runMonitor(int action, long referenceTime, Object[] args) { switch (action) { - case WAIT: - try { - started = true; - waiting = true; - wait(); - } catch (InterruptedException e) { - System.err.println(e); + case WAIT: + started = true; + // Issue 279 - loop until ready + while (!ready && running) { + waiting = true; + try { + wait(); + } catch (InterruptedException e) { + System.err.println(e); + } + waiting = false; } - waiting = false; + ready = false; break; - case NOTIFY_AND_WAIT: + + case NOTIFY_AND_WAIT: VirtualUniverse.mc.runMonitor(MasterControl.THREAD_DONE, null, - null, null, this); - try { - waiting = true; - wait(); - } catch (InterruptedException e) { - System.err.println(e); + null, null, this); + // Issue 279 - loop until ready + while (!ready && running) { + waiting = true; + try { + wait(); + } catch (InterruptedException e) { + System.err.println(e); + } + waiting = false; } - waiting = false; + ready = false; break; - case RUN: - this.referenceTime = referenceTime; - this.args = args; - notify(); + + case RUN: + this.referenceTime = referenceTime; + this.args = args; + ready = true; + if (waiting) { + notify(); + } + break; + + case STOP: + running = false; + if (waiting) { + notify(); + } break; - case STOP: - running = false; - notify(); - break; } } @@ -303,6 +325,7 @@ abstract class J3dThread extends Thread { void cleanup() { active = false; running = true; + ready = false; data = null; started = true; lastWaitTimestamp = 0; diff --git a/src/classes/share/javax/media/j3d/LightBin.java b/src/classes/share/javax/media/j3d/LightBin.java index a92e638..51d4aab 100644 --- a/src/classes/share/javax/media/j3d/LightBin.java +++ b/src/classes/share/javax/media/j3d/LightBin.java @@ -338,8 +338,7 @@ class LightBin extends Object implements ObjectUpdate { } e.prev = null; e.next = null; - renderBin.envSetFreelist.add(e); - + if (environmentSetList == null && insertEnvSet.size() == 0) { renderBin.removeLightBin(this); geometryBackground = null; diff --git a/src/classes/share/javax/media/j3d/LightRetained.java b/src/classes/share/javax/media/j3d/LightRetained.java index 9126311..e4b7766 100644 --- a/src/classes/share/javax/media/j3d/LightRetained.java +++ b/src/classes/share/javax/media/j3d/LightRetained.java @@ -209,7 +209,7 @@ abstract class LightRetained extends LeafRetained { initScope(scope, index); - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); scopeInfo[0] = addScopeList; scopeInfo[1] = removeScopeList; scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE: Boolean.FALSE); @@ -560,7 +560,7 @@ abstract class LightRetained extends LeafRetained { * This method is implemented by each light for rendering * context updates. This default one does nothing. */ - abstract void update(long ctx, int lightSlot, double scale); + abstract void update(Context ctx, int lightSlot, double scale); // This routine is called when rendering Env structure @@ -847,7 +847,7 @@ abstract class LightRetained extends LeafRetained { } J3dMessage initMessage(int num) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.universe = universe; createMessage.type = J3dMessage.LIGHT_CHANGED; @@ -952,7 +952,7 @@ abstract class LightRetained extends LeafRetained { if (scopes.size() > 0) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); LightRetained[] mlts = new LightRetained[newlyAddedMirrorLights.size()]; for (int i = 0; i < mlts.length; i++) { mlts[i] = (LightRetained)newlyAddedMirrorLights.get(i); @@ -1036,7 +1036,7 @@ abstract class LightRetained extends LeafRetained { } void sendMessage(int attrMask, Object attr) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.LIGHT_CHANGED; createMessage.universe = universe; diff --git a/src/classes/share/javax/media/j3d/LineAttributesRetained.java b/src/classes/share/javax/media/j3d/LineAttributesRetained.java index a82228a..5765db9 100644 --- a/src/classes/share/javax/media/j3d/LineAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/LineAttributesRetained.java @@ -215,21 +215,12 @@ class LineAttributesRetained extends NodeComponentRetained { /** - * This (native) method updates the native context. - */ - native void updateNative(long ctx, - float lineWidth, int linePattern, - int linePatternMask, - int linePatternScaleFactor, - boolean lineAntialiasing); - - /** * This method updates the native context. */ - void updateNative(long ctx) { - updateNative(ctx, - lineWidth, linePattern, linePatternMask, - linePatternScaleFactor, lineAntialiasing); + void updateNative(Context ctx) { + Pipeline.getPipeline().updateLineAttributes(ctx, + lineWidth, linePattern, linePatternMask, + linePatternScaleFactor, lineAntialiasing); } @@ -292,7 +283,7 @@ class LineAttributesRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.LINEATTRIBUTES_CHANGED; createMessage.universe = null; @@ -305,7 +296,7 @@ class LineAttributesRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.LINEATTRIBUTES_CHANGED; diff --git a/src/classes/share/javax/media/j3d/LinearFogRetained.java b/src/classes/share/javax/media/j3d/LinearFogRetained.java index ef03698..fbb4270 100644 --- a/src/classes/share/javax/media/j3d/LinearFogRetained.java +++ b/src/classes/share/javax/media/j3d/LinearFogRetained.java @@ -49,7 +49,7 @@ class LinearFogRetained extends FogRetained { */ void setFrontDistance(double frontDistance){ this.frontDistance = frontDistance; - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.FOG_CHANGED; createMessage.universe = universe; @@ -78,7 +78,7 @@ class LinearFogRetained extends FogRetained { */ void setBackDistance(double backDistance){ this.backDistance = backDistance; - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.FOG_CHANGED; createMessage.universe = universe; @@ -98,12 +98,10 @@ class LinearFogRetained extends FogRetained { * This method and its native counterpart update the native context * fog values. */ - native void update(long ctx, float red, float green, float blue, - double fdist, double bdist); - - void update(long ctx, double scale) { + void update(Context ctx, double scale) { validateDistancesInEc(scale); - update(ctx, color.x, color.y, color.z, frontDistanceInEc, backDistanceInEc); + Pipeline.getPipeline().updateLinearFog(ctx, + color.x, color.y, color.z, frontDistanceInEc, backDistanceInEc); } @@ -115,7 +113,7 @@ class LinearFogRetained extends FogRetained { // Initialize the mirror object, this needs to be done, when // renderBin is not accessing any of the fields - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.universe = universe; createMessage.type = J3dMessage.FOG_CHANGED; diff --git a/src/classes/share/javax/media/j3d/Locale.java b/src/classes/share/javax/media/j3d/Locale.java index 0be5f36..92f9a3b 100644 --- a/src/classes/share/javax/media/j3d/Locale.java +++ b/src/classes/share/javax/media/j3d/Locale.java @@ -210,7 +210,7 @@ public class Locale extends Object { bgr.setLive(s); - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER| J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.type = J3dMessage.ORDERED_GROUP_INSERTED; createMessage.universe = universe; @@ -222,7 +222,7 @@ public class Locale extends Object { VirtualUniverse.mc.processMessage(createMessage); - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.type = J3dMessage.VIEWSPECIFICGROUP_INIT; createMessage.universe = universe; @@ -232,7 +232,7 @@ public class Locale extends Object { VirtualUniverse.mc.processMessage(createMessage); - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = s.notifyThreads; createMessage.type = J3dMessage.INSERT_NODES; createMessage.universe = universe; @@ -252,7 +252,7 @@ public class Locale extends Object { b.executeInitialize(); } - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_BEHAVIOR; createMessage.type = J3dMessage.BEHAVIOR_ACTIVATE; createMessage.universe = universe; @@ -334,7 +334,7 @@ public class Locale extends Object { bgr.setLocale(null); if (messages == null) { - destroyMessage = VirtualUniverse.mc.getMessage(); + destroyMessage = new J3dMessage(); } else { destroyMessage = messages[startIndex++]; } @@ -348,7 +348,7 @@ public class Locale extends Object { if (messages == null) { VirtualUniverse.mc.processMessage(destroyMessage); - destroyMessage = VirtualUniverse.mc.getMessage(); + destroyMessage = new J3dMessage(); } else { destroyMessage = messages[startIndex++]; } @@ -360,7 +360,7 @@ public class Locale extends Object { if (messages == null) { VirtualUniverse.mc.processMessage(destroyMessage); - destroyMessage = VirtualUniverse.mc.getMessage(); + destroyMessage = new J3dMessage(); } else { destroyMessage = messages[startIndex++]; } @@ -439,7 +439,7 @@ public class Locale extends Object { universe.setLiveState.reset(this); obgr.clearLive(universe.setLiveState); - destroyMessage = VirtualUniverse.mc.getMessage(); + destroyMessage = new J3dMessage(); destroyMessage.threads = J3dThread.UPDATE_RENDER| J3dThread.UPDATE_RENDERING_ENVIRONMENT; destroyMessage.type = J3dMessage.ORDERED_GROUP_REMOVED; @@ -450,7 +450,7 @@ public class Locale extends Object { destroyMessage.args[4] = universe.setLiveState.ogCIOTableList.toArray(); VirtualUniverse.mc.processMessage(destroyMessage); - destroyMessage = VirtualUniverse.mc.getMessage(); + destroyMessage = new J3dMessage(); destroyMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; destroyMessage.type = J3dMessage.VIEWSPECIFICGROUP_CLEAR; destroyMessage.universe = universe; @@ -459,7 +459,7 @@ public class Locale extends Object { VirtualUniverse.mc.processMessage(destroyMessage); - destroyMessage = VirtualUniverse.mc.getMessage(); + destroyMessage = new J3dMessage(); destroyMessage.threads = universe.setLiveState.notifyThreads; destroyMessage.type = J3dMessage.REMOVE_NODES; destroyMessage.universe = universe; @@ -493,7 +493,7 @@ public class Locale extends Object { nbgr.setLive(universe.setLiveState); - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER| J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.type = J3dMessage.ORDERED_GROUP_INSERTED; createMessage.universe = universe; @@ -505,7 +505,7 @@ public class Locale extends Object { VirtualUniverse.mc.processMessage(createMessage); // XXXX: make these two into one message - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = universe.setLiveState.notifyThreads; createMessage.type = J3dMessage.INSERT_NODES; createMessage.universe = universe; @@ -529,7 +529,7 @@ public class Locale extends Object { ((BehaviorRetained) behaviorNodes[i]).executeInitialize(); } - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_BEHAVIOR; createMessage.type = J3dMessage.BEHAVIOR_ACTIVATE; createMessage.universe = universe; @@ -1068,14 +1068,4 @@ public class Locale extends Object { } - /** - * Cleans up resources associated with this Locale - */ - protected void finalize() { - // free nodeId - if (universe != null && nodeId != null) { - universe.nodeIdFreeList.addElement(nodeId); - nodeId = null; - } - } } diff --git a/src/classes/share/javax/media/j3d/MasterControl.java b/src/classes/share/javax/media/j3d/MasterControl.java index ddb311f..655e9f6 100644 --- a/src/classes/share/javax/media/j3d/MasterControl.java +++ b/src/classes/share/javax/media/j3d/MasterControl.java @@ -20,8 +20,6 @@ package javax.media.j3d; import java.util.*; import java.awt.*; -import java.io.File; - class MasterControl { @@ -32,25 +30,16 @@ class MasterControl { static final int SET_WORK = 1; static final int RUN_THREADS = 2; static final int THREAD_DONE = 3; - static final int WAIT_FOR_ALL = 4; static final int SET_WORK_FOR_REQUEST_RENDERER = 5; static final int RUN_RENDERER_CLEANUP = 6; - static final int SLEEP = 7; // The thread states for MC static final int SLEEPING = 0; static final int RUNNING = 1; - static final int WAITING_FOR_THREAD = 2; static final int WAITING_FOR_THREADS = 3; static final int WAITING_FOR_CPU = 4; static final int WAITING_FOR_RENDERER_CLEANUP = 5; - // The Rendering API's that we currently know about - static final int RENDER_OPENGL_SOLARIS = 0; - static final int RENDER_OPENGL_WIN32 = 1; - static final int RENDER_DIRECT3D = 2; - static final int RENDER_OPENGL_LINUX = 3; - // Constants used in renderer thread argument static final Integer REQUESTRENDER = new Integer(Renderer.REQUESTRENDER); static final Integer RENDER = new Integer(Renderer.RENDER); @@ -127,12 +116,6 @@ class MasterControl { */ private int numActiveViews = 0; - // A freelist for ImageComponentUpdateInfo - private ImageComponentUpdateInfo[] imageUpdateInfoList = - new ImageComponentUpdateInfo[2]; - private int numFreeImageUpdateInfo = 0; - - /** * The list of active universes get from View */ @@ -295,15 +278,11 @@ class MasterControl { */ static long systemStartTime = 0L; - // The rendering API we are using - private int renderingAPI = RENDER_OPENGL_SOLARIS; - static boolean isD3DAPI = false; - - // Are we on a Win32 system - static boolean isWin32 = false; - - // The class that describes the low level rendering code - private NativeAPIInfo nativeAPIInfo = null; + // Flag indicating that we are on a Windows OS + private static boolean isWindowsOs = false; + + // Flag indicating we are on MacOS + private static boolean isMacOs = false; // This is a counter for texture id's, valid id starts from 1 private int textureIdCount = 0; @@ -322,14 +301,6 @@ class MasterControl { // This is a counter for rendererBit private int rendererCount = 0; - /* - // Flag that indicates whether the JVM is version JDK1.5 or later. - // If so, then the jvm15OrBetter flag is set to true, indicating that - // 1.5 functionality can be used. - // We don't use any JDK 1.5 features yet, so this is a placeholder. - static boolean jvm15OrBetter = false; - */ - // Flag that indicates whether to shared display context or not boolean isSharedCtx = false; @@ -356,6 +327,16 @@ class MasterControl { // be in display list. boolean vertexAttrsInDisplayList = false; + // Issue 249 - flag that indicates whether the soleUser optimization is permitted + boolean allowSoleUser = false; + + // Issue 266 - Flag indicating whether null graphics configs are allowed + // Set by -Dj3d.allowNullGraphicsConfig property + // Setting this flag causes Canvas3D to allow a null GraphicsConfiguration + // for on-screen canvases. This is only for backward compatibility with + // legacy applications. + boolean allowNullGraphicsConfig = false; + // The global shading language being used. Using a ShaderProgram // with a shading language other than the one specified by // globalShadingLanguage will cause a ShaderError to be generated, @@ -368,7 +349,7 @@ class MasterControl { static boolean cgLibraryAvailable = false; static boolean glslLibraryAvailable = false; - + // REQUESTCLEANUP messages argument static Integer REMOVEALLCTXS_CLEANUP = new Integer(1); static Integer REMOVECTX_CLEANUP = new Integer(2); @@ -388,20 +369,17 @@ class MasterControl { // Flag that indicates whether to lock the DSI while rendering boolean doDsiRenderLock = false; - - // Flag that indicates whether J3DGraphics2D uses texturemapping - // instead of drawpixel for composite the buffers - boolean isJ3dG2dDrawPixel = false; - - // flag that indicates whether BackgroundRetained uses texturemapping - // or drawpixel clear the background - boolean isBackgroundTexture = true; + + // Flag that indicates the pre-1.5 behavior of enforcing power-of-two + // textures. If set, then any non-power-of-two textures will throw an + // exception. + boolean enforcePowerOfTwo = false; // Flag that indicates whether the framebuffer is sharing the // Z-buffer with both the left and right eyes when in stereo mode. // If this is true, we need to clear the Z-buffer between rendering // to the left and right eyes. - boolean sharedStereoZBuffer; + boolean sharedStereoZBuffer = true; // True to disable all underlying multisampling API so it uses // the setting in the driver. @@ -410,11 +388,11 @@ class MasterControl { // False to disable compiled vertex array extensions if support boolean isCompiledVertexArray = true; - // False to disable rescale normal if OGL support - boolean isForceNormalized = false; - - // True to allow simulated (multi-pass) multi-texture - boolean allowSimulatedMultiTexture = false; + // Number of reserved vertex attribute locations for GLSL (must be at + // least 1). + // Issue 269 - need to reserve up to 6 vertex attribtue locations to ensure + // that we don't collide with a predefined gl_* attribute on nVidia cards. + int glslVertexAttrOffset = 6; // Hashtable that maps a GraphicsDevice to its associated // Screen3D--this is only used for on-screen Canvas3Ds @@ -435,7 +413,7 @@ class MasterControl { // Root ThreadGroup for creating Java 3D threads private static ThreadGroup rootThreadGroup; - // Thread priority for all Java3D threads + // Thread priority for all Java 3D threads private static int threadPriority; static private Object mcThreadLock = new Object(); @@ -443,40 +421,11 @@ class MasterControl { private ArrayList timestampUpdateList = new ArrayList(3); private UnorderList freeMessageList = new UnorderList(8); - - // System properties containing the native library search PATH - // The order listed is the order in which they will be searched - private static final String[] systemPathProps = { - "sun.boot.library.path", - "java.library.path" - }; + // Native AWT object long awt; - private native long getAWT(); - - // Method to initialize the native J3D library - private native boolean initializeJ3D(boolean disableXinerama); - // Method to verify whether the native Cg library is available - private static native boolean loadNativeCgLibrary(String[] libpath); - - // Method to get number of procesor - private native int getNumberOfProcessor(); - - // Methods to set/get system thread concurrency - private native void setThreadConcurrency(int newLevel); - private native int getThreadConcurrency(); - - // Native method to get the high-resolution timer value. - // This method is only called by the J3dClock.getHiResTimerValue. - // It is defined as a MasterControl method for convenience, so we don't - // have to have yet another class with native methods. - // - // NOTE: once we drop support for JDK 1.4.2, this method will go away. - static native long getNativeTimerValue(); - - // Maximum lights supported by the native API - private native int getMaximumLights(); + // Maximum number of lights int maxLights; // This is used for D3D only @@ -509,15 +458,9 @@ class MasterControl { */ MasterControl() { assert librariesLoaded; - - // Get AWT handle - awt = getAWT(); - // Get native API information - nativeAPIInfo = new NativeAPIInfo(); - renderingAPI = nativeAPIInfo.getRenderingAPI(); - isD3DAPI = (renderingAPI == RENDER_DIRECT3D); - isWin32 = isD3DAPI || (renderingAPI == RENDER_OPENGL_WIN32); + // Get AWT handle + awt = Pipeline.getPipeline().getAWT(); // Initialize the start time upon which alpha's and behaviors // are synchronized to (if it isn't already set). @@ -532,7 +475,7 @@ class MasterControl { } // Check to see whether shared contexts are allowed - if (getRenderingAPI() != RENDER_DIRECT3D) { + if (!isD3D()) { isSharedCtx = getBooleanProperty("j3d.sharedctx", isSharedCtx, "shared contexts"); } @@ -586,23 +529,6 @@ class MasterControl { isCompiledVertexArray, "compiled vertex array"); - isForceNormalized = - getBooleanProperty("j3d.forceNormalized", - isForceNormalized, - "force normalized"); - - allowSimulatedMultiTexture = - getBooleanProperty("j3d.simulatedMultiTexture", - allowSimulatedMultiTexture, - "simulated multi-texture"); - - if (allowSimulatedMultiTexture) { - System.err.println("************************************************************************"); - System.err.println(J3dI18N.getString("MasterControl2")); - System.err.println(J3dI18N.getString("MasterControl3")); - System.err.println("************************************************************************"); - } - boolean j3dOptimizeSpace = getBooleanProperty("j3d.optimizeForSpace", true, "optimize for space"); @@ -625,36 +551,30 @@ class MasterControl { doDsiRenderLock = getBooleanProperty("j3d.renderLock", doDsiRenderLock, "render lock"); + + // Check to see whether we enforce power-of-two textures + enforcePowerOfTwo = getBooleanProperty("j3d.textureEnforcePowerOfTwo", + enforcePowerOfTwo, + "checking power-of-two textures"); - // Check to see whether J3DGraphics2D uses texturemapping - // or drawpixel to composite the buffers - isJ3dG2dDrawPixel = getBooleanProperty("j3d.g2ddrawpixel", - isJ3dG2dDrawPixel, - "Graphics2D DrawPixel"); + // Issue 249 - check to see whether the soleUser optimization is permitted + allowSoleUser = getBooleanProperty("j3d.allowSoleUser", + allowSoleUser, + "sole-user mode"); - // Check to see whether BackgroundRetained uses texturemapping - // or drawpixel clear the background - if (!isD3D()) { - isBackgroundTexture = - getBooleanProperty("j3d.backgroundtexture", - isBackgroundTexture, - "background texture"); - } else { - // D3D always uses background texture and uses - // canvas.clear() instead of canvas.textureclear() in Renderer - isBackgroundTexture = false; - } + // Issue 266 - check to see whether null graphics configs are allowed + allowNullGraphicsConfig = getBooleanProperty("j3d.allowNullGraphicsConfig", + allowNullGraphicsConfig, + "null graphics configs"); // Check to see if stereo mode is sharing the Z-buffer for both eyes. - boolean defaultSharedStereoZBuffer = - getRenderingAPI() != RENDER_OPENGL_SOLARIS; sharedStereoZBuffer = getBooleanProperty("j3d.sharedstereozbuffer", - defaultSharedStereoZBuffer, + sharedStereoZBuffer, "shared stereo Z buffer"); // Get the maximum number of concurrent threads (CPUs) - final int defaultThreadLimit = getNumberOfProcessor()+1; + final int defaultThreadLimit = getNumberOfProcessors() + 1; Integer threadLimit = (Integer) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -664,7 +584,6 @@ class MasterControl { } }); - cpuLimit = threadLimit.intValue(); if (cpuLimit < 1) cpuLimit = 1; @@ -673,22 +592,6 @@ class MasterControl { cpuLimit); } - // Ensure that there are at least enough system threads to - // support all of Java 3D's threads running in parallel - int threadConcurrency = getThreadConcurrency(); - if (J3dDebug.debug) { - System.err.println("System threadConcurrency = " + - threadConcurrency); - } - if (threadConcurrency != -1 && threadConcurrency < (cpuLimit + 1)) { - threadConcurrency = cpuLimit + 1; - if (J3dDebug.debug) { - System.err.println("Setting system threadConcurrency to " + - threadConcurrency); - } - setThreadConcurrency(threadConcurrency); - } - // Get the input device scheduler sampling time Integer samplingTime = (Integer) java.security.AccessController.doPrivileged( @@ -705,17 +608,34 @@ class MasterControl { + samplingTime + " ms"); } - // See if Xinerama should be disabled for better performance. + // Get the glslVertexAttrOffset + final int defaultGLSLVertexAttrOffset = glslVertexAttrOffset; + Integer vattrOffset = + (Integer) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + return Integer.getInteger("j3d.glslVertexAttrOffset", + defaultGLSLVertexAttrOffset); + } + }); + + glslVertexAttrOffset = vattrOffset.intValue(); + if (glslVertexAttrOffset < 1) { + glslVertexAttrOffset = 1; + } + if (J3dDebug.debug || glslVertexAttrOffset != defaultGLSLVertexAttrOffset) { + System.err.println("Java 3D: glslVertexAttrOffset = " + + glslVertexAttrOffset); + } + + // See if Xinerama should be disabled for better performance. boolean disableXinerama = false; if (getProperty("j3d.disableXinerama") != null) { disableXinerama = true; } // Initialize the native J3D library - if (!initializeJ3D(disableXinerama)) { - if (isGreenThreadUsed()) { - System.err.print(J3dI18N.getString("MasterControl1")); - } + if (!Pipeline.getPipeline().initializeJ3D(disableXinerama)) { throw new RuntimeException(J3dI18N.getString("MasterControl0")); } @@ -728,10 +648,24 @@ class MasterControl { System.err.println("Java 3D: could not disable Xinerama"); } + // Check for obsolete properties + String[] obsoleteProps = { + "j3d.backgroundtexture", + "j3d.forceNormalized", + "j3d.g2ddrawpixel", + "j3d.simulatedMultiTexture", + "j3d.useFreeLists", + }; + for (int i = 0; i < obsoleteProps.length; i++) { + if (getProperty(obsoleteProps[i]) != null) { + System.err.println(obsoleteProps[i] + " : property ignored"); + } + } + // Get the maximum Lights - maxLights = getMaximumLights(); + maxLights = Pipeline.getPipeline().getMaximumLights(); - // create the freelists + // create the freelists FreeListManager.createFreeLists(); // create an array canvas use registers @@ -777,98 +711,87 @@ class MasterControl { (msg + " disabled")); } - // Java 3D only supports native threads - boolean isGreenThreadUsed() { - return false; - } - - /** - * Method to load the native libraries needed by Java 3D. This is + * Method to create and initialize the rendering Pipeline object, + * and to load the native libraries needed by Java 3D. This is * called by the static initializer in VirtualUniverse <i>before</i> * the MasterControl object is created. */ static void loadLibraries() { assert !librariesLoaded; - // This works around a native load library bug - try { - java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit(); - toolkit = null; // just making sure GC collects this - } catch (java.awt.AWTError e) { - } - - // Load the JAWT native library - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - System.loadLibrary("jawt"); - return null; - } - }); - - // Load the native J3D library - final String oglLibraryName = "j3dcore-ogl"; - final String d3dLibraryName = "j3dcore-d3d"; - final String libraryName = (String) - java.security.AccessController.doPrivileged(new - java.security.PrivilegedAction() { - public Object run() { - String libName = oglLibraryName; - - // If it is a Windows OS, we want to support dynamic native library selection (ogl, d3d) - String osName = System.getProperty("os.name"); - if (osName != null && osName.startsWith("Windows")) { - // XXXX : Should eventually support a more flexible dynamic - // selection scheme via an API call. - String str = System.getProperty("j3d.rend"); - if (str != null && str.equals("d3d")) { - libName = d3dLibraryName; - } - } + // Set global flags indicating whether we are running on Windows or MacOS + String osName = getProperty("os.name"); + isWindowsOs = osName != null && osName.startsWith("Windows"); + isMacOs = osName != null && osName.startsWith("Mac"); + +//KCR: System.err.println("MasterControl.loadLibraries()"); +//KCR: System.err.println(" osName = \"" + osName + "\"" + +//KCR: ", isWindowsOs = " + isWindowsOs + +//KCR: ", isMacOs = " + isMacOs); + + // Initialize the Pipeline object associated with the + // renderer specified by the "j3d.rend" system property. + // + // XXXX : We should consider adding support for a more flexible, + // dynamic selection scheme via an API call. + + // Default rendering pipeline is the JOGL pipeline on MacOS and the + // native OpenGL pipeline on all other platforms. + Pipeline.Type pipelineType = + isMacOs ? Pipeline.Type.JOGL : Pipeline.Type.NATIVE_OGL; + + String rendStr = getProperty("j3d.rend"); + if (rendStr == null) { + // Use default pipeline + } else if (rendStr.equals("ogl") && !isMacOs) { + pipelineType = Pipeline.Type.NATIVE_OGL; + } else if (rendStr.equals("d3d") && isWindowsOs) { + pipelineType = Pipeline.Type.NATIVE_D3D; + } else if (rendStr.equals("jogl")) { + pipelineType = Pipeline.Type.JOGL; + } else if (rendStr.equals("noop")) { + pipelineType = Pipeline.Type.NOOP; + } else { + System.err.println("Java 3D: Unrecognized renderer: " + rendStr); + // Use default pipeline + } - System.loadLibrary(libName); - return libName; - } - }); +//KCR: System.err.println(" using " + pipelineType + " pipeline"); + + // Construct the singleton Pipeline instance + Pipeline.createPipeline(pipelineType); + + // Get the global j3d.shadingLanguage system property + final String slStr = getProperty("j3d.shadingLanguage"); + if (slStr != null) { + boolean found = false; + if (slStr.equals("GLSL")) { + globalShadingLanguage = Shader.SHADING_LANGUAGE_GLSL; + found = true; + } else if (slStr.equals("Cg")) { + globalShadingLanguage = Shader.SHADING_LANGUAGE_CG; + found = true; + } - // Get the global j3d.shadingLanguage property - final String slStr = getProperty("j3d.shadingLanguage"); - if (slStr != null) { - boolean found = false; - if (slStr.equals("GLSL")) { - globalShadingLanguage = Shader.SHADING_LANGUAGE_GLSL; - found = true; - } - else if (slStr.equals("Cg")) { - globalShadingLanguage = Shader.SHADING_LANGUAGE_CG; - found = true; - } + if (found) { + System.err.println("Java 3D: Setting global shading language to " + slStr); + } else { + System.err.println("Java 3D: Unrecognized shading language: " + slStr); + } + } - if (found) { - System.err.println("Java 3D: Setting global shading language to " + slStr); - } - else { - System.err.println("Java 3D: Unrecognized shading language: " + slStr); - } - } + // Load all required libraries + Pipeline.getPipeline().loadLibraries(globalShadingLanguage); // Check whether the Cg library is available if (globalShadingLanguage == Shader.SHADING_LANGUAGE_CG) { - String cgLibraryName = libraryName + "-cg"; - String[] libpath = setupLibPath(systemPathProps, cgLibraryName); - if (loadNativeCgLibrary(libpath)) { - cgLibraryAvailable = true; - } + cgLibraryAvailable = Pipeline.getPipeline().isCgLibraryAvailable(); } - + // Check whether the GLSL library is available if (globalShadingLanguage == Shader.SHADING_LANGUAGE_GLSL) { - if (libraryName == oglLibraryName) { - // No need to verify that GLSL is available, since GLSL is part - // of OpenGL as an extension (or part of core in 2.0) - glslLibraryAvailable = true; - } + glslLibraryAvailable = Pipeline.getPipeline().isGLSLLibraryAvailable(); } assert !(glslLibraryAvailable && cgLibraryAvailable) : @@ -879,46 +802,6 @@ class MasterControl { /** - * Parse the specified System properties containing a PATH and return an - * array of Strings, where each element is an absolute filename consisting of - * the individual component of the path concatenated with the (relative) - * library file name. Only those absolute filenames that exist are included. - * If no absolute filename is found, we will try the relative library name. - */ - private static String[] setupLibPath(String[] props, String libName) { - ArrayList pathList = new ArrayList(); - - String filename = System.mapLibraryName(libName); - for (int n = 0; n < props.length; n++) { - String pathString = getProperty(props[n]); - boolean done = false; - int posStart = 0; - while (!done) { - int posEnd = pathString.indexOf(File.pathSeparator, posStart); - if (posEnd == -1) { - posEnd = pathString.length(); - done = true; - } - String pathDir = pathString.substring(posStart, posEnd); - File pathFile = new File(pathDir, filename); - if (pathFile.exists()) { - pathList.add(pathFile.getAbsolutePath()); - } - - posStart = posEnd + 1; - } - } - - // If no absolute path names exist, add in the relative library name - if (pathList.size() == 0) { - pathList.add(filename); - } - - return (String[])pathList.toArray(new String[0]); - } - - - /** * Invoke from InputDeviceScheduler to create an * InputDeviceBlockingThread. */ @@ -997,8 +880,7 @@ class MasterControl { * This returns the a unused displayListId */ Integer getDisplayListId() { - return (Integer) - FreeListManager.getObject(FreeListManager.DISPLAYLIST); + return (Integer) FreeListManager.getObject(FreeListManager.DISPLAYLIST); } void freeDisplayListId(Integer id) { @@ -1017,11 +899,12 @@ class MasterControl { synchronized (textureIdLock) { if (textureIds.size() > 0) { - return ((Integer)FreeListManager. + id = ((Integer)FreeListManager. getObject(FreeListManager.TEXTURE2D)).intValue(); } else { - return (++textureIdCount); + id = (++textureIdCount); } + return id; } } @@ -1079,72 +962,6 @@ class MasterControl { } } } - - Transform3D getTransform3D(Transform3D val) { - Transform3D t; - t = (Transform3D) - FreeListManager.getObject(FreeListManager.TRANSFORM3D); - if (val != null) t.set(val); - return t; - } - - void addToTransformFreeList(Transform3D t) { - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t); - } - - - ImageComponentUpdateInfo getFreeImageUpdateInfo() { - ImageComponentUpdateInfo info; - - synchronized (imageUpdateInfoList) { - if (numFreeImageUpdateInfo > 0) { - numFreeImageUpdateInfo--; - info = (ImageComponentUpdateInfo) - imageUpdateInfoList[numFreeImageUpdateInfo]; - } else { - info = new ImageComponentUpdateInfo(); - } - } - return (info); - } - - void addFreeImageUpdateInfo(ImageComponentUpdateInfo info) { - synchronized (imageUpdateInfoList) { - if (imageUpdateInfoList.length == numFreeImageUpdateInfo) { - ImageComponentUpdateInfo[] newFreeList = - new ImageComponentUpdateInfo[numFreeImageUpdateInfo * 2]; - System.arraycopy(imageUpdateInfoList, 0, newFreeList, 0, - numFreeImageUpdateInfo); - newFreeList[numFreeImageUpdateInfo++] = info; - imageUpdateInfoList = newFreeList; - } else { - imageUpdateInfoList[numFreeImageUpdateInfo++] = info; - } - } - } - - void addFreeImageUpdateInfo(ArrayList freeList) { - ImageComponentUpdateInfo info; - - synchronized (imageUpdateInfoList) { - int len = numFreeImageUpdateInfo + freeList.size(); - - if (imageUpdateInfoList.length <= len) { - ImageComponentUpdateInfo[] newFreeList = - new ImageComponentUpdateInfo[len * 2]; - System.arraycopy(imageUpdateInfoList, 0, newFreeList, 0, - numFreeImageUpdateInfo); - imageUpdateInfoList = newFreeList; - } - - for (int i = 0; i < freeList.size(); i++) { - info = (ImageComponentUpdateInfo) freeList.get(i); - if (info != null) { - imageUpdateInfoList[numFreeImageUpdateInfo++] = info; - } - } - } - } /** @@ -1270,77 +1087,29 @@ class MasterControl { } /** - * Returns the native rendering layer we are using + * Returns whether we are using D3D. + * TODO: most code that cares about this should move into the pipeline */ - final int getRenderingAPI() { - return renderingAPI; - } - final boolean isD3D() { - return isD3DAPI; + return Pipeline.getPipeline().getPipelineType() == Pipeline.Type.NATIVE_D3D; } /** - * This method increments and returns the next time value - * timeLock must get before this procedure is invoked + * Returns whether we are running on Windows + * TODO: most code that cares about this should move into the pipeline */ - final long getTime() { - return (time++); + final boolean isWindows() { + return isWindowsOs; } - - - /** - * This adds a BHNode to one of the list of BHNodes - */ - void addBHNodeToFreelists(BHNode bH) { - bH.parent = null; - bH.mark = false; - - if (bH.nodeType == BHNode.BH_TYPE_INTERNAL) { - ((BHInternalNode)bH).lChild = null; - ((BHInternalNode)bH).rChild = null; - FreeListManager.freeObject(FreeListManager.BHINTERNAL, bH); - } - else if (bH.nodeType == BHNode.BH_TYPE_LEAF) { - ((BHLeafNode)(bH)).leafIF = null; - FreeListManager.freeObject(FreeListManager.BHLEAF, bH); - } - } - /** - * This gets a message from the free list. If there isn't any, - * it creates one. + * This method increments and returns the next time value + * timeLock must get before this procedure is invoked */ - BHNode getBHNode(int type) { - - if (type == BHNode.BH_TYPE_LEAF) { - return (BHNode) FreeListManager.getObject(FreeListManager.BHLEAF); - } - - if (type == BHNode.BH_TYPE_INTERNAL) { - return (BHNode) - FreeListManager.getObject(FreeListManager.BHINTERNAL); - } - return null; + final long getTime() { + return (time++); } - - /** - * This adds a message to the list of messages - */ - final void addMessageToFreelists(J3dMessage m) { - FreeListManager.freeObject(FreeListManager.MESSAGE, m); - } - - /** - * This gets a message from the free list. If there isn't any, - * it creates one. - */ - final J3dMessage getMessage() { - return (J3dMessage) FreeListManager.getObject(FreeListManager.MESSAGE); - } - /** * This takes a given message and parses it out to the structures and @@ -1493,7 +1262,6 @@ class MasterControl { if (message.getRefcount() == 0) { message.clear(); - addMessageToFreelists(message); } } } @@ -1685,183 +1453,189 @@ class MasterControl { } /** - * This snapshots the time values to be used for this iteration + * This snapshots the time values to be used for this iteration. + * Note that this method is called without the timeLock held. + * We must synchronize on timeLock to prevent updating + * thread.lastUpdateTime from user thread in sendMessage() + * or sendRunMessage(). */ private void updateTimeValues() { - int i=0; - J3dThreadData lastThread=null; - J3dThreadData thread=null; - long lastTime = currentTime; - - currentTime = getTime(); - - J3dThreadData threads[] = (J3dThreadData []) - stateWorkThreads.toArray(false); - int size = stateWorkThreads.arraySize(); - - while (i<lastTransformStructureThread) { - thread = threads[i++]; - - if ((thread.lastUpdateTime > thread.lastRunTime) && - !thread.thread.userStop) { - lastThread = thread; - thread.needsRun = true; - thread.threadOpts = J3dThreadData.CONT_THREAD; - thread.lastRunTime = currentTime; - } else { - thread.needsRun = false; - } - } - - if (lastThread != null) { - lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; - lastThread = null; - } - - while (i<lastStructureUpdateThread) { - thread = threads[i++]; - if ((thread.lastUpdateTime > thread.lastRunTime) && - !thread.thread.userStop) { - lastThread = thread; - thread.needsRun = true; - thread.threadOpts = J3dThreadData.CONT_THREAD; - thread.lastRunTime = currentTime; - } else { - thread.needsRun = false; - } - } - if (lastThread != null) { - lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; - lastThread = null; - } - - while (i<size) { - thread = threads[i++]; - if ((thread.lastUpdateTime > thread.lastRunTime) && - !thread.thread.userStop) { - lastThread = thread; - thread.needsRun = true; - thread.threadOpts = J3dThreadData.CONT_THREAD; - thread.lastRunTime = currentTime; - } else { - thread.needsRun = false; - } - } - if (lastThread != null) { - lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; - lastThread = null; - } - + synchronized (timeLock) { + int i=0; + J3dThreadData lastThread=null; + J3dThreadData thread=null; + long lastTime = currentTime; + + currentTime = getTime(); + + J3dThreadData threads[] = (J3dThreadData []) + stateWorkThreads.toArray(false); + int size = stateWorkThreads.arraySize(); + + while (i<lastTransformStructureThread) { + thread = threads[i++]; + + if ((thread.lastUpdateTime > thread.lastRunTime) && + !thread.thread.userStop) { + lastThread = thread; + thread.needsRun = true; + thread.threadOpts = J3dThreadData.CONT_THREAD; + thread.lastRunTime = currentTime; + } else { + thread.needsRun = false; + } + } - threads = (J3dThreadData []) renderWorkThreads.toArray(false); - size = renderWorkThreads.arraySize(); - View v; - J3dThreadData lastRunThread = null; - waitTimestamp++; - sleepTime = 0L; - - boolean threadToRun = false; // Not currently used - - // Fix for Issue 12: loop through the list of threads, calling - // computeCycleTime() exactly once per view. This ensures that - // all threads for a given view see consistent values for - // isMinCycleTimeAchieve and sleepTime. - v = null; - for (i=0; i<size; i++) { - thread = threads[i]; - if (thread.view != v) { - thread.view.computeCycleTime(); - // Set sleepTime to the value needed to satify the - // minimum cycle time of the slowest view - if (thread.view.sleepTime > sleepTime) { - sleepTime = thread.view.sleepTime; - } - } - v = thread.view; - } + if (lastThread != null) { + lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; + lastThread = null; + } - v = null; - for (i=0; i<size; i++) { - thread = threads[i]; - if (thread.canvas == null) { // Only for swap thread - ((Object []) thread.threadArgs)[3] = null; - } - if ((thread.lastUpdateTime > thread.lastRunTime) && - !thread.thread.userStop) { - - if (thread.thread.lastWaitTimestamp == waitTimestamp) { - // This renderer thread is repeated. We must wait - // until all previous renderer threads done before - // allowing this thread to continue. Note that - // lastRunThread can't be null in this case. - waitTimestamp++; - if (thread.view != v) { - // A new View is start - v = thread.view; - threadToRun = true; - lastRunThread.threadOpts = - (J3dThreadData.STOP_TIMER | - J3dThreadData.WAIT_ALL_THREADS); - ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; - thread.threadOpts = (J3dThreadData.START_TIMER | - J3dThreadData.CONT_THREAD); - } else { - if ((lastRunThread.threadOpts & - J3dThreadData.START_TIMER) != 0) { - lastRunThread.threadOpts = - (J3dThreadData.START_TIMER | - J3dThreadData.WAIT_ALL_THREADS); - - } else { - lastRunThread.threadOpts = - J3dThreadData.WAIT_ALL_THREADS; - } - thread.threadOpts = J3dThreadData.CONT_THREAD; - - } - } else { - if (thread.view != v) { - v = thread.view; - threadToRun = true; - // Although the renderer thread is not - // repeated. We still need to wait all - // previous renderer threads if new View - // start. - if (lastRunThread != null) { - lastRunThread.threadOpts = - (J3dThreadData.STOP_TIMER | - J3dThreadData.WAIT_ALL_THREADS); - ((Object []) lastRunThread.threadArgs)[3] - = lastRunThread.view; - } - thread.threadOpts = (J3dThreadData.START_TIMER | - J3dThreadData.CONT_THREAD); - } else { - thread.threadOpts = J3dThreadData.CONT_THREAD; - } - } - thread.thread.lastWaitTimestamp = waitTimestamp; - thread.needsRun = true; - thread.lastRunTime = currentTime; - lastRunThread = thread; - } else { - thread.needsRun = false; - } - } + while (i<lastStructureUpdateThread) { + thread = threads[i++]; + if ((thread.lastUpdateTime > thread.lastRunTime) && + !thread.thread.userStop) { + lastThread = thread; + thread.needsRun = true; + thread.threadOpts = J3dThreadData.CONT_THREAD; + thread.lastRunTime = currentTime; + } else { + thread.needsRun = false; + } + } + if (lastThread != null) { + lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; + lastThread = null; + } + while (i<size) { + thread = threads[i++]; + if ((thread.lastUpdateTime > thread.lastRunTime) && + !thread.thread.userStop) { + lastThread = thread; + thread.needsRun = true; + thread.threadOpts = J3dThreadData.CONT_THREAD; + thread.lastRunTime = currentTime; + } else { + thread.needsRun = false; + } + } + if (lastThread != null) { + lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; + lastThread = null; + } - if (lastRunThread != null) { - lastRunThread.threadOpts = - (J3dThreadData.STOP_TIMER | - J3dThreadData.WAIT_ALL_THREADS| - J3dThreadData.LAST_STOP_TIMER); - lockGeometry = true; - ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; - } else { - lockGeometry = false; - } - + threads = (J3dThreadData []) renderWorkThreads.toArray(false); + size = renderWorkThreads.arraySize(); + View v; + J3dThreadData lastRunThread = null; + waitTimestamp++; + sleepTime = 0L; + + boolean threadToRun = false; // Not currently used + + // Fix for Issue 12: loop through the list of threads, calling + // computeCycleTime() exactly once per view. This ensures that + // all threads for a given view see consistent values for + // isMinCycleTimeAchieve and sleepTime. + v = null; + for (i=0; i<size; i++) { + thread = threads[i]; + if (thread.view != v) { + thread.view.computeCycleTime(); + // Set sleepTime to the value needed to satify the + // minimum cycle time of the slowest view + if (thread.view.sleepTime > sleepTime) { + sleepTime = thread.view.sleepTime; + } + } + v = thread.view; + } + + v = null; + for (i=0; i<size; i++) { + thread = threads[i]; + if (thread.canvas == null) { // Only for swap thread + ((Object []) thread.threadArgs)[3] = null; + } + if ((thread.lastUpdateTime > thread.lastRunTime) && + !thread.thread.userStop) { + + if (thread.thread.lastWaitTimestamp == waitTimestamp) { + // This renderer thread is repeated. We must wait + // until all previous renderer threads done before + // allowing this thread to continue. Note that + // lastRunThread can't be null in this case. + waitTimestamp++; + if (thread.view != v) { + // A new View is start + v = thread.view; + threadToRun = true; + lastRunThread.threadOpts = + (J3dThreadData.STOP_TIMER | + J3dThreadData.WAIT_ALL_THREADS); + ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; + thread.threadOpts = (J3dThreadData.START_TIMER | + J3dThreadData.CONT_THREAD); + } else { + if ((lastRunThread.threadOpts & + J3dThreadData.START_TIMER) != 0) { + lastRunThread.threadOpts = + (J3dThreadData.START_TIMER | + J3dThreadData.WAIT_ALL_THREADS); + + } else { + lastRunThread.threadOpts = + J3dThreadData.WAIT_ALL_THREADS; + } + thread.threadOpts = J3dThreadData.CONT_THREAD; + + } + } else { + if (thread.view != v) { + v = thread.view; + threadToRun = true; + // Although the renderer thread is not + // repeated. We still need to wait all + // previous renderer threads if new View + // start. + if (lastRunThread != null) { + lastRunThread.threadOpts = + (J3dThreadData.STOP_TIMER | + J3dThreadData.WAIT_ALL_THREADS); + ((Object []) lastRunThread.threadArgs)[3] + = lastRunThread.view; + } + thread.threadOpts = (J3dThreadData.START_TIMER | + J3dThreadData.CONT_THREAD); + } else { + thread.threadOpts = J3dThreadData.CONT_THREAD; + } + } + thread.thread.lastWaitTimestamp = waitTimestamp; + thread.needsRun = true; + thread.lastRunTime = currentTime; + lastRunThread = thread; + } else { + thread.needsRun = false; + } + } + + + if (lastRunThread != null) { + lastRunThread.threadOpts = + (J3dThreadData.STOP_TIMER | + J3dThreadData.WAIT_ALL_THREADS| + J3dThreadData.LAST_STOP_TIMER); + lockGeometry = true; + ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; + } else { + lockGeometry = false; + } + } + + // Issue 275 - go to sleep without holding timeLock // Sleep for the amount of time needed to satisfy the minimum // cycle time for all views. if (sleepTime > 0) { @@ -1873,7 +1647,6 @@ class MasterControl { } // System.err.println("MasterControl: done sleeping"); } - } private void createUpdateThread(J3dStructure structure) { @@ -2162,7 +1935,6 @@ class MasterControl { } rdr.onScreen = null; rdr.offScreen = null; - } // cleanup ThreadData corresponds to the view in renderer @@ -2290,9 +2062,7 @@ class MasterControl { synchronized (VirtualUniverse.mc.deviceScreenMap) { deviceScreenMap.clear(); } - FreeListManager.clearList(FreeListManager.MESSAGE); - FreeListManager.clearList(FreeListManager.BHLEAF); - FreeListManager.clearList(FreeListManager.BHINTERNAL); + mirrorObjects.clear(); // Note: We should not clear the DISPLAYLIST/TEXTURE // list here because other structure may release them @@ -2306,7 +2076,6 @@ class MasterControl { renderOnceList.clear(); timestampUpdateList.clear(); - FreeListManager.clearList(FreeListManager.TRANSFORM3D); defaultRenderMethod = null; text3DRenderMethod = null; vertexArrayRenderMethod = null; @@ -2395,7 +2164,15 @@ class MasterControl { // offScreen canvases will be handled by the // request renderer, so don't add offScreen canvas // the render list - if (!cv.offScreen) { + // + // Issue 131: Automatic offscreen canvases need to + // be added to onscreen list. Special case. + // + // TODO KCR Issue 131: this should probably be + // changed to a list of screens since multiple + // off-screen canvases (either auto or manual) can + // be used by the same renderer + if (!cv.manualRendering) { screen.renderer.onScreen = screen; } else { screen.renderer.offScreen = screen; @@ -2866,7 +2643,8 @@ class MasterControl { for (int k=0; k < canvasList.length; k++) { if (j < canvasList[k].length) { Canvas3D cv = canvasList[k][j]; - if (cv.active && cv.isRunningStatus && !cv.offScreen) { + // Issue 131: setup renderer unless manualRendering + if (cv.active && cv.isRunningStatus && !cv.manualRendering ) { if (cv.screen.renderer == null) { continue; } @@ -2887,7 +2665,8 @@ class MasterControl { Canvas3D cv = canvasList[j][k]; // create swap thread only if there is at // least one active canvas - if (cv.active && cv.isRunningStatus && !cv.offScreen) { + // Issue 131: only if not manualRendering + if (cv.active && cv.isRunningStatus && !cv.manualRendering) { if (cv.screen.renderer == null) { // Should not happen continue; @@ -2988,7 +2767,7 @@ class MasterControl { void sendRenderMessage(GraphicsConfiguration gc, Object arg, Integer mtype) { Renderer rdr = createRenderer(gc); - J3dMessage renderMessage = VirtualUniverse.mc.getMessage(); + J3dMessage renderMessage = new J3dMessage(); renderMessage.threads = J3dThread.RENDER_THREAD; renderMessage.type = J3dMessage.RENDER_IMMEDIATE; renderMessage.universe = null; @@ -3011,12 +2790,16 @@ class MasterControl { // Assert the master control thread is created. J3dDebug.doAssert((mcThread != null), "mcThread != null"); Renderer rdr = createRenderer(c.graphicsConfiguration); - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.RENDER_THREAD; createMessage.type = J3dMessage.DESTROY_CTX_AND_OFFSCREENBUFFER; createMessage.universe = null; createMessage.view = null; createMessage.args[0] = c; + // Fix for issue 340: send display, drawable & ctx in msg + createMessage.args[1] = new Long(c.screen.display); + createMessage.args[2] = c.drawable; + createMessage.args[3] = c.ctx; rdr.rendererStructure.addMessage(createMessage); synchronized (requestObjList) { setWorkForRequestRenderer(); @@ -3051,7 +2834,7 @@ class MasterControl { // Fix for Issue 72 : call createRenderer rather than getting // the renderer from the canvas.screen object Renderer rdr = createRenderer(c.graphicsConfiguration); - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.RENDER_THREAD; createMessage.type = J3dMessage.CREATE_OFFSCREENBUFFER; createMessage.universe = null; @@ -3195,7 +2978,10 @@ class MasterControl { threadListsChanged = true; } } else if (type == START_RENDERER) { - ((Canvas3D) o).isRunningStatus = true; + Canvas3D c3d = (Canvas3D) o; + if (!c3d.isFatalError()) { + c3d.isRunningStatus = true; + } threadListsChanged = true; } else if (type == STOP_RENDERER) { if (o instanceof Canvas3D) { @@ -3225,7 +3011,7 @@ class MasterControl { } rendererRun = true; } else if (type == FREE_DRAWING_SURFACE) { - DrawingSurfaceObjectAWT.freeDrawingSurface(o); + Pipeline.getPipeline().freeDrawingSurfaceNative(o); } else if (type == GETBESTCONFIG) { GraphicsConfiguration gc = ((GraphicsConfiguration []) ((GraphicsConfigTemplate3D) o).testCfg)[0]; @@ -3569,22 +3355,27 @@ class MasterControl { } } break; + case THREAD_DONE: if (state != WAITING_FOR_RENDERER_CLEANUP) { + threadPending--; - if (nthread.type == J3dThread.RENDER_THREAD) { + assert threadPending >= 0 : ("threadPending = " + threadPending); + if (nthread.type == J3dThread.RENDER_THREAD) { View v = (View) nthread.args[3]; if (v != null) { // STOP_TIMER v.stopTime = J3dClock.currentTimeMillis(); } - + if (--renderPending == 0) { renderWaiting = false; } + assert renderPending >= 0 : ("renderPending = " + renderPending); } else { if (--statePending == 0) { stateWaiting = false; } + assert statePending >= 0 : ("statePending = " + statePending); } if (state == WAITING_FOR_CPU || state == WAITING_FOR_THREADS) { notify(); @@ -3594,19 +3385,12 @@ class MasterControl { state = RUNNING; } break; - case WAIT_FOR_ALL: - while (threadPending != 0) { - state = WAITING_FOR_THREADS; - try { - wait(); - } catch (InterruptedException e) { - System.err.println(e); - } - } - break; + case CHECK_FOR_WORK: if (!workToDo) { state = SLEEPING; + // NOTE: this could wakeup spuriously (see issue 279), but it + // will not cause any problems. try { wait(); } catch (InterruptedException e) { @@ -3616,12 +3400,14 @@ class MasterControl { } workToDo = false; break; + case SET_WORK: workToDo = true; if (state == SLEEPING) { notify(); } break; + case SET_WORK_FOR_REQUEST_RENDERER: requestRenderWorkToDo = true; workToDo = true; @@ -3630,45 +3416,29 @@ class MasterControl { notify(); } break; + case RUN_RENDERER_CLEANUP: nthread.runMonitor(J3dThread.RUN, currentTime, rendererCleanupArgs); state = WAITING_FOR_RENDERER_CLEANUP; - try { - wait(); - } catch (InterruptedException e) { - System.err.println(e); - } + // Issue 279 - loop until state is set to running + while (state != RUNNING) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println(e); + } + } break; - case SLEEP: - state = SLEEPING; - try { - wait(sleepTime); - } catch (InterruptedException e) { - System.err.println(e); - } + + default: + // Should never get here + assert false : "missing case in switch statement"; } } // Static initializer static { - /* - // Determine whether the JVM is version JDK1.5 or later. - // XXXX: replace this with code that checks for the existence - // of a class or method that is defined in 1.5, but not in 1.4 - String versionString = - (String) java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - return System.getProperty("java.version"); - } - }); - jvm15OrBetter = !(versionString.startsWith("1.4") || - versionString.startsWith("1.3") || - versionString.startsWith("1.2") || - versionString.startsWith("1.1")); - */ - // create ThreadGroup java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -3828,4 +3598,9 @@ class MasterControl { // even whether) we sleep } } + + // Return the number of available processors + private int getNumberOfProcessors() { + return Runtime.getRuntime().availableProcessors(); + } } diff --git a/src/classes/share/javax/media/j3d/MaterialRetained.java b/src/classes/share/javax/media/j3d/MaterialRetained.java index 06ddef8..4417aaa 100644 --- a/src/classes/share/javax/media/j3d/MaterialRetained.java +++ b/src/classes/share/javax/media/j3d/MaterialRetained.java @@ -409,21 +409,10 @@ class MaterialRetained extends NodeComponentRetained { /** * Updates the native context. */ - native void updateNative(long ctx, - float red, float green, float blue, float alpha, - float ared, float agreen, float ablue, - float ered, float egreen, float eblue, - float dred, float dgreen, float dblue, - float sred, float sgreen, float sblue, - float shininess, int colorTarget, boolean enable); - - /** - * Updates the native context. - */ - void updateNative(long ctx, + void updateNative(Context ctx, float red, float green, float blue, float alpha, boolean enableLighting) { - updateNative(ctx, red, green, blue, alpha, + Pipeline.getPipeline().updateMaterial(ctx, red, green, blue, alpha, ambientColor.x, ambientColor.y, ambientColor.z, emissiveColor.x, emissiveColor.y, emissiveColor.z, diffuseColor.x, diffuseColor.y, diffuseColor.z, @@ -516,7 +505,7 @@ class MaterialRetained extends NodeComponentRetained { ArrayList gaList = Shape3DRetained.getGeomAtomsList(mirror.users, univList); // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.MATERIAL_CHANGED; createMessage.universe = null; @@ -528,7 +517,7 @@ class MaterialRetained extends NodeComponentRetained { int size = univList.size(); for(int i=0; i<size; i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.MATERIAL_CHANGED; diff --git a/src/classes/share/javax/media/j3d/MediaContainerRetained.java b/src/classes/share/javax/media/j3d/MediaContainerRetained.java index e5dda5b..f029fec 100644 --- a/src/classes/share/javax/media/j3d/MediaContainerRetained.java +++ b/src/classes/share/javax/media/j3d/MediaContainerRetained.java @@ -14,10 +14,6 @@ package javax.media.j3d; import java.net.URL; import java.io.InputStream; -import java.net.MalformedURLException; -import java.io.File; -import java.security.*; -import java.io.InputStream; /** * The MediaContainerRetained object defines all rendering state that can @@ -183,7 +179,7 @@ class MediaContainerRetained extends NodeComponentRetained { */ void dispatchMessage() { // Send message including a integer argumentD - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.SOUND_SCHEDULER; createMessage.type = J3dMessage.MEDIA_CONTAINER_CHANGED; createMessage.universe = null; diff --git a/src/classes/share/javax/media/j3d/ModelClipRetained.java b/src/classes/share/javax/media/j3d/ModelClipRetained.java index b1e3365..f76c967 100644 --- a/src/classes/share/javax/media/j3d/ModelClipRetained.java +++ b/src/classes/share/javax/media/j3d/ModelClipRetained.java @@ -577,9 +577,6 @@ class ModelClipRetained extends LeafRetained { * This method and its native counterpart update the native context * model clip planes. */ - native void update(long ctx, int planeNum, boolean enableFlag, - double A, double B, double C, double D); - void update(Canvas3D cv, int enableMask) { cv.setModelViewMatrix(cv.ctx, cv.vworldToEc.mat, @@ -587,10 +584,10 @@ class ModelClipRetained extends LeafRetained { update(cv.ctx, enableMask, getLastLocalToVworld()); } - void update(long ctx, int enableMask, Transform3D trans) { + void update(Context ctx, int enableMask, Transform3D trans) { if (!VirtualUniverse.mc.isD3D()) { for (int i = 0; i < 6; i ++) { - update(ctx, i, ((enableMask & (1 << i)) != 0), + Pipeline.getPipeline().updateModelClip(ctx, i, ((enableMask & (1 << i)) != 0), xformPlanes[i].x, xformPlanes[i].y, xformPlanes[i].z, xformPlanes[i].w); } @@ -613,10 +610,10 @@ class ModelClipRetained extends LeafRetained { xformPlanes[i].z, xformPlanes[i].w); vec.normalize(); invtrans.transform(vec); - update(ctx, i, true, vec.x, vec.y, vec.z, vec.w); + Pipeline.getPipeline().updateModelClip(ctx, i, true, vec.x, vec.y, vec.z, vec.w); } else { - update(ctx, i, false, 0, 0, 0, 0); + Pipeline.getPipeline().updateModelClip(ctx, i, false, 0, 0, 0, 0); } } } @@ -853,7 +850,7 @@ class ModelClipRetained extends LeafRetained { // Initialize the mirror object, this needs to be done, when // renderBin is not accessing any of the fields - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.universe = universe; createMessage.type = J3dMessage.MODELCLIP_CHANGED; @@ -914,7 +911,7 @@ class ModelClipRetained extends LeafRetained { if (scopes.size() > 0) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; createMessage.universe = universe; createMessage.type = J3dMessage.MODELCLIP_CHANGED; @@ -1026,7 +1023,7 @@ class ModelClipRetained extends LeafRetained { } final void sendMessage(int attrMask, Object attr1, Object attr2) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.MODELCLIP_CHANGED; createMessage.universe = universe; diff --git a/src/classes/share/javax/media/j3d/MorphRetained.java b/src/classes/share/javax/media/j3d/MorphRetained.java index a91567e..b063fb2 100644 --- a/src/classes/share/javax/media/j3d/MorphRetained.java +++ b/src/classes/share/javax/media/j3d/MorphRetained.java @@ -138,7 +138,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { if (source.isLive()) { // Notify Geometry Structure to set mirror shape collision // bound and check for collision - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.COLLISION_BOUND_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM; message.universe = universe; @@ -154,7 +154,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { void setBounds(Bounds bounds) { super.setBounds(bounds); if (source.isLive() && !boundsAutoCompute) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.REGION_BOUND_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | targetThreads; @@ -297,7 +297,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { shape.setMorphGeometry(morphedGeometryArray, mirrorShape3D); J3dMessage mChangeMessage = null; - mChangeMessage = VirtualUniverse.mc.getMessage(); + mChangeMessage = new J3dMessage(); mChangeMessage.type = J3dMessage.MORPH_CHANGED; mChangeMessage.threads = (J3dThread.UPDATE_GEOMETRY | J3dThread.UPDATE_TRANSFORM); @@ -377,7 +377,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { else size = 1; J3dMessage[] createMessage = new J3dMessage[size]; - createMessage[0] = VirtualUniverse.mc.getMessage(); + createMessage[0] = new J3dMessage(); createMessage[0].threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT | J3dThread.UPDATE_RENDER; createMessage[0].type = J3dMessage.MORPH_CHANGED; @@ -398,7 +398,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { createMessage[0].args[3] = obj; createMessage[0].args[4] = Shape3DRetained.getGeomAtomsArray(mirrorShape3D); if(visibleIsDirty) { - createMessage[1] = VirtualUniverse.mc.getMessage(); + createMessage[1] = new J3dMessage(); createMessage[1].threads = J3dThread.UPDATE_GEOMETRY; createMessage[1].type = J3dMessage.SHAPE3D_CHANGED; createMessage[1].universe = universe; @@ -431,7 +431,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { if (((Morph)this.source).isLive()) { // Send a message - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT | J3dThread.UPDATE_RENDER;; createMessage.type = J3dMessage.MORPH_CHANGED; @@ -568,7 +568,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { if (source.isLive()) { ((GeometryArrayRetained)morphedGeometryArray.retained).updateData(this); J3dMessage mChangeMessage = null; - mChangeMessage = VirtualUniverse.mc.getMessage(); + mChangeMessage = new J3dMessage(); mChangeMessage.type = J3dMessage.MORPH_CHANGED; mChangeMessage.threads = (J3dThread.UPDATE_GEOMETRY | J3dThread.UPDATE_TRANSFORM); @@ -1447,7 +1447,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { // Need to clone the geometry , if its indexed ... if (refCount == 1 && this.geometryArrays[0] instanceof IndexedGeometryArrayRetained) { - J3dMessage mChangeMessage = VirtualUniverse.mc.getMessage(); + J3dMessage mChangeMessage = new J3dMessage(); mChangeMessage.type = J3dMessage.MORPH_CHANGED; mChangeMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; mChangeMessage.args[0] = this; @@ -1650,7 +1650,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { localBounds = getBounds(); super.setBoundsAutoCompute(autoCompute); if (source.isLive()) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY | @@ -1666,7 +1666,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { void updateBounds() { localBounds = getEffectiveBounds(); if (source.isLive()) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY | diff --git a/src/classes/share/javax/media/j3d/NativeAPIInfo.java b/src/classes/share/javax/media/j3d/NativeAPIInfo.java deleted file mode 100644 index 62b1f69..0000000 --- a/src/classes/share/javax/media/j3d/NativeAPIInfo.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -/* - * Portions of this code were derived from work done by the Blackdown - * group (www.blackdown.org), who did the initial Linux implementation - * of the Java 3D API. - */ - -package javax.media.j3d; - -class NativeAPIInfo { - - /** - * Returns the rendering API being used. - * @return the rendering API, one of: - * <code>MasterControl.RENDER_OPENGL_LINUX</code>, - * <code>MasterControl.RENDER_OPENGL_SOLARIS</code>, - * <code>MasterControl.RENDER_OPENGL_WIN32</code>, - * or <code>MasterControl.RENDER_DIRECT3D</code> - */ - native int getRenderingAPI(); -} diff --git a/src/classes/share/javax/media/j3d/NativeContext.java b/src/classes/share/javax/media/j3d/NativeContext.java new file mode 100644 index 0000000..62a3e0b --- /dev/null +++ b/src/classes/share/javax/media/j3d/NativeContext.java @@ -0,0 +1,31 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Graphics context objects for native rendering pipeline. + */ +class NativeContext implements Context { + + // Native context pointer + private long nativeCtx; + + NativeContext(long nativeCtx) { + this.nativeCtx = nativeCtx; + } + + long getNativeCtx() { + return nativeCtx; + } + +} diff --git a/src/classes/share/javax/media/j3d/NativeDrawable.java b/src/classes/share/javax/media/j3d/NativeDrawable.java new file mode 100644 index 0000000..73fb9d3 --- /dev/null +++ b/src/classes/share/javax/media/j3d/NativeDrawable.java @@ -0,0 +1,32 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Graphics Drawable objects for native rendering pipeline. + */ +class NativeDrawable implements Drawable { + + // Native drawable pointer. On Windows it is the native HDC. + // On X11 it is the handle to the native X11 drawable. + private long nativeDrawable; + + NativeDrawable(long nativeDrawable) { + this.nativeDrawable = nativeDrawable; + } + + long getNativeDrawable() { + return nativeDrawable; + } + +} diff --git a/src/classes/share/javax/media/j3d/NativePipeline.java b/src/classes/share/javax/media/j3d/NativePipeline.java new file mode 100644 index 0000000..1a3288f --- /dev/null +++ b/src/classes/share/javax/media/j3d/NativePipeline.java @@ -0,0 +1,3325 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.io.File; +import java.util.ArrayList; + +/** + * Concrete implementation of Pipeline class for native OGL and D3D rendering + * pipeline. + */ +class NativePipeline extends Pipeline { + + // System properties containing the native library search PATH + // The order listed is the order in which they will be searched + private static final String[] systemPathProps = { + "sun.boot.library.path", + "java.library.path" + }; + + // Prefix for native libraries + private static final String libPrefix = "j3dcore"; + + // Boolean indicating whether we are using D3D or OGL + private boolean isD3D; + + // Renderer name, either "ogl" or "d3d" + private String rendererName; + + // Flags indicating whether the Cg or GLSL libraries are available. + private boolean cgLibraryAvailable = false; + private boolean glslLibraryAvailable = false; + + /** + * The platform dependent template. Since there is no + * template-specific instance data in the NativeConfigTemplate3D + * class, we can create one statically. + */ + private static NativeConfigTemplate3D nativeTemplate = new NativeConfigTemplate3D(); + + /** + * Constructor for singleton NativePipeline instance + */ + protected NativePipeline() { + } + + /** + * Initialize the pipeline + */ + void initialize(Pipeline.Type pipelineType) { + super.initialize(pipelineType); + + // This works around a native load library bug + try { + java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit(); + toolkit = null; // just making sure GC collects this + } catch (java.awt.AWTError e) { + } + + switch (pipelineType) { + case NATIVE_OGL: + isD3D = false; + rendererName = "ogl"; + break; + case NATIVE_D3D: + isD3D = true; + rendererName = "d3d"; + break; + default: + assert false; // Should never get here + } + } + + /** + * Load all of the required libraries + */ + void loadLibraries(int globalShadingLanguage) { + // Load the native JAWT library + loadLibrary("jawt"); + + // Load the native rendering library + String libraryName = libPrefix + "-" + rendererName; + loadLibrary(libraryName); + + // Check whether the Cg library is available + if (globalShadingLanguage == Shader.SHADING_LANGUAGE_CG) { + String cgLibraryName = libPrefix + "-" + rendererName + "-cg"; + String[] libpath = setupLibPath(cgLibraryName); + cgLibraryAvailable = loadNativeCgLibrary(libpath); + } + + // Check whether the GLSL library is available + if (globalShadingLanguage == Shader.SHADING_LANGUAGE_GLSL) { + if (getPipelineType() == Pipeline.Type.NATIVE_OGL) { + // No need to verify that GLSL is available, since GLSL is part + // of OpenGL as an extension (or part of core in 2.0) + glslLibraryAvailable = true; + } + } + } + + /** + * Returns true if the Cg library is loaded and available. Note that this + * does not necessarily mean that Cg is supported by the graphics card. + */ + boolean isCgLibraryAvailable() { + return cgLibraryAvailable; + } + + /** + * Returns true if the GLSL library is loaded and available. Note that this + * does not necessarily mean that GLSL is supported by the graphics card. + */ + boolean isGLSLLibraryAvailable() { + return glslLibraryAvailable; + } + + /** + * Load the specified native library. + */ + private void loadLibrary(String libName) { + final String libraryName = libName; + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + System.loadLibrary(libraryName); + return null; + } + }); + } + + /** + * Parse the specified System properties containing a PATH and return an + * array of Strings, where each element is an absolute filename consisting of + * the individual component of the path concatenated with the (relative) + * library file name. Only those absolute filenames that exist are included. + * If no absolute filename is found, we will try the relative library name. + */ + private String[] setupLibPath(String libName) { + final String libraryName = libName; + return (String[]) + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + ArrayList pathList = new ArrayList(); + + String filename = System.mapLibraryName(libraryName); + for (int n = 0; n < systemPathProps.length; n++) { + String pathString = System.getProperty(systemPathProps[n]); + boolean done = false; + int posStart = 0; + while (!done) { + int posEnd = pathString.indexOf(File.pathSeparator, posStart); + if (posEnd == -1) { + posEnd = pathString.length(); + done = true; + } + String pathDir = pathString.substring(posStart, posEnd); + File pathFile = new File(pathDir, filename); + if (pathFile.exists()) { + pathList.add(pathFile.getAbsolutePath()); + } + + posStart = posEnd + 1; + } + } + + // If no absolute path names exist, add in the relative library name + if (pathList.size() == 0) { + pathList.add(filename); + } + + return (String[])pathList.toArray(new String[0]); + } + }); + } + + // Method to verify whether the native Cg library is available + private native boolean loadNativeCgLibrary(String[] libpath); + + + // + // Methods to box/unbox various native objects + // + + private long unbox(Context ctx) { + if (ctx == null) { + return 0; + } else { + return ((NativeContext)ctx).getNativeCtx(); + } + } + + private Context boxContext(long nativeCtx) { + if (nativeCtx == 0) { + return null; + } else { + return new NativeContext(nativeCtx); + } + } + + private long unbox(Drawable drawable) { + if (drawable == null) { + return 0; + } else { + return ((NativeDrawable)drawable).getNativeDrawable(); + } + } + + private Drawable boxDrawable(long nativeDrawable) { + if (nativeDrawable == 0) { + return null; + } else { + return new NativeDrawable(nativeDrawable); + } + } + + private long unbox(ShaderProgramId shaderProgramId) { + if (shaderProgramId == null) { + return 0; + } else { + return ((NativeShaderObject)shaderProgramId).getNativeId(); + } + } + + private ShaderProgramId boxShaderProgramId(long nativeId) { + if (nativeId == 0) { + return null; + } else { + return new NativeShaderObject(nativeId); + } + } + + private long unbox(ShaderId shaderId) { + if (shaderId == null) { + return 0; + } else { + return ((NativeShaderObject)shaderId).getNativeId(); + } + } + + private ShaderId boxShaderId(long nativeId) { + if (nativeId == 0) { + return null; + } else { + return new NativeShaderObject(nativeId); + } + } + + private long unbox(ShaderAttrLoc attrLoc) { + if (attrLoc == null) { + return -1; + } else { + return ((NativeShaderObject)attrLoc).getNativeId(); + } + } + + private ShaderAttrLoc boxShaderAttrLoc(long nativeId) { + if (nativeId == -1) { + return null; + } else { + return new NativeShaderObject(nativeId); + } + } + + // --------------------------------------------------------------------- + + // + // GeometryArrayRetained methods + // + + // Used by D3D to free vertex buffer + native void freeD3DArray(GeometryArrayRetained geo, boolean deleteVB); + + // used for GeometryArrays by Copy or interleaved + native void execute(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + int vertexAttrCount, int[] vertexAttrSizes, + float[] varray, float[] cdata, int cdirty); + + void execute(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + int vertexAttrCount, int[] vertexAttrSizes, + float[] varray, float[] cdata, int cdirty) { + execute(unbox(ctx), + geo, geo_type, + isNonUniformScale, + useAlpha, + ignoreVertexColors, + startVIndex, vcount, vformat, + texCoordSetCount, texCoordSetMap, + texCoordSetMapLen, + texCoordSetOffset, + numActiveTexUnitState, + vertexAttrCount, vertexAttrSizes, + varray, cdata, cdirty); + } + + // used by GeometryArray by Reference with java arrays + native void executeVA(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty); + + void executeVA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty) { + executeVA(unbox(ctx), + geo, geo_type, + isNonUniformScale, + ignoreVertexColors, + vcount, + vformat, + vdefined, + coordIndex, vfcoords, vdcoords, + colorIndex, cfdata, cbdata, + normalIndex, ndata, + vertexAttrCount, vertexAttrSizes, + vertexAttrIndex, vertexAttrData, + texcoordmaplength, + texcoordoffset, + numActiveTexUnitState, + texIndex, texstride, texCoords, + cdirty); + } + + // used by GeometryArray by Reference with NIO buffer + native void executeVABuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, + Object vcoords, + int colorIndex, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + int normalIndex, Object ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, Object[] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty); + + void executeVABuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, + Object vcoords, + int colorIndex, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + int normalIndex, Object ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, Object[] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty) { + executeVABuffer(unbox(ctx), + geo, geo_type, + isNonUniformScale, + ignoreVertexColors, + vcount, + vformat, + vdefined, + coordIndex, + vcoords, + colorIndex, + cdataBuffer, + cfdata, cbdata, + normalIndex, ndata, + vertexAttrCount, vertexAttrSizes, + vertexAttrIndex, vertexAttrData, + texcoordmaplength, + texcoordoffset, + numActiveTexUnitState, + texIndex, texstride, texCoords, + cdirty); + } + + // used by GeometryArray by Reference in interleaved format with NIO buffer + native void executeInterleavedBuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object varray, float[] cdata, int cdirty); + + void executeInterleavedBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object varray, float[] cdata, int cdirty) { + executeInterleavedBuffer(unbox(ctx), + geo, geo_type, + isNonUniformScale, + useAlpha, + ignoreVertexColors, + startVIndex, vcount, vformat, + texCoordSetCount, texCoordSetMap, + texCoordSetMapLen, + texCoordSetOffset, + numActiveTexUnitState, + varray, cdata, cdirty); + } + + native void setVertexFormat(long ctx, GeometryArrayRetained geo, + int vformat, boolean useAlpha, boolean ignoreVertexColors); + + void setVertexFormat(Context ctx, GeometryArrayRetained geo, + int vformat, boolean useAlpha, boolean ignoreVertexColors) { + setVertexFormat(unbox(ctx), geo, + vformat, useAlpha, ignoreVertexColors); + } + + native void disableGlobalAlpha(long ctx, GeometryArrayRetained geo, int vformat, + boolean useAlpha, boolean ignoreVertexColors); + + void disableGlobalAlpha(Context ctx, GeometryArrayRetained geo, int vformat, + boolean useAlpha, boolean ignoreVertexColors) { + disableGlobalAlpha(unbox(ctx), geo, vformat, + useAlpha, ignoreVertexColors); + } + + // used for GeometryArrays + native void buildGA(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int startVIndex, + int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, int[] texCoordSetMapOffset, + int vertexAttrCount, int[] vertexAttrSizes, + double[] xform, double[] nxform, + float[] varray); + + void buildGA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int startVIndex, + int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, int[] texCoordSetMapOffset, + int vertexAttrCount, int[] vertexAttrSizes, + double[] xform, double[] nxform, + float[] varray) { + buildGA(unbox(ctx), + geo, geo_type, + isNonUniformScale, updateAlpha, + alpha, + ignoreVertexColors, + startVIndex, + vcount, vformat, + texCoordSetCount, texCoordSetMap, + texCoordSetMapLen, texCoordSetMapOffset, + vertexAttrCount, vertexAttrSizes, + xform, nxform, + varray); + } + + // used to Build Dlist GeometryArray by Reference with java arrays + native void buildGAForByRef(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int[] texIndex, int texstride, Object[] texCoords, + double[] xform, double[] nxform); + + void buildGAForByRef(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int[] texIndex, int texstride, Object[] texCoords, + double[] xform, double[] nxform) { + buildGAForByRef(unbox(ctx), + geo, geo_type, + isNonUniformScale, updateAlpha, + alpha, + ignoreVertexColors, + vcount, + vformat, + vdefined, + coordIndex, vfcoords, vdcoords, + colorIndex, cfdata, cbdata, + normalIndex, ndata, + vertexAttrCount, vertexAttrSizes, + vertexAttrIndex, vertexAttrData, + texcoordmaplength, + texcoordoffset, + texIndex, texstride, texCoords, + xform, nxform); + } + + // --------------------------------------------------------------------- + + // + // IndexedGeometryArrayRetained methods + // + + // by-copy or interleaved, by reference, Java arrays + native void executeIndexedGeometry(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + float[] varray, float[] cdata, + int cdirty, + int[] indexCoord); + + void executeIndexedGeometry(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + float[] varray, float[] cdata, + int cdirty, + int[] indexCoord) { + executeIndexedGeometry(unbox(ctx), + geo, geo_type, + isNonUniformScale, + useAlpha, + ignoreVertexColors, + initialIndexIndex, + indexCount, + vertexCount, vformat, + vertexAttrCount, vertexAttrSizes, + texCoordSetCount, texCoordSetMap, + texCoordSetMapLen, + texCoordSetOffset, + numActiveTexUnitState, + varray, cdata, + cdirty, + indexCoord); + } + + // interleaved, by reference, nio buffer + native void executeIndexedGeometryBuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object varray, float[] cdata, + int cdirty, + int[] indexCoord); + + void executeIndexedGeometryBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object varray, float[] cdata, + int cdirty, + int[] indexCoord) { + executeIndexedGeometryBuffer(unbox(ctx), + geo, geo_type, + isNonUniformScale, + useAlpha, + ignoreVertexColors, + initialIndexIndex, + indexCount, + vertexCount, vformat, + texCoordSetCount, texCoordSetMap, + texCoordSetMapLen, + texCoordSetOffset, + numActiveTexUnitState, + varray, cdata, + cdirty, + indexCoord); + } + + // non interleaved, by reference, Java arrays + native void executeIndexedGeometryVA(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + float[] vfcoords, double[] vdcoords, + float[] cfdata, byte[] cbdata, + float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord); + + void executeIndexedGeometryVA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + float[] vfcoords, double[] vdcoords, + float[] cfdata, byte[] cbdata, + float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord) { + executeIndexedGeometryVA(unbox(ctx), + geo, geo_type, + isNonUniformScale, + ignoreVertexColors, + initialIndexIndex, + validIndexCount, + vertexCount, + vformat, + vdefined, + vfcoords, vdcoords, + cfdata, cbdata, + ndata, + vertexAttrCount, vertexAttrSizes, + vertexAttrData, + texcoordmaplength, + texcoordoffset, + numActiveTexUnitState, + texstride, texCoords, + cdirty, + indexCoord); + } + + // non interleaved, by reference, nio buffer + native void executeIndexedGeometryVABuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + Object vcoords, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + Object normal, + int vertexAttrCount, int[] vertexAttrSizes, + Object[] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord); + + void executeIndexedGeometryVABuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + Object vcoords, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + Object normal, + int vertexAttrCount, int[] vertexAttrSizes, + Object[] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord) { + executeIndexedGeometryVABuffer(unbox(ctx), + geo, geo_type, + isNonUniformScale, + ignoreVertexColors, + initialIndexIndex, + validIndexCount, + vertexCount, + vformat, + vdefined, + vcoords, + cdataBuffer, + cfdata, cbdata, + normal, + vertexAttrCount, vertexAttrSizes, + vertexAttrData, + texcoordmaplength, + texcoordoffset, + numActiveTexUnitState, + texstride, texCoords, + cdirty, + indexCoord); + } + + // by-copy geometry + native void buildIndexedGeometry(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetMapOffset, + double[] xform, double[] nxform, + float[] varray, int[] indexCoord); + + void buildIndexedGeometry(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetMapOffset, + double[] xform, double[] nxform, + float[] varray, int[] indexCoord) { + buildIndexedGeometry(unbox(ctx), + geo, geo_type, + isNonUniformScale, updateAlpha, + alpha, + ignoreVertexColors, + initialIndexIndex, + validIndexCount, + vertexCount, + vformat, + vertexAttrCount, vertexAttrSizes, + texCoordSetCount, texCoordSetMap, + texCoordSetMapLen, + texCoordSetMapOffset, + xform, nxform, + varray, indexCoord); + } + + + // --------------------------------------------------------------------- + + // + // GraphicsContext3D methods + // + + native void readRaster(long ctx, + int type, int xSrcOffset, int ySrcOffset, + int width, int height, int hCanvas, + int imageDataType, + int imageFormat, + Object imageBuffer, + int depthFormat, + Object depthBuffer); + + void readRaster(Context ctx, + int type, int xSrcOffset, int ySrcOffset, + int width, int height, int hCanvas, + int imageDataType, + int imageFormat, + Object imageBuffer, + int depthFormat, + Object depthBuffer) { + readRaster(unbox(ctx), + type, xSrcOffset, ySrcOffset, + width, height, hCanvas, + imageDataType, + imageFormat, imageBuffer, + depthFormat, depthBuffer); + } + + // --------------------------------------------------------------------- + + // + // CgShaderProgramRetained methods + // + + // ShaderAttributeValue methods + + native ShaderError setCgUniform1i(long ctx, + long shaderProgramId, + long uniformLocation, + int value); + + ShaderError setCgUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value) { + return setCgUniform1i(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniform1f(long ctx, + long shaderProgramId, + long uniformLocation, + float value); + + ShaderError setCgUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value) { + return setCgUniform1f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniform2i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + ShaderError setCgUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return setCgUniform2i(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniform2f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setCgUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setCgUniform2f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniform3i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + ShaderError setCgUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return setCgUniform3i(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniform3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setCgUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setCgUniform3f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniform4i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + ShaderError setCgUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return setCgUniform4i(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniform4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setCgUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setCgUniform4f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniformMatrix3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setCgUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setCgUniformMatrix3f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setCgUniformMatrix4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setCgUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setCgUniformMatrix4f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + // ShaderAttributeArray methods + + native ShaderError setCgUniform1iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + ShaderError setCgUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return setCgUniform1iArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniform1fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setCgUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setCgUniform1fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniform2iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + ShaderError setCgUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return setCgUniform2iArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniform2fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setCgUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setCgUniform2fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniform3iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + ShaderError setCgUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return setCgUniform3iArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniform3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setCgUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setCgUniform3fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniform4iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + ShaderError setCgUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return setCgUniform4iArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniform4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setCgUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setCgUniform4fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniformMatrix3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setCgUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setCgUniformMatrix3fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setCgUniformMatrix4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setCgUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setCgUniformMatrix4fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + // Native interfaces for shader compilation, etc. + native ShaderError createCgShader(long ctx, int shaderType, long[] shaderId); + + ShaderError createCgShader(Context ctx, int shaderType, ShaderId[] shaderId) { + long[] nativeId = new long[1]; + ShaderError err = createCgShader(unbox(ctx), shaderType, nativeId); + shaderId[0] = boxShaderId(nativeId[0]); + return err; + } + + native ShaderError destroyCgShader(long ctx, long shaderId); + + ShaderError destroyCgShader(Context ctx, ShaderId shaderId) { + return destroyCgShader(unbox(ctx), unbox(shaderId)); + } + + native ShaderError compileCgShader(long ctx, long shaderId, String program); + + ShaderError compileCgShader(Context ctx, ShaderId shaderId, String program) { + return compileCgShader(unbox(ctx), unbox(shaderId), program); + } + + native ShaderError createCgShaderProgram(long ctx, long[] shaderProgramId); + + ShaderError createCgShaderProgram(Context ctx, ShaderProgramId[] shaderProgramId) { + long[] nativeId = new long[1]; + ShaderError err = createCgShaderProgram(unbox(ctx), nativeId); + shaderProgramId[0] = boxShaderProgramId(nativeId[0]); + return err; + } + + native ShaderError destroyCgShaderProgram(long ctx, long shaderProgramId); + + ShaderError destroyCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return destroyCgShaderProgram(unbox(ctx), unbox(shaderProgramId)); + } + + native ShaderError linkCgShaderProgram(long ctx, long shaderProgramId, + long[] shaderIds); + + ShaderError linkCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId, + ShaderId[] shaderIds) { + + assert shaderIds != null; + long[] nativeIds = new long[shaderIds.length]; + for (int i = 0; i < shaderIds.length; i++) { + nativeIds[i] = unbox(shaderIds[i]); + } + return linkCgShaderProgram(unbox(ctx), unbox(shaderProgramId), + nativeIds); + } + + native void lookupCgVertexAttrNames(long ctx, long shaderProgramId, + int numAttrNames, String[] attrNames, boolean[] errArr); + + void lookupCgVertexAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, boolean[] errArr) { + lookupCgVertexAttrNames(unbox(ctx), unbox(shaderProgramId), + numAttrNames, attrNames, errArr); + } + + native void lookupCgShaderAttrNames(long ctx, long shaderProgramId, + int numAttrNames, String[] attrNames, long[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr); + + void lookupCgShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, ShaderAttrLoc[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr) { + + assert numAttrNames == locArr.length; + long[] nativeLocArr = new long[numAttrNames]; + for (int i = 0; i < numAttrNames; i++) { + // Initialize to invalid native location + nativeLocArr[i] = -1; + } + lookupCgShaderAttrNames(unbox(ctx), unbox(shaderProgramId), + numAttrNames, attrNames, nativeLocArr, + typeArr, sizeArr, isArrayArr); + for (int i = 0; i < numAttrNames; i++) { + locArr[i] = boxShaderAttrLoc(nativeLocArr[i]); + } + } + + native ShaderError useCgShaderProgram(long ctx, long shaderProgramId); + + ShaderError useCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return useCgShaderProgram(unbox(ctx), unbox(shaderProgramId)); + } + + // --------------------------------------------------------------------- + + // + // GLSLShaderProgramRetained methods + // + + // ShaderAttributeValue methods + + native ShaderError setGLSLUniform1i(long ctx, + long shaderProgramId, + long uniformLocation, + int value); + + ShaderError setGLSLUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value) { + return setGLSLUniform1i(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniform1f(long ctx, + long shaderProgramId, + long uniformLocation, + float value); + + ShaderError setGLSLUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value) { + return setGLSLUniform1f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniform2i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + ShaderError setGLSLUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return setGLSLUniform2i(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniform2f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setGLSLUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setGLSLUniform2f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniform3i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + ShaderError setGLSLUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return setGLSLUniform3i(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniform3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setGLSLUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setGLSLUniform3f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniform4i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + ShaderError setGLSLUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return setGLSLUniform4i(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniform4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setGLSLUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setGLSLUniform4f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniformMatrix3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setGLSLUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setGLSLUniformMatrix3f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + native ShaderError setGLSLUniformMatrix4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + ShaderError setGLSLUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return setGLSLUniformMatrix4f(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + value); + } + + // ShaderAttributeArray methods + + native ShaderError setGLSLUniform1iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + ShaderError setGLSLUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return setGLSLUniform1iArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniform1fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setGLSLUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setGLSLUniform1fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniform2iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + ShaderError setGLSLUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return setGLSLUniform2iArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniform2fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setGLSLUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setGLSLUniform2fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniform3iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + ShaderError setGLSLUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return setGLSLUniform3iArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniform3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setGLSLUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setGLSLUniform3fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniform4iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + ShaderError setGLSLUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return setGLSLUniform4iArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniform4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setGLSLUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setGLSLUniform4fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniformMatrix3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setGLSLUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setGLSLUniformMatrix3fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + native ShaderError setGLSLUniformMatrix4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + ShaderError setGLSLUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return setGLSLUniformMatrix4fArray(unbox(ctx), + unbox(shaderProgramId), + unbox(uniformLocation), + numElements, + value); + } + + // native interfaces for shader compilation, etc. + native ShaderError createGLSLShader(long ctx, int shaderType, long[] shaderId); + + ShaderError createGLSLShader(Context ctx, int shaderType, ShaderId[] shaderId) { + long[] nativeId = new long[1]; + ShaderError err = createGLSLShader(unbox(ctx), shaderType, nativeId); + shaderId[0] = boxShaderId(nativeId[0]); + return err; + } + native ShaderError destroyGLSLShader(long ctx, long shaderId); + + ShaderError destroyGLSLShader(Context ctx, ShaderId shaderId) { + return destroyGLSLShader(unbox(ctx), unbox(shaderId)); + } + native ShaderError compileGLSLShader(long ctx, long shaderId, String program); + + ShaderError compileGLSLShader(Context ctx, ShaderId shaderId, String program) { + return compileGLSLShader(unbox(ctx), unbox(shaderId), program); + } + + native ShaderError createGLSLShaderProgram(long ctx, long[] shaderProgramId); + + ShaderError createGLSLShaderProgram(Context ctx, ShaderProgramId[] shaderProgramId) { + long[] nativeId = new long[1]; + ShaderError err = createGLSLShaderProgram(unbox(ctx), nativeId); + shaderProgramId[0] = boxShaderProgramId(nativeId[0]); + return err; + } + native ShaderError destroyGLSLShaderProgram(long ctx, long shaderProgramId); + + ShaderError destroyGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return destroyGLSLShaderProgram(unbox(ctx), unbox(shaderProgramId)); + } + native ShaderError linkGLSLShaderProgram(long ctx, long shaderProgramId, + long[] shaderId); + + ShaderError linkGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId, + ShaderId[] shaderIds) { + assert shaderIds != null; + long[] nativeIds = new long[shaderIds.length]; + for (int i = 0; i < shaderIds.length; i++) { + nativeIds[i] = unbox(shaderIds[i]); + } + return linkGLSLShaderProgram(unbox(ctx), unbox(shaderProgramId), + nativeIds); + } + native ShaderError bindGLSLVertexAttrName(long ctx, long shaderProgramId, + String attrName, int attrIndex); + + ShaderError bindGLSLVertexAttrName(Context ctx, ShaderProgramId shaderProgramId, + String attrName, int attrIndex) { + return bindGLSLVertexAttrName(unbox(ctx), unbox(shaderProgramId), + attrName, attrIndex); + } + native void lookupGLSLShaderAttrNames(long ctx, long shaderProgramId, + int numAttrNames, String[] attrNames, long[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr); + + void lookupGLSLShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, ShaderAttrLoc[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr) { + + assert numAttrNames == locArr.length; + long[] nativeLocArr = new long[numAttrNames]; + for (int i = 0; i < numAttrNames; i++) { + // Initialize to invalid native location + nativeLocArr[i] = -1; + } + lookupGLSLShaderAttrNames(unbox(ctx), unbox(shaderProgramId), + numAttrNames, attrNames, nativeLocArr, + typeArr, sizeArr, isArrayArr); + for (int i = 0; i < numAttrNames; i++) { + locArr[i] = boxShaderAttrLoc(nativeLocArr[i]); + } + } + + native ShaderError useGLSLShaderProgram(long ctx, long shaderProgramId); + + ShaderError useGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return useGLSLShaderProgram(unbox(ctx), unbox(shaderProgramId)); + } + + + // --------------------------------------------------------------------- + + // + // ImageComponent2DRetained methods + // + + // free d3d surface referred to by id + native void freeD3DSurface(ImageComponent2DRetained image, int hashId); + + + // --------------------------------------------------------------------- + + // + // Renderer methods + // + + native void cleanupRenderer(); + + + // --------------------------------------------------------------------- + + // + // ColoringAttributesRetained methods + // + + native void updateColoringAttributes(long ctx, + float dRed, float dGreen, float dBlue, + float red, float green, float blue, + float alpha, + boolean lEnable, + int shadeModel); + + void updateColoringAttributes(Context ctx, + float dRed, float dGreen, float dBlue, + float red, float green, float blue, + float alpha, + boolean lEnable, + int shadeModel) { + updateColoringAttributes(unbox(ctx), + dRed, dGreen, dBlue, + red, green, blue, + alpha, + lEnable, + shadeModel); + } + + + // --------------------------------------------------------------------- + + // + // DirectionalLightRetained methods + // + + native void updateDirectionalLight(long ctx, + int lightSlot, float red, float green, + float blue, float x, float y, float z); + + void updateDirectionalLight(Context ctx, + int lightSlot, float red, float green, + float blue, float x, float y, float z) { + updateDirectionalLight(unbox(ctx), + lightSlot, red, green, + blue, x, y, z); + } + + + // --------------------------------------------------------------------- + + // + // PointLightRetained methods + // + + native void updatePointLight(long ctx, + int lightSlot, float red, float green, + float blue, float ax, float ay, float az, + float px, float py, float pz); + + void updatePointLight(Context ctx, + int lightSlot, float red, float green, + float blue, float ax, float ay, float az, + float px, float py, float pz) { + updatePointLight(unbox(ctx), + lightSlot, red, green, + blue, ax, ay, az, + px, py, pz); + } + + + // --------------------------------------------------------------------- + + // + // SpotLightRetained methods + // + + native void updateSpotLight(long ctx, + int lightSlot, float red, float green, + float blue, float ax, float ay, float az, + float px, float py, float pz, float spreadAngle, + float concentration, float dx, float dy, + float dz); + + void updateSpotLight(Context ctx, + int lightSlot, float red, float green, + float blue, float ax, float ay, float az, + float px, float py, float pz, float spreadAngle, + float concentration, float dx, float dy, + float dz) { + updateSpotLight(unbox(ctx), + lightSlot, red, green, + blue, ax, ay, az, + px, py, pz, spreadAngle, + concentration, dx, dy, + dz); + } + + + // --------------------------------------------------------------------- + + // + // ExponentialFogRetained methods + // + + native void updateExponentialFog(long ctx, + float red, float green, float blue, + float density); + + void updateExponentialFog(Context ctx, + float red, float green, float blue, + float density) { + updateExponentialFog(unbox(ctx), + red, green, blue, + density); + } + + + // --------------------------------------------------------------------- + + // + // LinearFogRetained methods + // + + native void updateLinearFog(long ctx, + float red, float green, float blue, + double fdist, double bdist); + + void updateLinearFog(Context ctx, + float red, float green, float blue, + double fdist, double bdist) { + updateLinearFog(unbox(ctx), + red, green, blue, + fdist, bdist); + } + + + // --------------------------------------------------------------------- + + // + // LineAttributesRetained methods + // + + native void updateLineAttributes(long ctx, + float lineWidth, int linePattern, + int linePatternMask, + int linePatternScaleFactor, + boolean lineAntialiasing); + + void updateLineAttributes(Context ctx, + float lineWidth, int linePattern, + int linePatternMask, + int linePatternScaleFactor, + boolean lineAntialiasing) { + updateLineAttributes(unbox(ctx), + lineWidth, linePattern, + linePatternMask, + linePatternScaleFactor, + lineAntialiasing); + } + + + // --------------------------------------------------------------------- + + // + // MaterialRetained methods + // + + native void updateMaterial(long ctx, + float red, float green, float blue, float alpha, + float ared, float agreen, float ablue, + float ered, float egreen, float eblue, + float dred, float dgreen, float dblue, + float sred, float sgreen, float sblue, + float shininess, int colorTarget, boolean enable); + + void updateMaterial(Context ctx, + float red, float green, float blue, float alpha, + float ared, float agreen, float ablue, + float ered, float egreen, float eblue, + float dred, float dgreen, float dblue, + float sred, float sgreen, float sblue, + float shininess, int colorTarget, boolean enable) { + updateMaterial(unbox(ctx), + red, green, blue, alpha, + ared, agreen, ablue, + ered, egreen, eblue, + dred, dgreen, dblue, + sred, sgreen, sblue, + shininess, colorTarget, enable); + } + + + // --------------------------------------------------------------------- + + // + // ModelClipRetained methods + // + + native void updateModelClip(long ctx, int planeNum, boolean enableFlag, + double A, double B, double C, double D); + + void updateModelClip(Context ctx, int planeNum, boolean enableFlag, + double A, double B, double C, double D) { + updateModelClip(unbox(ctx), planeNum, enableFlag, + A, B, C, D); + } + + + // --------------------------------------------------------------------- + + // + // PointAttributesRetained methods + // + + native void updatePointAttributes(long ctx, float pointSize, boolean pointAntialiasing); + + void updatePointAttributes(Context ctx, float pointSize, boolean pointAntialiasing) { + updatePointAttributes(unbox(ctx), pointSize, pointAntialiasing); + } + + + // --------------------------------------------------------------------- + + // + // PolygonAttributesRetained methods + // + + native void updatePolygonAttributes(long ctx, + int polygonMode, int cullFace, + boolean backFaceNormalFlip, + float polygonOffset, + float polygonOffsetFactor); + + void updatePolygonAttributes(Context ctx, + int polygonMode, int cullFace, + boolean backFaceNormalFlip, + float polygonOffset, + float polygonOffsetFactor) { + updatePolygonAttributes(unbox(ctx), + polygonMode, cullFace, + backFaceNormalFlip, + polygonOffset, + polygonOffsetFactor); + } + + + // --------------------------------------------------------------------- + + // + // RenderingAttributesRetained methods + // + + // TODO : Need to handle stencil operation on the native side -- Chien + native void updateRenderingAttributes(long ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride, + boolean depthBufferEnable, + boolean depthBufferWriteEnable, + int depthTestFunction, + float alphaTestValue, int alphaTestFunction, + boolean ignoreVertexColors, + boolean rasterOpEnable, int rasterOp, + boolean userStencilAvailable, boolean stencilEnable, + int stencilFailOp, int stencilZFailOp, int stencilZPassOp, + int stencilFunction, int stencilReferenceValue, + int stencilCompareMask, int stencilWriteMask ); + + void updateRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride, + boolean depthBufferEnable, + boolean depthBufferWriteEnable, + int depthTestFunction, + float alphaTestValue, int alphaTestFunction, + boolean ignoreVertexColors, + boolean rasterOpEnable, int rasterOp, + boolean userStencilAvailable, boolean stencilEnable, + int stencilFailOp, int stencilZFailOp, int stencilZPassOp, + int stencilFunction, int stencilReferenceValue, + int stencilCompareMask, int stencilWriteMask ) { + updateRenderingAttributes(unbox(ctx), + depthBufferWriteEnableOverride, + depthBufferEnableOverride, + depthBufferEnable, + depthBufferWriteEnable, + depthTestFunction, + alphaTestValue, alphaTestFunction, + ignoreVertexColors, + rasterOpEnable, rasterOp, + userStencilAvailable, stencilEnable, + stencilFailOp, stencilZFailOp, stencilZPassOp, + stencilFunction, stencilReferenceValue, + stencilCompareMask, stencilWriteMask ); + } + + + // --------------------------------------------------------------------- + + // + // TexCoordGenerationRetained methods + // + + /** + * This method updates the native context: + * trans contains eyeTovworld transform in d3d + * trans contains vworldToEye transform in ogl + */ + native void updateTexCoordGeneration(long ctx, + boolean enable, int genMode, int format, + float planeSx, float planeSy, float planeSz, float planeSw, + float planeTx, float planeTy, float planeTz, float planeTw, + float planeRx, float planeRy, float planeRz, float planeRw, + float planeQx, float planeQy, float planeQz, float planeQw, + double[] trans); + + void updateTexCoordGeneration(Context ctx, + boolean enable, int genMode, int format, + float planeSx, float planeSy, float planeSz, float planeSw, + float planeTx, float planeTy, float planeTz, float planeTw, + float planeRx, float planeRy, float planeRz, float planeRw, + float planeQx, float planeQy, float planeQz, float planeQw, + double[] trans) { + updateTexCoordGeneration(unbox(ctx), + enable, genMode, format, + planeSx, planeSy, planeSz, planeSw, + planeTx, planeTy, planeTz, planeTw, + planeRx, planeRy, planeRz, planeRw, + planeQx, planeQy, planeQz, planeQw, + trans); + } + + + // --------------------------------------------------------------------- + + // + // TransparencyAttributesRetained methods + // + + native void updateTransparencyAttributes(long ctx, + float alpha, int geometryType, + int polygonMode, + boolean lineAA, boolean pointAA, + int transparencyMode, + int srcBlendFunction, + int dstBlendFunction); + + void updateTransparencyAttributes(Context ctx, + float alpha, int geometryType, + int polygonMode, + boolean lineAA, boolean pointAA, + int transparencyMode, + int srcBlendFunction, + int dstBlendFunction) { + updateTransparencyAttributes(unbox(ctx), + alpha, geometryType, + polygonMode, + lineAA, pointAA, + transparencyMode, + srcBlendFunction, + dstBlendFunction); + } + + + // --------------------------------------------------------------------- + + // + // TextureAttributesRetained methods + // + + native void updateTextureAttributes(long ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, float red, + float green, float blue, float alpha, + int textureFormat); + + void updateTextureAttributes(Context ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, float red, + float green, float blue, float alpha, + int textureFormat) { + updateTextureAttributes(unbox(ctx), + transform, isIdentity, textureMode, + perspCorrectionMode, red, + green, blue, alpha, + textureFormat); + } + + native void updateRegisterCombiners(long ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, float red, + float green, float blue, float alpha, + int textureFormat, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale); + + void updateRegisterCombiners(Context ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, float red, + float green, float blue, float alpha, + int textureFormat, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale) { + updateRegisterCombiners(unbox(ctx), + transform, isIdentity, textureMode, + perspCorrectionMode, red, + green, blue, alpha, + textureFormat, + combineRgbMode, combineAlphaMode, + combineRgbSrc, combineAlphaSrc, + combineRgbFcn, combineAlphaFcn, + combineRgbScale, combineAlphaScale); + } + + native void updateTextureColorTable(long ctx, int numComponents, + int colorTableSize, + int[] colorTable); + + void updateTextureColorTable(Context ctx, int numComponents, + int colorTableSize, + int[] colorTable) { + updateTextureColorTable(unbox(ctx), numComponents, + colorTableSize, + colorTable); + } + + native void updateCombiner(long ctx, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale); + + void updateCombiner(Context ctx, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale) { + updateCombiner(unbox(ctx), + combineRgbMode, combineAlphaMode, + combineRgbSrc, combineAlphaSrc, + combineRgbFcn, combineAlphaFcn, + combineRgbScale, combineAlphaScale); + } + + + // --------------------------------------------------------------------- + + // + // TextureUnitStateRetained methods + // + + native void updateTextureUnitState(long ctx, int unitIndex, boolean enableFlag); + + void updateTextureUnitState(Context ctx, int unitIndex, boolean enableFlag) { + updateTextureUnitState(unbox(ctx), unitIndex, enableFlag); + } + + + // --------------------------------------------------------------------- + + // + // TextureRetained methods + // Texture2DRetained methods + // + + native void bindTexture2D(long ctx, int objectId, boolean enable); + + void bindTexture2D(Context ctx, int objectId, boolean enable) { + bindTexture2D(unbox(ctx), objectId, enable); + } + + native void updateTexture2DImage(long ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object data); + + void updateTexture2DImage(Context ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object data) { + updateTexture2DImage(unbox(ctx), + numLevels, level, + textureFormat, imageFormat, + width, height, + boundaryWidth, + imageDataType, data); + } + + native void updateTexture2DSubImage(long ctx, + int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object data); + + void updateTexture2DSubImage(Context ctx, + int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object data) { + updateTexture2DSubImage(unbox(ctx), + level, xoffset, yoffset, + textureFormat, imageFormat, + imgXOffset, imgYOffset, + tilew, width, height, + imageDataType, data); + } + + native void updateTexture2DLodRange(long ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod); + + void updateTexture2DLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + updateTexture2DLodRange(unbox(ctx), + baseLevel, maximumLevel, + minimumLod, maximumLod); + } + + native void updateTexture2DLodOffset(long ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ); + + void updateTexture2DLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + updateTexture2DLodOffset(unbox(ctx), + lodOffsetX, lodOffsetY, + lodOffsetZ); + } + + native void updateTexture2DBoundary(long ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha); + + void updateTexture2DBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha) { + updateTexture2DBoundary(unbox(ctx), + boundaryModeS, boundaryModeT, + boundaryRed, boundaryGreen, + boundaryBlue, boundaryAlpha); + } + + native void updateTexture2DFilterModes(long ctx, + int minFilter, int magFilter); + + void updateTexture2DFilterModes(Context ctx, + int minFilter, int magFilter) { + updateTexture2DFilterModes(unbox(ctx), + minFilter, magFilter); + } + + native void updateTexture2DSharpenFunc(long ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts); + + void updateTexture2DSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + updateTexture2DSharpenFunc(unbox(ctx), + numSharpenTextureFuncPts, + sharpenTextureFuncPts); + } + + native void updateTexture2DFilter4Func(long ctx, + int numFilter4FuncPts, + float[] filter4FuncPts); + + void updateTexture2DFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + updateTexture2DFilter4Func(unbox(ctx), + numFilter4FuncPts, + filter4FuncPts); + } + + native void updateTexture2DAnisotropicFilter(long ctx, float degree); + + void updateTexture2DAnisotropicFilter(Context ctx, float degree) { + updateTexture2DAnisotropicFilter(unbox(ctx), degree); + } + + + // --------------------------------------------------------------------- + + // + // Texture3DRetained methods + // + + native void bindTexture3D(long ctx, int objectId, boolean enable); + + void bindTexture3D(Context ctx, int objectId, boolean enable) { + bindTexture3D(unbox(ctx), objectId, enable); + } + + native void updateTexture3DImage(long ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, int depth, + int boundaryWidth, + int imageDataType, Object imageData); + + void updateTexture3DImage(Context ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, int depth, + int boundaryWidth, + int imageDataType, Object imageData) { + updateTexture3DImage(unbox(ctx), + numLevels, level, + textureFormat, imageFormat, + width, height, depth, + boundaryWidth, + imageDataType, imageData); + } + + native void updateTexture3DSubImage(long ctx, + int level, + int xoffset, int yoffset, int zoffset, + int textureFormat, int imageFormat, + int imgXoffset, int imgYoffset, int imgZoffset, + int tilew, int tileh, + int width, int height, int depth, + int imageDataType, Object imageData); + + void updateTexture3DSubImage(Context ctx, + int level, + int xoffset, int yoffset, int zoffset, + int textureFormat, int imageFormat, + int imgXoffset, int imgYoffset, int imgZoffset, + int tilew, int tileh, + int width, int height, int depth, + int imageDataType, Object imageData) { + updateTexture3DSubImage(unbox(ctx), + level, + xoffset, yoffset, zoffset, + textureFormat, imageFormat, + imgXoffset, imgYoffset, imgZoffset, + tilew, tileh, + width, height, depth, + imageDataType, imageData); + } + + native void updateTexture3DLodRange(long ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod); + + void updateTexture3DLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + updateTexture3DLodRange(unbox(ctx), + baseLevel, maximumLevel, + minimumLod, maximumLod); + } + + native void updateTexture3DLodOffset(long ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ); + + void updateTexture3DLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + updateTexture3DLodOffset(unbox(ctx), + lodOffsetX, lodOffsetY, + lodOffsetZ); + } + + native void updateTexture3DBoundary(long ctx, + int boundaryModeS, int boundaryModeT, + int boundaryModeR, float boundaryRed, + float boundaryGreen, float boundaryBlue, + float boundaryAlpha); + + + void updateTexture3DBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + int boundaryModeR, float boundaryRed, + float boundaryGreen, float boundaryBlue, + float boundaryAlpha) { + updateTexture3DBoundary(unbox(ctx), + boundaryModeS, boundaryModeT, + boundaryModeR, boundaryRed, + boundaryGreen, boundaryBlue, + boundaryAlpha); + } + + native void updateTexture3DFilterModes(long ctx, + int minFilter, int magFilter); + + void updateTexture3DFilterModes(Context ctx, + int minFilter, int magFilter) { + updateTexture3DFilterModes(unbox(ctx), + minFilter, magFilter); + } + + native void updateTexture3DSharpenFunc(long ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts); + + void updateTexture3DSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + updateTexture3DSharpenFunc(unbox(ctx), + numSharpenTextureFuncPts, + sharpenTextureFuncPts); + } + + native void updateTexture3DFilter4Func(long ctx, + int numFilter4FuncPts, + float[] filter4FuncPts); + + void updateTexture3DFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + updateTexture3DFilter4Func(unbox(ctx), + numFilter4FuncPts, + filter4FuncPts); + } + + native void updateTexture3DAnisotropicFilter(long ctx, float degree); + + void updateTexture3DAnisotropicFilter(Context ctx, float degree) { + updateTexture3DAnisotropicFilter(unbox(ctx), degree); + } + + + // --------------------------------------------------------------------- + + // + // TextureCubeMapRetained methods + // + + native void bindTextureCubeMap(long ctx, int objectId, boolean enable); + + void bindTextureCubeMap(Context ctx, int objectId, boolean enable) { + bindTextureCubeMap(unbox(ctx), objectId, enable); + } + + native void updateTextureCubeMapImage(long ctx, + int face, int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object imageData); + + void updateTextureCubeMapImage(Context ctx, + int face, int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object imageData) { + updateTextureCubeMapImage(unbox(ctx), + face, numLevels, level, + textureFormat, imageFormat, + width, height, + boundaryWidth, + imageDataType, imageData); + } + + native void updateTextureCubeMapSubImage(long ctx, + int face, int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object imageData); + + void updateTextureCubeMapSubImage(Context ctx, + int face, int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object imageData) { + updateTextureCubeMapSubImage(unbox(ctx), + face, level, xoffset, yoffset, + textureFormat, imageFormat, + imgXOffset, imgYOffset, + tilew, width, height, + imageDataType, imageData); + } + + native void updateTextureCubeMapLodRange(long ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod); + + void updateTextureCubeMapLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + updateTextureCubeMapLodRange(unbox(ctx), + baseLevel, maximumLevel, + minimumLod, maximumLod); + } + + native void updateTextureCubeMapLodOffset(long ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ); + + void updateTextureCubeMapLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + updateTextureCubeMapLodOffset(unbox(ctx), + lodOffsetX, lodOffsetY, + lodOffsetZ); + } + + native void updateTextureCubeMapBoundary(long ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha); + + void updateTextureCubeMapBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha) { + updateTextureCubeMapBoundary(unbox(ctx), + boundaryModeS, boundaryModeT, + boundaryRed, boundaryGreen, + boundaryBlue, boundaryAlpha); + } + + native void updateTextureCubeMapFilterModes(long ctx, + int minFilter, int magFilter); + + void updateTextureCubeMapFilterModes(Context ctx, + int minFilter, int magFilter) { + updateTextureCubeMapFilterModes(unbox(ctx), + minFilter, magFilter); + } + + native void updateTextureCubeMapSharpenFunc(long ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts); + + void updateTextureCubeMapSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + updateTextureCubeMapSharpenFunc(unbox(ctx), + numSharpenTextureFuncPts, + sharpenTextureFuncPts); + } + + native void updateTextureCubeMapFilter4Func(long ctx, + int numFilter4FuncPts, + float[] filter4FuncPts); + + void updateTextureCubeMapFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + updateTextureCubeMapFilter4Func(unbox(ctx), + numFilter4FuncPts, + filter4FuncPts); + } + + native void updateTextureCubeMapAnisotropicFilter(long ctx, float degree); + + void updateTextureCubeMapAnisotropicFilter(Context ctx, float degree) { + updateTextureCubeMapAnisotropicFilter(unbox(ctx), degree); + } + + // --------------------------------------------------------------------- + + // + // MasterControl methods + // + + // Method to return the AWT object + native long getAWT(); + + // Method to initialize the native J3D library + native boolean initializeJ3D(boolean disableXinerama); + + // Maximum lights supported by the native API + native int getMaximumLights(); + + + // --------------------------------------------------------------------- + + // + // Canvas3D methods + // + + // This is the native method for creating the underlying graphics context. + native long createNewContext(Canvas3D cv, long display, long drawable, + long fbConfig, long shareCtx, boolean isSharedCtx, + boolean offScreen, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable); + + // This is the native method for creating the underlying graphics context. + Context createNewContext(Canvas3D cv, long display, Drawable drawable, + long fbConfig, Context shareCtx, boolean isSharedCtx, + boolean offScreen, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + + long nativeCtx = createNewContext(cv, display, unbox(drawable), + fbConfig, unbox(shareCtx), isSharedCtx, + offScreen, + glslLibraryAvailable, + cgLibraryAvailable); + + return boxContext(nativeCtx); + } + + native void createQueryContext(Canvas3D cv, long display, long drawable, + long fbConfig, boolean offScreen, int width, int height, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable); + + void createQueryContext(Canvas3D cv, long display, Drawable drawable, + long fbConfig, boolean offScreen, int width, int height, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + + createQueryContext(cv, display, unbox(drawable), + fbConfig, offScreen, width, height, + glslLibraryAvailable, + cgLibraryAvailable); + } + + // This is the native for creating offscreen buffer + native long createOffScreenBuffer(Canvas3D cv, long ctx, long display, long fbConfig, int width, int height); + + Drawable createOffScreenBuffer(Canvas3D cv, Context ctx, long display, long fbConfig, int width, int height) { + long nativeDrawable = createOffScreenBuffer(cv, unbox(ctx), display, fbConfig, width, height); + return boxDrawable(nativeDrawable); + } + + native void destroyOffScreenBuffer(Canvas3D cv, long ctx, long display, long fbConfig, long drawable); + + void destroyOffScreenBuffer(Canvas3D cv, Context ctx, long display, long fbConfig, Drawable drawable) { + destroyOffScreenBuffer(cv, unbox(ctx), display, fbConfig, unbox(drawable)); + } + + // This is the native for reading the image from the offscreen buffer + native void readOffScreenBuffer(Canvas3D cv, long ctx, int format, int type, Object data, int width, int height); + + void readOffScreenBuffer(Canvas3D cv, Context ctx, int format, int type, Object data, int width, int height) { + readOffScreenBuffer(cv, unbox(ctx), format, type, data, width, height); + } + + // The native method for swapBuffers + native int swapBuffers(Canvas3D cv, long ctx, long dpy, long drawable); + + int swapBuffers(Canvas3D cv, Context ctx, long dpy, Drawable drawable) { + return swapBuffers(cv, unbox(ctx), dpy, unbox(drawable)); + } + + + // notify D3D that Canvas is resize + native int resizeD3DCanvas(Canvas3D cv, long ctx); + + int resizeD3DCanvas(Canvas3D cv, Context ctx) { + return resizeD3DCanvas(cv, unbox(ctx)); + } + + + // notify D3D to toggle between FullScreen and window mode + native int toggleFullScreenMode(Canvas3D cv, long ctx); + + int toggleFullScreenMode(Canvas3D cv, Context ctx) { + return toggleFullScreenMode(cv, unbox(ctx)); + } + + + // native method for setting Material when no material is present + native void updateMaterialColor(long ctx, float r, float g, float b, float a); + + void updateMaterialColor(Context ctx, float r, float g, float b, float a) { + updateMaterialColor(unbox(ctx), r, g, b, a); + } + + + native void destroyContext(long display, long drawable, long ctx); + + void destroyContext(long display, Drawable drawable, Context ctx) { + assert display != 0 || VirtualUniverse.mc.isWindows(); + assert ctx != null; + assert drawable != null; + destroyContext(display, unbox(drawable), unbox(ctx)); + } + + + // This is the native method for doing accumulation. + native void accum(long ctx, float value); + + void accum(Context ctx, float value) { + accum(unbox(ctx), value); + } + + + // This is the native method for doing accumulation return. + native void accumReturn(long ctx); + + void accumReturn(Context ctx) { + accumReturn(unbox(ctx)); + } + + + // This is the native method for clearing the accumulation buffer. + native void clearAccum(long ctx); + + void clearAccum(Context ctx) { + clearAccum(unbox(ctx)); + } + + + // This is the native method for getting the number of lights the underlying + // native library can support. + native int getNumCtxLights(long ctx); + + int getNumCtxLights(Context ctx) { + return getNumCtxLights(unbox(ctx)); + } + + + // Native method for decal 1st child setup + native boolean decal1stChildSetup(long ctx); + + boolean decal1stChildSetup(Context ctx) { + return decal1stChildSetup(unbox(ctx)); + } + + + // Native method for decal nth child setup + native void decalNthChildSetup(long ctx); + + void decalNthChildSetup(Context ctx) { + decalNthChildSetup(unbox(ctx)); + } + + + // Native method for decal reset + native void decalReset(long ctx, boolean depthBufferEnable); + + void decalReset(Context ctx, boolean depthBufferEnable) { + decalReset(unbox(ctx), depthBufferEnable); + } + + + // Native method for decal reset + native void ctxUpdateEyeLightingEnable(long ctx, boolean localEyeLightingEnable); + + void ctxUpdateEyeLightingEnable(Context ctx, boolean localEyeLightingEnable) { + ctxUpdateEyeLightingEnable(unbox(ctx), localEyeLightingEnable); + } + + + // The following three methods are used in multi-pass case + + // native method for setting blend color + native void setBlendColor(long ctx, float red, float green, + float blue, float alpha); + + void setBlendColor(Context ctx, float red, float green, + float blue, float alpha) { + setBlendColor(unbox(ctx), red, green, + blue, alpha); + } + + + // native method for setting blend func + native void setBlendFunc(long ctx, int src, int dst); + + void setBlendFunc(Context ctx, int src, int dst) { + setBlendFunc(unbox(ctx), src, dst); + } + + + // native method for setting fog enable flag + native void setFogEnableFlag(long ctx, boolean enableFlag); + + void setFogEnableFlag(Context ctx, boolean enableFlag) { + setFogEnableFlag(unbox(ctx), enableFlag); + } + + + // Setup the full scene antialising in D3D and ogl when GL_ARB_multisamle supported + native void setFullSceneAntialiasing(long ctx, boolean enable); + + void setFullSceneAntialiasing(Context ctx, boolean enable) { + setFullSceneAntialiasing(unbox(ctx), enable); + } + + + native void setGlobalAlpha(long ctx, float alpha); + + void setGlobalAlpha(Context ctx, float alpha) { + setGlobalAlpha(unbox(ctx), alpha); + } + + + // Native method to update separate specular color control + native void updateSeparateSpecularColorEnable(long ctx, boolean control); + + void updateSeparateSpecularColorEnable(Context ctx, boolean control) { + updateSeparateSpecularColorEnable(unbox(ctx), control); + } + + + // Initialization for D3D when scene begin + native void beginScene(long ctx); + + void beginScene(Context ctx) { + beginScene(unbox(ctx)); + } + + native void endScene(long ctx); + + void endScene(Context ctx) { + endScene(unbox(ctx)); + } + + + // True under Solaris, + // False under windows when display mode <= 8 bit + native boolean validGraphicsMode(); + + // native method for setting light enables + native void setLightEnables(long ctx, long enableMask, int maxLights); + + void setLightEnables(Context ctx, long enableMask, int maxLights) { + setLightEnables(unbox(ctx), enableMask, maxLights); + } + + + // native method for setting scene ambient + native void setSceneAmbient(long ctx, float red, float green, float blue); + + void setSceneAmbient(Context ctx, float red, float green, float blue) { + setSceneAmbient(unbox(ctx), red, green, blue); + } + + + // native method for disabling fog + native void disableFog(long ctx); + + void disableFog(Context ctx) { + disableFog(unbox(ctx)); + } + + + // native method for disabling modelClip + native void disableModelClip(long ctx); + + void disableModelClip(Context ctx) { + disableModelClip(unbox(ctx)); + } + + + // native method for setting default RenderingAttributes + native void resetRenderingAttributes(long ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride); + + void resetRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride) { + resetRenderingAttributes(unbox(ctx), + depthBufferWriteEnableOverride, + depthBufferEnableOverride); + } + + + // native method for setting default texture + native void resetTextureNative(long ctx, int texUnitIndex); + + void resetTextureNative(Context ctx, int texUnitIndex) { + resetTextureNative(unbox(ctx), texUnitIndex); + } + + + // native method for activating a particular texture unit + native void activeTextureUnit(long ctx, int texUnitIndex); + + void activeTextureUnit(Context ctx, int texUnitIndex) { + activeTextureUnit(unbox(ctx), texUnitIndex); + } + + + // native method for setting default TexCoordGeneration + native void resetTexCoordGeneration(long ctx); + + void resetTexCoordGeneration(Context ctx) { + resetTexCoordGeneration(unbox(ctx)); + } + + + // native method for setting default TextureAttributes + native void resetTextureAttributes(long ctx); + + void resetTextureAttributes(Context ctx) { + resetTextureAttributes(unbox(ctx)); + } + + + // native method for setting default PolygonAttributes + native void resetPolygonAttributes(long ctx); + + void resetPolygonAttributes(Context ctx) { + resetPolygonAttributes(unbox(ctx)); + } + + + // native method for setting default LineAttributes + native void resetLineAttributes(long ctx); + + void resetLineAttributes(Context ctx) { + resetLineAttributes(unbox(ctx)); + } + + + // native method for setting default PointAttributes + native void resetPointAttributes(long ctx); + + void resetPointAttributes(Context ctx) { + resetPointAttributes(unbox(ctx)); + } + + + // native method for setting default TransparencyAttributes + native void resetTransparency(long ctx, int geometryType, + int polygonMode, boolean lineAA, + boolean pointAA); + + void resetTransparency(Context ctx, int geometryType, + int polygonMode, boolean lineAA, + boolean pointAA) { + resetTransparency(unbox(ctx), geometryType, + polygonMode, lineAA, + pointAA); + } + + + // native method for setting default ColoringAttributes + native void resetColoringAttributes(long ctx, + float r, float g, + float b, float a, + boolean enableLight); + + void resetColoringAttributes(Context ctx, + float r, float g, + float b, float a, + boolean enableLight) { + resetColoringAttributes(unbox(ctx), + r, g, + b, a, + enableLight); + } + + /** + * This native method makes sure that the rendering for this canvas + * gets done now. + */ + native void syncRender(long ctx, boolean wait); + + void syncRender(Context ctx, boolean wait) { + syncRender(unbox(ctx), wait); + } + + + // The native method that sets this ctx to be the current one + native boolean useCtx(long ctx, long display, long drawable); + + boolean useCtx(Context ctx, long display, Drawable drawable) { + assert display != 0 || VirtualUniverse.mc.isWindows(); + return useCtx(unbox(ctx), display, unbox(drawable)); + } + + native void clear(long ctx, float r, float g, float b); + + void clear(Context ctx, float r, float g, float b) { + clear(unbox(ctx), r, g, b); + + } + + native void textureFillBackground(long ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY); + + void textureFillBackground(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY) { + textureFillBackground(unbox(ctx), texMinU, texMaxU, texMinV, texMaxV, + mapMinX, mapMaxX, mapMinY, mapMaxY); + } + + native void textureFillRaster(long ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY, float mapZ, float alpha); + + void textureFillRaster(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY, float mapZ, float alpha) { + textureFillRaster(unbox(ctx), texMinU, texMaxU, texMinV, texMaxV, + mapMinX, mapMaxX, mapMinY, mapMaxY, mapZ, alpha); + } + + native void executeRasterDepth(long ctx, float posX, float posY, float posZ, + int srcOffsetX, int srcOffsetY, int rasterWidth, int rasterHeight, + int depthWidth, int depthHeight, int depthType, Object depthData); + + void executeRasterDepth(Context ctx, float posX, float posY, float posZ, + int srcOffsetX, int srcOffsetY, int rasterWidth, int rasterHeight, + int depthWidth, int depthHeight, int depthType, Object depthData) { + executeRasterDepth(unbox(ctx), posX, posY, posZ, srcOffsetX, srcOffsetY, + rasterWidth, rasterHeight, depthWidth, depthHeight, depthType, depthData); + } + + // The native method for setting the ModelView matrix. + native void setModelViewMatrix(long ctx, double[] viewMatrix, double[] modelMatrix); + + void setModelViewMatrix(Context ctx, double[] viewMatrix, double[] modelMatrix) { + setModelViewMatrix(unbox(ctx), viewMatrix, modelMatrix); + } + + + // The native method for setting the Projection matrix. + native void setProjectionMatrix(long ctx, double[] projMatrix); + + void setProjectionMatrix(Context ctx, double[] projMatrix) { + setProjectionMatrix(unbox(ctx), projMatrix); + } + + + // The native method for setting the Viewport. + native void setViewport(long ctx, int x, int y, int width, int height); + + void setViewport(Context ctx, int x, int y, int width, int height) { + setViewport(unbox(ctx), x, y, width, height); + } + + + // used for display Lists + native void newDisplayList(long ctx, int displayListId); + + void newDisplayList(Context ctx, int displayListId) { + newDisplayList(unbox(ctx), displayListId); + } + + native void endDisplayList(long ctx); + + void endDisplayList(Context ctx) { + endDisplayList(unbox(ctx)); + } + + native void callDisplayList(long ctx, int id, boolean isNonUniformScale); + + void callDisplayList(Context ctx, int id, boolean isNonUniformScale) { + callDisplayList(unbox(ctx), id, isNonUniformScale); + } + + + native void freeDisplayList(long ctx, int id); + + void freeDisplayList(Context ctx, int id) { + freeDisplayList(unbox(ctx), id); + } + + native void freeTexture(long ctx, int id); + + void freeTexture(Context ctx, int id) { + freeTexture(unbox(ctx), id); + } + + native void texturemapping(long ctx, + int px, int py, + int xmin, int ymin, int xmax, int ymax, + int texWidth, int texHeight, + int rasWidth, + int format, int objectId, + byte[] image, + int winWidth, int winHeight); + + void texturemapping(Context ctx, + int px, int py, + int xmin, int ymin, int xmax, int ymax, + int texWidth, int texHeight, + int rasWidth, + int format, int objectId, + byte[] image, + int winWidth, int winHeight) { + texturemapping(unbox(ctx), + px, py, + xmin, ymin, xmax, ymax, + texWidth, texHeight, + rasWidth, + format, objectId, + image, + winWidth, winHeight); + } + + + native boolean initTexturemapping(long ctx, int texWidth, + int texHeight, int objectId); + + boolean initTexturemapping(Context ctx, int texWidth, + int texHeight, int objectId) { + return initTexturemapping(unbox(ctx), texWidth, + texHeight, objectId); + } + + + + // Set internal render mode to one of FIELD_ALL, FIELD_LEFT or + // FIELD_RIGHT. Note that it is up to the caller to ensure that + // stereo is available before setting the mode to FIELD_LEFT or + // FIELD_RIGHT. The boolean isTRUE for double buffered mode, FALSE + // foe single buffering. + native void setRenderMode(long ctx, int mode, boolean doubleBuffer); + + void setRenderMode(Context ctx, int mode, boolean doubleBuffer) { + setRenderMode(unbox(ctx), mode, doubleBuffer); + } + + + // Set glDepthMask. + native void setDepthBufferWriteEnable(long ctx, boolean mode); + + void setDepthBufferWriteEnable(Context ctx, boolean mode) { + setDepthBufferWriteEnable(unbox(ctx), mode); + } + + + + // --------------------------------------------------------------------- + + // + // Canvas3D / GraphicsConfigTemplate3D methods - logic dealing with + // native graphics configuration or drawing surface + // + + // Return a graphics config based on the one passed in. Note that we can + // assert that the input config is non-null and was created from a + // GraphicsConfigTemplate3D. + // This method must return a valid GraphicsConfig, or else it must throw + // an exception if one cannot be returned. + GraphicsConfiguration getGraphicsConfig(GraphicsConfiguration gconfig) { +//KCR: System.err.println("NativePipeline.getGraphicsConfig()"); + + // Just return the input graphics config + return gconfig; + } + + // Get the native FBconfig pointer + long getFbConfig(GraphicsConfigInfo gcInfo) { + long fbConfig = ((Long)gcInfo.getPrivateData()).longValue(); + if (fbConfig == 0L) { + throw new IllegalArgumentException(J3dI18N.getString("Canvas3D23")); + } + + return fbConfig; + } + + // Get best graphics config from pipeline + GraphicsConfiguration getBestConfiguration(GraphicsConfigTemplate3D gct, + GraphicsConfiguration[] gc) { + return nativeTemplate.getBestConfiguration(gct, gc); + } + + // Determine whether specified graphics config is supported by pipeline + boolean isGraphicsConfigSupported(GraphicsConfigTemplate3D gct, + GraphicsConfiguration gc) { + return nativeTemplate.isGraphicsConfigSupported(gct, gc); + } + + // Methods to get actual capabilities from Canvas3D + boolean hasDoubleBuffer(Canvas3D cv) { + return nativeTemplate.hasDoubleBuffer(cv); + } + + boolean hasStereo(Canvas3D cv) { + return nativeTemplate.hasStereo(cv); + } + + int getStencilSize(Canvas3D cv) { + return nativeTemplate.getStencilSize(cv); + } + + boolean hasSceneAntialiasingMultisample(Canvas3D cv) { + return nativeTemplate.hasSceneAntialiasingMultisample(cv); + } + + boolean hasSceneAntialiasingAccum(Canvas3D cv) { + return nativeTemplate.hasSceneAntialiasingAccum(cv); + } + + // Methods to get native WS display and screen + long getDisplay() { + return NativeScreenInfo.getDisplay(); + } + int getScreen(GraphicsDevice graphicsDevice) { + return NativeScreenInfo.getScreen(graphicsDevice); + } + + // --------------------------------------------------------------------- + + // + // DrawingSurfaceObject methods + // + + // Method to construct a new DrawingSurfaceObject + DrawingSurfaceObject createDrawingSurfaceObject(Canvas3D cv) { + return new DrawingSurfaceObjectAWT(cv, + VirtualUniverse.mc.awt, cv.screen.display, cv.screen.screen, + VirtualUniverse.mc.xineramaDisabled); + } + + + // Method to free the drawing surface object + // (called from Canvas3D.removeNotify) + void freeDrawingSurface(Canvas3D cv, DrawingSurfaceObject drawingSurfaceObject) { + synchronized (drawingSurfaceObject) { + DrawingSurfaceObjectAWT dso = + (DrawingSurfaceObjectAWT)drawingSurfaceObject; + // get nativeDS before it is set to 0 in invalidate() + long ds = dso.getDS(); + long ds_struct[] = {ds, dso.getDSI()}; + if (ds != 0) { + VirtualUniverse.mc.postRequest( + MasterControl.FREE_DRAWING_SURFACE, + ds_struct); + } + + drawingSurfaceObject.invalidate(); + } + } + + // Method to free the native drawing surface object + void freeDrawingSurfaceNative(Object o) { + DrawingSurfaceObjectAWT.freeDrawingSurface(o); + } + +} diff --git a/src/classes/share/javax/media/j3d/NativeShaderObject.java b/src/classes/share/javax/media/j3d/NativeShaderObject.java new file mode 100644 index 0000000..050fb37 --- /dev/null +++ b/src/classes/share/javax/media/j3d/NativeShaderObject.java @@ -0,0 +1,31 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Shader objects for native rendering pipeline. + */ +class NativeShaderObject implements ShaderProgramId, ShaderId, ShaderAttrLoc { + + // Native shader object; + private long nativeId; + + NativeShaderObject(long nativeId) { + this.nativeId = nativeId; + } + + long getNativeId() { + return nativeId; + } + +} diff --git a/src/classes/share/javax/media/j3d/NioImageBuffer.java b/src/classes/share/javax/media/j3d/NioImageBuffer.java new file mode 100644 index 0000000..91ebe92 --- /dev/null +++ b/src/classes/share/javax/media/j3d/NioImageBuffer.java @@ -0,0 +1,379 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; + +/** + * The NioImageBuffer class is a container for an image whose DataBuffer + * is specified via a java.nio.Buffer. An an NioImageBuffer can be wrapped by + * an ImageComponent and used for texture mapping, or for rendering Raster + * objects or background images. An NioImageBuffer must not be used as the + * buffer of an off-screen Canvas3D, or for reading back a raster image. + * + * @see ImageComponent2D + * @see ImageComponent3D + * + * @since Java 3D 1.5 + */ +public class NioImageBuffer { + + /** + * Used to specify the type of the image. + */ + public enum ImageType { + /** + * Represents an image with 8-bit RGB color components, + * corresponding to a Windows-style BGR color model, with the + * colors Blue, Green, and Red stored in 3 consecutive + * bytes for each pixel. + * The data buffer must be a ByteBuffer when using this imageType. + */ + TYPE_3BYTE_BGR, + + /** + * Represents an image with 8-bit RGB color components with + * Red, Green, and Blue, stored in 3 consecutive + * bytes for each pixel. + * The data buffer must be a ByteBuffer when using this imageType. + */ + TYPE_3BYTE_RGB, + + /** + * Represents an image with 8-bit RGBA color components with + * Alpha, Blue, Green, and Red stored in 4 consecutive + * bytes for each pixel. + * The data buffer must be a ByteBuffer when using this imageType. + */ + TYPE_4BYTE_ABGR, + + /** + * Represents an image with 8-bit RGBA color components with + * Red, Green, Blue, and Alpha stored in 4 consecutive + * bytes for each pixel. + * The data buffer must be a ByteBuffer when using this imageType. + */ + TYPE_4BYTE_RGBA, + + /** + * Represents a unsigned byte grayscale image, non-indexed. + * The data buffer must be a ByteBuffer when using this imageType. + */ + TYPE_BYTE_GRAY, + + /** + * Represents an image with 8-bit RGBA color components packed + * into integer pixels. + * The data buffer must be an IntBuffer when using this imageType. + */ + TYPE_INT_ARGB, + + /** + * Represents an image with 8-bit RGB color components, + * corresponding to a Windows- or Solaris- style BGR color model, + * with the colors Blue, Green, and Red packed into integer + * pixels. + * The data buffer must be an IntBuffer when using this imageType. + */ + TYPE_INT_BGR, + + /** + * Represents an image with 8-bit RGB color components packed into + * integer pixels. + * The data buffer must be an IntBuffer when using this imageType. + */ + TYPE_INT_RGB, + + } + + + /** + * Enum for type of buffer + */ + enum BufferType { + BYTE_BUFFER, + INT_BUFFER, + } + + + // Width and height of image + int width; + int height; + + // TYpe of image + ImageType imageType; + + // Cached buffer + Buffer buffer; + + // Type of NIO Buffer: byte or int + BufferType bufferType; + + // Number of bytes allocated per pixel + int bytesPerPixel; + + // Number of byte or int elements per pixel + int elementsPerPixel; + + /** + * Constructs an NIO image buffer of the specified size and type. + * A direct NIO buffer of the correct type (ByteBuffer or IntBuffer) + * and size to match the input parameters + * is allocated. + * + * @param width width of the image + * @param height height of the image + * @param imageType type of the image. + * + * @exception IllegalArgumentException if width < 1 or height < 1 + * @exception NullPointerException if imageType is null + */ + public NioImageBuffer(int width, int height, ImageType imageType) { + + processParams(width, height, imageType); + + ByteBuffer tmpBuffer = ByteBuffer.allocateDirect(width * height * bytesPerPixel); + switch (bufferType) { + case BYTE_BUFFER: + buffer = tmpBuffer; + break; + + case INT_BUFFER: + buffer = tmpBuffer.order(ByteOrder.nativeOrder()).asIntBuffer(); + break; + + default: + // We should never get here + throw new AssertionError("missing case statement"); + } + } + + /** + * Constructs an NIO image buffer of the specified size and type, using + * the specified dataBuffer. + * The the byte order of the specified dataBuffer must match the native + * byte order of the underlying platform. + * For best performance, the NIO buffer should be a direct buffer. + * + * @param width width of the image + * @param height height of the image + * @param imageType type of the image. + * @param dataBuffer an NIO buffer of the correct type (ByteBuffer or + * IntBuffer) to match the specified imageType. + * This constructor will create a new view of + * the buffer, and will call <code>rewind</code> on that view, + * such that elements 0 through <code>dataBuffer.limit()-1</code> + * will be available internally. The number of elements in + * the buffer must be exactly <code>width*height*numElementsPerPixel</code>, + * where <code>numElementsPerPixel</code> is + * 3 for TYPE_3BYTE_BGR and TYPE_3BYTE_RGB, + * 4 for TYPE_4BYTE_ABGR and TYPE_4BYTE_RGBA, + * and 1 for all other types. + * + * @exception IllegalArgumentException if width < 1 or height < 1 + * @exception NullPointerException if imageType or dataBuffer is null + * @exception IllegalArgumentException if the type of the dataBuffer does + * not match the imageType + * @exception IllegalArgumentException if <code>dataBuffer.limit() != + * width*height*numElementsPerPixel</code> + * @exception IllegalArgumentException if the byte order of the specified + * dataBuffer does not match the native byte order of the underlying + * platform. + */ + public NioImageBuffer(int width, int height, ImageType imageType, + Buffer dataBuffer) { + + processParams(width, height, imageType); + setDataBuffer(dataBuffer); + } + + /** + * Gets the width of this data buffer. + * + * @return the width of this data buffer. + */ + public int getWidth() { + return width; + } + + /** + * Gets the height of this data buffer. + * + * @return the width of this data buffer. + */ + public int getHeight() { + return height; + } + + /** + * Gets the image type of this data buffer. + * + * @return the image type of this data buffer. + */ + public ImageType getImageType() { + return imageType; + } + + /** + * Sets the data buffer to the specified input data buffer. + * The the byte order of the specified dataBuffer must match the native + * byte order of the underlying platform. + * For best performance, the NIO buffer should be a direct buffer. + * + * @param dataBuffer an NIO buffer of the correct type (ByteBuffer or + * IntBuffer) to match the imageType of this + * NioImageBuffer. This method will create a new view of + * the buffer, and will call <code>rewind</code> on that view, + * such that elements 0 through <code>dataBuffer.limit()-1</code> + * will be available internally. The number of elements in + * the buffer must be exactly <code>width*height*numElementsPerPixel</code>, + * where <code>numElementsPerPixel</code> is + * 3 for TYPE_3BYTE_BGR and TYPE_3BYTE_RGB, + * 4 for TYPE_4BYTE_ABGR and TYPE_4BYTE_RGBA, + * and 1 for all other types. + * + * @exception NullPointerException if dataBuffer is null + * @exception IllegalArgumentException if the type of the dataBuffer does + * not match the imageType + * @exception IllegalArgumentException if <code>dataBuffer.limit() != + * width*height*numElementsPerPixel</code> + * @exception IllegalArgumentException if the byte order of the specified + * dataBuffer does not match the native byte order of the underlying + * platform. + */ + public void setDataBuffer(Buffer dataBuffer) { + if (dataBuffer == null) { + throw new NullPointerException(); + } + + if (dataBuffer.limit() != width*height*elementsPerPixel) { + throw new IllegalArgumentException(J3dI18N.getString("NioImageBuffer3")); + } + + switch (bufferType) { + case BYTE_BUFFER: + if (!(dataBuffer instanceof ByteBuffer)) { + throw new IllegalArgumentException(J3dI18N.getString("NioImageBuffer4")); + } + buffer = ((ByteBuffer)dataBuffer).duplicate().rewind(); + break; + + case INT_BUFFER: + if (!(dataBuffer instanceof IntBuffer)) { + throw new IllegalArgumentException(J3dI18N.getString("NioImageBuffer4")); + } + + if (((IntBuffer)dataBuffer).order() != ByteOrder.nativeOrder()) { + throw new IllegalArgumentException(J3dI18N.getString("NioImageBuffer5")); + } + buffer = ((IntBuffer)dataBuffer).duplicate().rewind(); + break; + + default: + // We should never get here + throw new AssertionError("missing case statement"); + } + } + + /** + * Gets the data buffer to the specified input data buffer. + * + * @return a view of the current data buffer for this NIO image buffer. + * This view will be rewound such that elements 0 + * through <code>dataBuffer.limit()-1</code> are available. + */ + public Buffer getDataBuffer() { + Buffer tmpBuffer = null; + + switch (bufferType) { + case BYTE_BUFFER: + tmpBuffer = ((ByteBuffer)buffer).duplicate(); + break; + + case INT_BUFFER: + tmpBuffer = ((IntBuffer)buffer).duplicate(); + break; + + default: + // We should never get here + throw new AssertionError("missing case statement"); + } + + return tmpBuffer.rewind(); + } + + + // Sanity check the input parameters, calculate the buffer type and + // the number of bytes per pixel + private void processParams(int width, int height, ImageType imageType) { + if (width < 1) { + throw new IllegalArgumentException(J3dI18N.getString("NioImageBuffer0")); + } + + if (height < 1) { + throw new IllegalArgumentException(J3dI18N.getString("NioImageBuffer1")); + } + + switch (imageType) { + case TYPE_3BYTE_BGR: + bufferType = BufferType.BYTE_BUFFER; + bytesPerPixel = 3; + elementsPerPixel = 3; + break; + + case TYPE_3BYTE_RGB: + bufferType = BufferType.BYTE_BUFFER; + bytesPerPixel = 3; + elementsPerPixel = 3; + break; + + case TYPE_4BYTE_ABGR: + bufferType = BufferType.BYTE_BUFFER; + bytesPerPixel = 4; + elementsPerPixel = 4; + break; + + case TYPE_4BYTE_RGBA: + bufferType = BufferType.BYTE_BUFFER; + bytesPerPixel = 4; + elementsPerPixel = 4; + break; + + case TYPE_BYTE_GRAY: + bufferType = BufferType.BYTE_BUFFER; + bytesPerPixel = 1; + elementsPerPixel = 1; + break; + + case TYPE_INT_ARGB: + case TYPE_INT_BGR: + case TYPE_INT_RGB: + bufferType = BufferType.INT_BUFFER; + bytesPerPixel = 4; + elementsPerPixel = 1; + break; + + default: + // We should never get here + throw new AssertionError("missing case statement"); + } + + this.width = width; + this.height = height; + this.imageType = imageType; + } + +} diff --git a/src/classes/share/javax/media/j3d/NodeComponent.java b/src/classes/share/javax/media/j3d/NodeComponent.java index 524814e..0498ae5 100644 --- a/src/classes/share/javax/media/j3d/NodeComponent.java +++ b/src/classes/share/javax/media/j3d/NodeComponent.java @@ -265,4 +265,29 @@ public abstract class NodeComponent extends SceneGraphObject { boolean duplicateChild() { return getDuplicateOnCloneTree(); } + + /* + * @exception IllegalSharingException if this NodeComponent is live and + * the specified image is being used by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this NodeComponent is + * being used by an immediate mode context and + * the specified image is being used by a Canvas3D as an off-screen buffer. + */ + void validateImageIllegalSharing(ImageComponent image) { + // Do illegal sharing check + if(image != null) { + ImageComponentRetained imageRetained = (ImageComponentRetained) image.retained; + NodeComponentRetained ncRetained = (NodeComponentRetained)this.retained; + if(imageRetained.getUsedByOffScreen()) { + if(isLive()) { + throw new IllegalSharingException(J3dI18N.getString("NodeComponent2")); + } + if(ncRetained.getInImmCtx()) { + throw new IllegalSharingException(J3dI18N.getString("NodeComponent3")); + } + } + } + } + } diff --git a/src/classes/share/javax/media/j3d/NodeComponentRetained.java b/src/classes/share/javax/media/j3d/NodeComponentRetained.java index 8b25c27..5af65a0 100644 --- a/src/classes/share/javax/media/j3d/NodeComponentRetained.java +++ b/src/classes/share/javax/media/j3d/NodeComponentRetained.java @@ -43,7 +43,7 @@ class NodeComponentRetained extends SceneGraphObjectRetained { // In the case of Appearance, its a bitmask of all components int changedFrequent = 0; int compChanged = 0; - + // Increment the refcount. If this is the first, mark it as live. void doSetLive(boolean inBackgroundGroup, int refCount) { int oldRefCount = this.refCount; @@ -212,21 +212,13 @@ class NodeComponentRetained extends SceneGraphObjectRetained { mirror = null; } - // Evaluate state based on the following extensions - void evaluateExtensions(int extensions) { - } - - - - void setFrequencyChangeMask(int bit, int mask) { - // Record only the inf->frequent change if (source.getCapabilityIsFrequent(bit)) changedFrequent |= mask; else if (!source.isLive()) { + // Record the freq->infreq change only for non-live node components changedFrequent &= ~mask; } - } protected Object clone() { diff --git a/src/classes/share/javax/media/j3d/NodeRetained.java b/src/classes/share/javax/media/j3d/NodeRetained.java index 7742891..bb833a4 100644 --- a/src/classes/share/javax/media/j3d/NodeRetained.java +++ b/src/classes/share/javax/media/j3d/NodeRetained.java @@ -363,10 +363,9 @@ abstract class NodeRetained extends SceneGraphObjectRetained implements NnuId { } if((nodeR instanceof TransformGroupRetained) && (nodeR != caller)) { - Transform3D t1 = VirtualUniverse.mc.getTransform3D(null); + Transform3D t1 = new Transform3D(); ((TransformGroupRetained)(nodeR)).transform.getWithLock(t1); l2Vw.mul(t1); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t1); } else if ((nodeR == caller) && (staticTransform != null)) { l2Vw.mul(staticTransform.transform); } diff --git a/src/classes/share/javax/media/j3d/NoopDrawingSurfaceObject.java b/src/classes/share/javax/media/j3d/NoopDrawingSurfaceObject.java new file mode 100644 index 0000000..5fb3c01 --- /dev/null +++ b/src/classes/share/javax/media/j3d/NoopDrawingSurfaceObject.java @@ -0,0 +1,57 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The DrawingSurfaceObject class is used to manage native drawing surface + */ +class NoopDrawingSurfaceObject extends DrawingSurfaceObject { + + NoopDrawingSurfaceObject(Canvas3D cv) { + super(cv); + + System.err.println("NoopDrawingSurfaceObject constructed"); + } + + synchronized boolean renderLock() { + System.err.println("NoopDrawingSurfaceObject.renderLock()"); + gotDsiLock = true; + return true; + } + + synchronized void unLock() { + System.err.println("NoopDrawingSurfaceObject.unLock()"); + gotDsiLock = false; + } + + synchronized void getDrawingSurfaceObjectInfo() { + if (canvas.drawable == null) { + System.err.println( + "NoopDrawingSurfaceObject.getDrawingSurfaceObjectInfo: window = " + + canvas.drawable); + + canvas.drawable = new NoopDrawable(); + } + } + + synchronized void invalidate() { + System.err.println("NoopDrawingSurfaceObject.invalidate()"); + } + + /** + * Dummy drawable for noop pipeline + */ + static class NoopDrawable implements Drawable { + } + +} diff --git a/src/classes/share/javax/media/j3d/NoopPipeline.java b/src/classes/share/javax/media/j3d/NoopPipeline.java new file mode 100644 index 0000000..09e7b04 --- /dev/null +++ b/src/classes/share/javax/media/j3d/NoopPipeline.java @@ -0,0 +1,1561 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; + +/** + * Concrete implementation of Pipeline class for the noop rendering + * pipeline. + */ +class NoopPipeline extends Pipeline { + + // Flags indicating whether the Cg or GLSL libraries are available. + private boolean cgLibraryAvailable = false; + + /** + * Constructor for singleton NoopPipeline instance + */ + protected NoopPipeline() { + } + + /** + * Initialize the pipeline + */ + void initialize(Pipeline.Type pipelineType) { + super.initialize(pipelineType); + + assert pipelineType == Pipeline.Type.NOOP; + } + + /** + * Load all of the required libraries + */ + void loadLibraries(int globalShadingLanguage) { + } + + /** + * Returns true if the Cg library is loaded and available. Note that this + * does not necessarily mean that Cg is supported by the graphics card. + */ + boolean isCgLibraryAvailable() { + return cgLibraryAvailable; + } + + /** + * Returns true if the GLSL library is loaded and available. Note that this + * does not necessarily mean that GLSL is supported by the graphics card. + */ + boolean isGLSLLibraryAvailable() { + return true; + } + + + // --------------------------------------------------------------------- + + // + // GeometryArrayRetained methods + // + + // Used by D3D to free vertex buffer + void freeD3DArray(GeometryArrayRetained geo, boolean deleteVB) { + } + + // used for GeometryArrays by Copy or interleaved + void execute(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + int vertexAttrCount, int[] vertexAttrSizes, + float[] varray, float[] cdata, int cdirty) { + } + + // used by GeometryArray by Reference with java arrays + void executeVA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty) { + } + + // used by GeometryArray by Reference with NIO buffer + void executeVABuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, + Object vcoords, + int colorIndex, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + int normalIndex, Object ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, Object[] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty) { + } + + // used by GeometryArray by Reference in interleaved format with NIO buffer + void executeInterleavedBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object varray, float[] cdata, int cdirty) { + } + + void setVertexFormat(Context ctx, GeometryArrayRetained geo, + int vformat, boolean useAlpha, boolean ignoreVertexColors) { + } + + void disableGlobalAlpha(Context ctx, GeometryArrayRetained geo, int vformat, + boolean useAlpha, boolean ignoreVertexColors) { + } + + // used for GeometryArrays + void buildGA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int startVIndex, + int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, int[] texCoordSetMapOffset, + int vertexAttrCount, int[] vertexAttrSizes, + double[] xform, double[] nxform, + float[] varray) { + } + + // used to Build Dlist GeometryArray by Reference with java arrays + void buildGAForByRef(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int[] texIndex, int texstride, Object[] texCoords, + double[] xform, double[] nxform) { + } + + + // --------------------------------------------------------------------- + + // + // IndexedGeometryArrayRetained methods + // + + // by-copy or interleaved, by reference, Java arrays + void executeIndexedGeometry(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + float[] varray, float[] cdata, + int cdirty, + int[] indexCoord) { + } + + // interleaved, by reference, nio buffer + void executeIndexedGeometryBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object varray, float[] cdata, + int cdirty, + int[] indexCoord) { + } + + // non interleaved, by reference, Java arrays + void executeIndexedGeometryVA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + float[] vfcoords, double[] vdcoords, + float[] cfdata, byte[] cbdata, + float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord) { + } + + // non interleaved, by reference, nio buffer + void executeIndexedGeometryVABuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + Object vcoords, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + Object normal, + int vertexAttrCount, int[] vertexAttrSizes, + Object[] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord) { + } + + // by-copy geometry + void buildIndexedGeometry(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetMapOffset, + double[] xform, double[] nxform, + float[] varray, int[] indexCoord) { + } + + + // --------------------------------------------------------------------- + + // + // GraphicsContext3D methods + // + + void readRaster(Context ctx, + int type, int xSrcOffset, int ySrcOffset, + int width, int height, int hCanvas, + int imageDataType, int imageFormat, + Object imageBuffer, + int depthFormat, + Object depthBuffer) { + + } + + // --------------------------------------------------------------------- + + // + // CgShaderProgramRetained methods + // + + // ShaderAttributeValue methods + + ShaderError setCgUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value) { + return null; + } + + ShaderError setCgUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value) { + return null; + } + + ShaderError setCgUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return null; + } + + ShaderError setCgUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + ShaderError setCgUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return null; + } + + ShaderError setCgUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + ShaderError setCgUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return null; + } + + ShaderError setCgUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + ShaderError setCgUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + ShaderError setCgUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + // ShaderAttributeArray methods + + ShaderError setCgUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return null; + } + + ShaderError setCgUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setCgUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return null; + } + + ShaderError setCgUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setCgUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return null; + } + + ShaderError setCgUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setCgUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return null; + } + + ShaderError setCgUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setCgUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setCgUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + // interfaces for shader compilation, etc. + ShaderError createCgShader(Context ctx, int shaderType, ShaderId[] shaderId) { + return null; + } + ShaderError destroyCgShader(Context ctx, ShaderId shaderId) { + return null; + } + ShaderError compileCgShader(Context ctx, ShaderId shaderId, String program) { + return null; + } + + ShaderError createCgShaderProgram(Context ctx, ShaderProgramId[] shaderProgramId) { + return null; + } + ShaderError destroyCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return null; + } + ShaderError linkCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId, + ShaderId[] shaderIds) { + return null; + } + void lookupCgVertexAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, boolean[] errArr) { + } + void lookupCgShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, ShaderAttrLoc[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr) { + } + + ShaderError useCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return null; + } + + + // --------------------------------------------------------------------- + + // + // GLSLShaderProgramRetained methods + // + + // ShaderAttributeValue methods + + ShaderError setGLSLUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value) { + return null; + } + + ShaderError setGLSLUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value) { + return null; + } + + ShaderError setGLSLUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return null; + } + + ShaderError setGLSLUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + ShaderError setGLSLUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return null; + } + + ShaderError setGLSLUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + ShaderError setGLSLUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value) { + return null; + } + + ShaderError setGLSLUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + ShaderError setGLSLUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + ShaderError setGLSLUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value) { + return null; + } + + // ShaderAttributeArray methods + + ShaderError setGLSLUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return null; + } + + ShaderError setGLSLUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setGLSLUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return null; + } + + ShaderError setGLSLUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setGLSLUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return null; + } + + ShaderError setGLSLUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setGLSLUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value) { + return null; + } + + ShaderError setGLSLUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setGLSLUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + ShaderError setGLSLUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value) { + return null; + } + + // interfaces for shader compilation, etc. + ShaderError createGLSLShader(Context ctx, int shaderType, ShaderId[] shaderId) { + return null; + } + ShaderError destroyGLSLShader(Context ctx, ShaderId shaderId) { + return null; + } + ShaderError compileGLSLShader(Context ctx, ShaderId shaderId, String program) { + return null; + } + + ShaderError createGLSLShaderProgram(Context ctx, ShaderProgramId[] shaderProgramId) { + return null; + } + ShaderError destroyGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return null; + } + ShaderError linkGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId, + ShaderId[] shaderIds) { + return null; + } + ShaderError bindGLSLVertexAttrName(Context ctx, ShaderProgramId shaderProgramId, + String attrName, int attrIndex) { + return null; + } + void lookupGLSLShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, ShaderAttrLoc[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr) { + } + + ShaderError useGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId) { + return null; + } + + + // --------------------------------------------------------------------- + + // + // ImageComponent2DRetained methods + // + + // free d3d surface referred to by id + void freeD3DSurface(ImageComponent2DRetained image, int hashId) { + } + + + + // --------------------------------------------------------------------- + + // + // Renderer methods + // + + void cleanupRenderer() { + } + + + // --------------------------------------------------------------------- + + // + // ColoringAttributesRetained methods + // + + void updateColoringAttributes(Context ctx, + float dRed, float dGreen, float dBlue, + float red, float green, float blue, + float alpha, + boolean lEnable, + int shadeModel) { + } + + + // --------------------------------------------------------------------- + + // + // DirectionalLightRetained methods + // + + void updateDirectionalLight(Context ctx, + int lightSlot, float red, float green, + float blue, float x, float y, float z) { + } + + + // --------------------------------------------------------------------- + + // + // PointLightRetained methods + // + + void updatePointLight(Context ctx, + int lightSlot, float red, float green, + float blue, float ax, float ay, float az, + float px, float py, float pz) { + } + + + // --------------------------------------------------------------------- + + // + // SpotLightRetained methods + // + + void updateSpotLight(Context ctx, + int lightSlot, float red, float green, + float blue, float ax, float ay, float az, + float px, float py, float pz, float spreadAngle, + float concentration, float dx, float dy, + float dz) { + } + + + // --------------------------------------------------------------------- + + // + // ExponentialFogRetained methods + // + + void updateExponentialFog(Context ctx, + float red, float green, float blue, + float density) { + } + + + // --------------------------------------------------------------------- + + // + // LinearFogRetained methods + // + + void updateLinearFog(Context ctx, + float red, float green, float blue, + double fdist, double bdist) { + } + + + // --------------------------------------------------------------------- + + // + // LineAttributesRetained methods + // + + void updateLineAttributes(Context ctx, + float lineWidth, int linePattern, + int linePatternMask, + int linePatternScaleFactor, + boolean lineAntialiasing) { + } + + + // --------------------------------------------------------------------- + + // + // MaterialRetained methods + // + + void updateMaterial(Context ctx, + float red, float green, float blue, float alpha, + float ared, float agreen, float ablue, + float ered, float egreen, float eblue, + float dred, float dgreen, float dblue, + float sred, float sgreen, float sblue, + float shininess, int colorTarget, boolean enable) { + } + + + // --------------------------------------------------------------------- + + // + // ModelClipRetained methods + // + + void updateModelClip(Context ctx, int planeNum, boolean enableFlag, + double A, double B, double C, double D) { + } + + + // --------------------------------------------------------------------- + + // + // PointAttributesRetained methods + // + + void updatePointAttributes(Context ctx, float pointSize, boolean pointAntialiasing) { + } + + + // --------------------------------------------------------------------- + + // + // PolygonAttributesRetained methods + // + + void updatePolygonAttributes(Context ctx, + int polygonMode, int cullFace, + boolean backFaceNormalFlip, + float polygonOffset, + float polygonOffsetFactor) { + } + + + // --------------------------------------------------------------------- + + // + // RenderingAttributesRetained methods + // + + void updateRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride, + boolean depthBufferEnable, + boolean depthBufferWriteEnable, + int depthTestFunction, + float alphaTestValue, int alphaTestFunction, + boolean ignoreVertexColors, + boolean rasterOpEnable, int rasterOp, + boolean userStencilAvailable, boolean stencilEnable, + int stencilFailOp, int stencilZFailOp, int stencilZPassOp, + int stencilFunction, int stencilReferenceValue, + int stencilCompareMask, int stencilWriteMask ) { + } + + + // --------------------------------------------------------------------- + + // + // TexCoordGenerationRetained methods + // + + /** + * This method updates the native context: + * trans contains eyeTovworld transform in d3d + * trans contains vworldToEye transform in ogl + */ + void updateTexCoordGeneration(Context ctx, + boolean enable, int genMode, int format, + float planeSx, float planeSy, float planeSz, float planeSw, + float planeTx, float planeTy, float planeTz, float planeTw, + float planeRx, float planeRy, float planeRz, float planeRw, + float planeQx, float planeQy, float planeQz, float planeQw, + double[] trans) { + } + + + // --------------------------------------------------------------------- + + // + // TransparencyAttributesRetained methods + // + + void updateTransparencyAttributes(Context ctx, + float alpha, int geometryType, + int polygonMode, + boolean lineAA, boolean pointAA, + int transparencyMode, + int srcBlendFunction, + int dstBlendFunction) { + } + + + // --------------------------------------------------------------------- + + // + // TextureAttributesRetained methods + // + + void updateTextureAttributes(Context ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, float red, + float green, float blue, float alpha, + int textureFormat) { + } + + void updateRegisterCombiners(Context ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, float red, + float green, float blue, float alpha, + int textureFormat, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale) { + } + + void updateTextureColorTable(Context ctx, int numComponents, + int colorTableSize, + int[] colorTable) { + } + + void updateCombiner(Context ctx, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale) { + } + + + // --------------------------------------------------------------------- + + // + // TextureUnitStateRetained methods + // + + void updateTextureUnitState(Context ctx, int unitIndex, boolean enableFlag) { + } + + + // --------------------------------------------------------------------- + + // + // TextureRetained methods + // Texture2DRetained methods + // + + void bindTexture2D(Context ctx, int objectId, boolean enable) { + } + + void updateTexture2DImage(Context ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object data) { + } + + void updateTexture2DSubImage(Context ctx, + int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object data) { + } + + void updateTexture2DLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + } + + void updateTexture2DLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + } + + void updateTexture2DBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha) { + } + + void updateTexture2DFilterModes(Context ctx, + int minFilter, int magFilter) { + } + + void updateTexture2DSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + } + + void updateTexture2DFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + } + + void updateTexture2DAnisotropicFilter(Context ctx, float degree) { + } + + + // --------------------------------------------------------------------- + + // + // Texture3DRetained methods + // + + void bindTexture3D(Context ctx, int objectId, boolean enable) { + } + + void updateTexture3DImage(Context ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, int depth, + int boundaryWidth, + int imageDataType, Object imageData) { + } + + void updateTexture3DSubImage(Context ctx, + int level, + int xoffset, int yoffset, int zoffset, + int textureFormat, int imageFormat, + int imgXoffset, int imgYoffset, int imgZoffset, + int tilew, int tileh, + int width, int height, int depth, + int imageTypeData, Object imageData) { + } + + void updateTexture3DLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + } + + void updateTexture3DLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + } + + void updateTexture3DBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + int boundaryModeR, float boundaryRed, + float boundaryGreen, float boundaryBlue, + float boundaryAlpha) { + } + + void updateTexture3DFilterModes(Context ctx, + int minFilter, int magFilter) { + } + + void updateTexture3DSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + } + + void updateTexture3DFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + } + + void updateTexture3DAnisotropicFilter(Context ctx, float degree) { + } + + + // --------------------------------------------------------------------- + + // + // TextureCubeMapRetained methods + // + + void bindTextureCubeMap(Context ctx, int objectId, boolean enable) { + } + + void updateTextureCubeMapImage(Context ctx, + int face, int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object imageData) { + } + + void updateTextureCubeMapSubImage(Context ctx, + int face, int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object imageData) { + } + + void updateTextureCubeMapLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + } + + void updateTextureCubeMapLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + } + + void updateTextureCubeMapBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha) { + } + + void updateTextureCubeMapFilterModes(Context ctx, + int minFilter, int magFilter) { + } + + void updateTextureCubeMapSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + } + + void updateTextureCubeMapFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + } + + void updateTextureCubeMapAnisotropicFilter(Context ctx, float degree) { + } + + // --------------------------------------------------------------------- + + // + // MasterControl methods + // + + // Method to return the AWT object + long getAWT() { + return 0L; + } + + // Method to initialize the native J3D library + boolean initializeJ3D(boolean disableXinerama) { + return true; + } + + // Maximum lights supported by the native API + int getMaximumLights() { + return 8; + } + + + // --------------------------------------------------------------------- + + // + // Canvas3D methods - native wrappers + // + + // This is the native method for creating the underlying graphics context. + Context createNewContext(Canvas3D cv, long display, Drawable drawable, + long fbConfig, Context shareCtx, boolean isSharedCtx, + boolean offScreen, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + return new NoopContext(); + } + + void createQueryContext(Canvas3D cv, long display, Drawable drawable, + long fbConfig, boolean offScreen, int width, int height, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable) { + } + + // This is the native for creating offscreen buffer + Drawable createOffScreenBuffer(Canvas3D cv, Context ctx, long display, long fbConfig, int width, int height) { + return null; + } + + void destroyOffScreenBuffer(Canvas3D cv, Context ctx, long display, long fbConfig, Drawable drawable) { + } + + // This is the native for reading the image from the offscreen buffer + void readOffScreenBuffer(Canvas3D cv, Context ctx, int format, int type, Object data, int width, int height) { + } + + // The native method for swapBuffers + int swapBuffers(Canvas3D cv, Context ctx, long dpy, Drawable drawable) { + return 0; + } + + // notify D3D that Canvas is resize + int resizeD3DCanvas(Canvas3D cv, Context ctx) { + return 0; + } + + // notify D3D to toggle between FullScreen and window mode + int toggleFullScreenMode(Canvas3D cv, Context ctx) { + return 0; + } + + // native method for setting Material when no material is present + void updateMaterialColor(Context ctx, float r, float g, float b, float a) { + } + + void destroyContext(long display, Drawable drawable, Context ctx) { + } + + // This is the native method for doing accumulation. + void accum(Context ctx, float value) { + } + + // This is the native method for doing accumulation return. + void accumReturn(Context ctx) { + } + + // This is the native method for clearing the accumulation buffer. + void clearAccum(Context ctx) { + } + + // This is the native method for getting the number of lights the underlying + // native library can support. + int getNumCtxLights(Context ctx) { + return 0; + } + + // Native method for decal 1st child setup + boolean decal1stChildSetup(Context ctx) { + return false; + } + + // Native method for decal nth child setup + void decalNthChildSetup(Context ctx) { + } + + // Native method for decal reset + void decalReset(Context ctx, boolean depthBufferEnable) { + } + + // Native method for decal reset + void ctxUpdateEyeLightingEnable(Context ctx, boolean localEyeLightingEnable) { + } + + // The following three methods are used in multi-pass case + + // native method for setting blend color + void setBlendColor(Context ctx, float red, float green, + float blue, float alpha) { + } + + // native method for setting blend func + void setBlendFunc(Context ctx, int src, int dst) { + } + + // native method for setting fog enable flag + void setFogEnableFlag(Context ctx, boolean enableFlag) { + } + + // Setup the full scene antialising in D3D and ogl when GL_ARB_multisamle supported + void setFullSceneAntialiasing(Context ctx, boolean enable) { + } + + void setGlobalAlpha(Context ctx, float alpha) { + } + + // Native method to update separate specular color control + void updateSeparateSpecularColorEnable(Context ctx, boolean control) { + } + + // Initialization for D3D when scene begin + void beginScene(Context ctx) { + } + void endScene(Context ctx) { + } + + // True under Solaris, + // False under windows when display mode <= 8 bit + boolean validGraphicsMode() { + return true; + } + + // native method for setting light enables + void setLightEnables(Context ctx, long enableMask, int maxLights) { + } + + // native method for setting scene ambient + void setSceneAmbient(Context ctx, float red, float green, float blue) { + } + + // native method for disabling fog + void disableFog(Context ctx) { + } + + // native method for disabling modelClip + void disableModelClip(Context ctx) { + } + + // native method for setting default RenderingAttributes + void resetRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride) { + } + + // native method for setting default texture + void resetTextureNative(Context ctx, int texUnitIndex) { + } + + // native method for activating a particular texture unit + void activeTextureUnit(Context ctx, int texUnitIndex) { + } + + // native method for setting default TexCoordGeneration + void resetTexCoordGeneration(Context ctx) { + } + + // native method for setting default TextureAttributes + void resetTextureAttributes(Context ctx) { + } + + // native method for setting default PolygonAttributes + void resetPolygonAttributes(Context ctx) { + } + + // native method for setting default LineAttributes + void resetLineAttributes(Context ctx) { + } + + // native method for setting default PointAttributes + void resetPointAttributes(Context ctx) { + } + + // native method for setting default TransparencyAttributes + void resetTransparency(Context ctx, int geometryType, + int polygonMode, boolean lineAA, + boolean pointAA) { + } + + // native method for setting default ColoringAttributes + void resetColoringAttributes(Context ctx, + float r, float g, + float b, float a, + boolean enableLight) { + } + + /** + * This native method makes sure that the rendering for this canvas + * gets done now. + */ + void syncRender(Context ctx, boolean wait) { + } + + // The native method that sets this ctx to be the current one + boolean useCtx(Context ctx, long display, Drawable drawable) { + return true; + } + + void clear(Context ctx, float r, float g, float b) { + + } + + void textureFillBackground(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY) { + + } + + void textureFillRaster(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY, float mapZ, float alpha) { + + } + + void executeRasterDepth(Context ctx, float posX, float posY, float posZ, + int srcOffsetX, int srcOffsetY, int rasterWidth, int rasterHeight, + int depthWidth, int depthHeight, int depthType, Object depthData) { + + } + + // The native method for setting the ModelView matrix. + void setModelViewMatrix(Context ctx, double[] viewMatrix, double[] modelMatrix) { + } + + // The native method for setting the Projection matrix. + void setProjectionMatrix(Context ctx, double[] projMatrix) { + } + + // The native method for setting the Viewport. + void setViewport(Context ctx, int x, int y, int width, int height) { + } + + // used for display Lists + void newDisplayList(Context ctx, int displayListId) { + } + void endDisplayList(Context ctx) { + } + void callDisplayList(Context ctx, int id, boolean isNonUniformScale) { + } + + void freeDisplayList(Context ctx, int id) { + } + void freeTexture(Context ctx, int id) { + } + + void texturemapping(Context ctx, + int px, int py, + int xmin, int ymin, int xmax, int ymax, + int texWidth, int texHeight, + int rasWidth, + int format, int objectId, + byte[] image, + int winWidth, int winHeight) { + } + + boolean initTexturemapping(Context ctx, int texWidth, + int texHeight, int objectId) { + return true; + } + + + // Set internal render mode to one of FIELD_ALL, FIELD_LEFT or + // FIELD_RIGHT. Note that it is up to the caller to ensure that + // stereo is available before setting the mode to FIELD_LEFT or + // FIELD_RIGHT. The boolean isTRUE for double buffered mode, FALSE + // foe single buffering. + void setRenderMode(Context ctx, int mode, boolean doubleBuffer) { + } + + // Set glDepthMask. + void setDepthBufferWriteEnable(Context ctx, boolean mode) { + } + + + // --------------------------------------------------------------------- + + // + // Canvas3D / GraphicsConfigTemplate3D methods - logic dealing with + // native graphics configuration or drawing surface + // + + // Return a graphics config based on the one passed in. Note that we can + // assert that the input config is non-null and was created from a + // GraphicsConfigTemplate3D. + // This method must return a valid GraphicsConfig, or else it must throw + // an exception if one cannot be returned. + GraphicsConfiguration getGraphicsConfig(GraphicsConfiguration gconfig) { + System.err.println("NoopPipeline.getGraphicsConfig()"); + return gconfig; + } + + // Get the native FBconfig pointer + long getFbConfig(GraphicsConfigInfo gcInfo) { + return 0L; + } + + + // Get best graphics config from pipeline + GraphicsConfiguration getBestConfiguration(GraphicsConfigTemplate3D gct, + GraphicsConfiguration[] gc) { + + GraphicsConfiguration gc1 = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + // We need to cache the GraphicsTemplate3D + synchronized (Canvas3D.graphicsConfigTable) { + if (Canvas3D.graphicsConfigTable.get(gc1) == null) { + GraphicsConfigInfo gcInfo = new GraphicsConfigInfo(gct); +// gcInfo.setPrivateData(privateData); + Canvas3D.graphicsConfigTable.put(gc1, gcInfo); + } + } + return gc1; + } + + // Determine whether specified graphics config is supported by pipeline + boolean isGraphicsConfigSupported(GraphicsConfigTemplate3D gct, + GraphicsConfiguration gc) { + return true; + } + + // Methods to get actual capabilities from Canvas3D + boolean hasDoubleBuffer(Canvas3D cv) { + return true; + } + + boolean hasStereo(Canvas3D cv) { + return false; + } + + int getStencilSize(Canvas3D cv) { + return 0; + } + + boolean hasSceneAntialiasingMultisample(Canvas3D cv) { + return false; + } + + boolean hasSceneAntialiasingAccum(Canvas3D cv) { + return false; + } + + // Methods to get native WS display and screen + long getDisplay() { + return 0L; + } + + int getScreen(GraphicsDevice graphicsDevice) { + return 0; + } + + + // --------------------------------------------------------------------- + + // + // DrawingSurfaceObject methods + // + + // Method to construct a new DrawingSurfaceObject + DrawingSurfaceObject createDrawingSurfaceObject(Canvas3D cv) { + return new NoopDrawingSurfaceObject(cv); + } + + // Method to free the drawing surface object + void freeDrawingSurface(Canvas3D cv, DrawingSurfaceObject drawingSurfaceObject) { + // This method is a no-op + } + + // Method to free the native drawing surface object + void freeDrawingSurfaceNative(Object o) { + // This method is a no-op + } + + /** + * Dummy context for noop pipeline + */ + static class NoopContext implements Context { + } + +} diff --git a/src/classes/share/javax/media/j3d/NotificationThread.java b/src/classes/share/javax/media/j3d/NotificationThread.java index ac0598a..321213d 100644 --- a/src/classes/share/javax/media/j3d/NotificationThread.java +++ b/src/classes/share/javax/media/j3d/NotificationThread.java @@ -67,6 +67,9 @@ class NotificationThread extends Thread { case J3dNotification.SHADER_ERROR: n.universe.notifyShaderErrorListeners((ShaderError)n.args[0]); break; + case J3dNotification.RENDERING_ERROR: + VirtualUniverse.notifyRenderingErrorListeners((RenderingError)n.args[0]); + break; default: System.err.println("J3dNotification.processNotifications: unrecognized type = " + n.type); } diff --git a/src/classes/share/javax/media/j3d/OrderedGroupRetained.java b/src/classes/share/javax/media/j3d/OrderedGroupRetained.java index 5548178..f1bb2b9 100644 --- a/src/classes/share/javax/media/j3d/OrderedGroupRetained.java +++ b/src/classes/share/javax/media/j3d/OrderedGroupRetained.java @@ -74,7 +74,7 @@ class OrderedGroupRetained extends GroupRetained { System.arraycopy(cIOArr, 0, newArr, 0, newArr.length); J3dMessage m; - m = VirtualUniverse.mc.getMessage(); + m = new J3dMessage(); m.threads = J3dThread.UPDATE_RENDER; m.type = J3dMessage.ORDERED_GROUP_TABLE_CHANGED; m.universe = universe; diff --git a/src/classes/share/javax/media/j3d/OrientedShape3DRenderMethod.java b/src/classes/share/javax/media/j3d/OrientedShape3DRenderMethod.java index 945f974..8153e13 100644 --- a/src/classes/share/javax/media/j3d/OrientedShape3DRenderMethod.java +++ b/src/classes/share/javax/media/j3d/OrientedShape3DRenderMethod.java @@ -21,7 +21,7 @@ package javax.media.j3d; class OrientedShape3DRenderMethod implements RenderMethod { - public boolean render(RenderMolecule rm, Canvas3D cv, int pass, + public boolean render(RenderMolecule rm, Canvas3D cv, RenderAtomListInfo ra, int dirtyBits) { boolean useAlpha; boolean isNonUniformScale; @@ -35,7 +35,7 @@ class OrientedShape3DRenderMethod implements RenderMethod { rm.textureBin.attributeBin.ignoreVertexColors, cv.ctx); if (rm.doInfinite) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); while (ra != null) { trans = ra.infLocalToVworld; isNonUniformScale = !trans.isCongruent(); @@ -44,10 +44,8 @@ class OrientedShape3DRenderMethod implements RenderMethod { ra.geometry().execute(cv, ra.renderAtom, isNonUniformScale, (useAlpha && ra.geometry().noAlpha), rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, - rm.textureBin.attributeBin.ignoreVertexColors, - pass); + rm.textureBin.attributeBin.ignoreVertexColors); ra = ra.next; } return true; @@ -57,7 +55,7 @@ class OrientedShape3DRenderMethod implements RenderMethod { while (ra != null) { if (cv.ra == ra.renderAtom) { if (cv.raIsVisible) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); trans = ra.localToVworld; isNonUniformScale = !trans.isCongruent(); @@ -65,18 +63,16 @@ class OrientedShape3DRenderMethod implements RenderMethod { ra.geometry().execute(cv, ra.renderAtom, isNonUniformScale, (useAlpha && ra.geometry().noAlpha), rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, rm.textureBin.attributeBin. - ignoreVertexColors, - pass); + ignoreVertexColors); isVisible = true; } } else { if (!VirtualUniverse.mc.viewFrustumCulling || ra.renderAtom.localeVwcBounds.intersect(cv.viewFrustum)) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.raIsVisible = true; trans = ra.localToVworld; isNonUniformScale = !trans.isCongruent(); @@ -85,11 +81,9 @@ class OrientedShape3DRenderMethod implements RenderMethod { ra.geometry().execute(cv, ra.renderAtom, isNonUniformScale, (useAlpha && ra.geometry().noAlpha), rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, rm.textureBin.attributeBin. - ignoreVertexColors, - pass); + ignoreVertexColors); isVisible = true; } else { diff --git a/src/classes/share/javax/media/j3d/OrientedShape3DRetained.java b/src/classes/share/javax/media/j3d/OrientedShape3DRetained.java index 7c007b9..044876f 100644 --- a/src/classes/share/javax/media/j3d/OrientedShape3DRetained.java +++ b/src/classes/share/javax/media/j3d/OrientedShape3DRetained.java @@ -228,7 +228,7 @@ class OrientedShape3DRetained extends Shape3DRetained { } void sendChangedMessage(int component, Object attr) { - J3dMessage changeMessage = VirtualUniverse.mc.getMessage(); + J3dMessage changeMessage = new J3dMessage(); changeMessage.type = J3dMessage.ORIENTEDSHAPE3D_CHANGED; changeMessage.threads = targetThreads ; changeMessage.universe = universe; diff --git a/src/classes/share/javax/media/j3d/Pipeline.java b/src/classes/share/javax/media/j3d/Pipeline.java new file mode 100644 index 0000000..d06532a --- /dev/null +++ b/src/classes/share/javax/media/j3d/Pipeline.java @@ -0,0 +1,1403 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; + +/** + * Abstract pipeline class for rendering pipeline methods. All rendering + * pipeline methods are defined here. + */ +abstract class Pipeline { + // Singleton pipeline instance + private static Pipeline pipeline; + + // Supported rendering pipelines + enum Type { + // Native rendering pipelines using OGL or D3D library + NATIVE_OGL, + NATIVE_D3D, + + // Java rendering pipeline using Java Bindings for OpenGL + JOGL, + + // No-op rendering pipeline + NOOP, + } + + // Type of rendering pipeline (as defined above) + private Type pipelineType = null; + + protected Pipeline() { + } + + /** + * Initialize the Pipeline. Called exactly once by + * MasterControl.loadLibraries() to create the singleton + * Pipeline object. + */ + static void createPipeline(Type pipelineType) { + String className = null; + switch (pipelineType) { + case NATIVE_OGL: + case NATIVE_D3D: + className = "javax.media.j3d.NativePipeline"; + break; + case JOGL: + className = "javax.media.j3d.JoglPipeline"; + break; + case NOOP: + className = "javax.media.j3d.NoopPipeline"; + break; + default: + // Should not get here + throw new AssertionError("missing case statement"); + } + + final String pipelineClassName = className; + pipeline = (Pipeline) + java.security.AccessController.doPrivileged(new + java.security.PrivilegedAction() { + public Object run() { + try { + Class pipelineClass = Class.forName(pipelineClassName); + return pipelineClass.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + pipeline.initialize(pipelineType); + } + + /** + * Returns the singleton Pipeline object. + */ + static Pipeline getPipeline() { + return pipeline; + } + + /** + * Initializes the pipeline object. Only called by initPipeline. + * Pipeline subclasses may override this, but must call + * super.initialize(pipelineType); + */ + void initialize(Type pipelineType) { + setPipelineType(pipelineType); + } + + /** + * Sets the pipeline type. Only called by initialize. + */ + private void setPipelineType(Type pipelineType) { + this.pipelineType = pipelineType; + } + + /** + * Returns the pipeline type + */ + Type getPipelineType() { + return pipelineType; + } + + /** + * Returns the pipeline name + */ + String getPipelineName() { + switch (pipelineType) { + case NATIVE_OGL: + return "NATIVE_OGL"; + case NATIVE_D3D: + return "NATIVE_D3D"; + case JOGL: + return "JOGL"; + case NOOP: + return "NOOP"; + default: + // Should not get here + throw new AssertionError("missing case statement"); + } + } + + /** + * Returns the renderer name + */ + String getRendererName() { + switch (pipelineType) { + case NATIVE_OGL: + case JOGL: + return "OpenGL"; + case NATIVE_D3D: + return "DirectX"; + case NOOP: + return "None"; + default: + // Should not get here + throw new AssertionError("missing case statement"); + } + } + + + // --------------------------------------------------------------------- + + // + // Methods to initialize and load required libraries (from MasterControl) + // + + /** + * Load all of the required libraries + */ + abstract void loadLibraries(int globalShadingLanguage); + + /** + * Returns true if the Cg library is loaded and available. Note that this + * does not necessarily mean that Cg is supported by the graphics card. + */ + abstract boolean isCgLibraryAvailable(); + + /** + * Returns true if the GLSL library is loaded and available. Note that this + * does not necessarily mean that GLSL is supported by the graphics card. + */ + abstract boolean isGLSLLibraryAvailable(); + + + // --------------------------------------------------------------------- + + // + // GeometryArrayRetained methods + // + + // Used by D3D to free vertex buffer + abstract void freeD3DArray(GeometryArrayRetained geo, boolean deleteVB); + + // used for GeometryArrays by Copy or interleaved + abstract void execute(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + int vertexAttrCount, int[] vertexAttrSizes, + float[] varray, float[] cdata, int cdirty); + + // used by GeometryArray by Reference with java arrays + abstract void executeVA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty); + + // used by GeometryArray by Reference with NIO buffer + abstract void executeVABuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, + Object vcoords, + int colorIndex, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + int normalIndex, Object ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, Object[] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty); + + // used by GeometryArray by Reference in interleaved format with NIO buffer + abstract void executeInterleavedBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object varray, float[] cdata, int cdirty); + + abstract void setVertexFormat(Context ctx, GeometryArrayRetained geo, + int vformat, boolean useAlpha, boolean ignoreVertexColors); + + abstract void disableGlobalAlpha(Context ctx, GeometryArrayRetained geo, int vformat, + boolean useAlpha, boolean ignoreVertexColors); + + // used for GeometryArrays + abstract void buildGA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int startVIndex, + int vcount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, int[] texCoordSetMapOffset, + int vertexAttrCount, int[] vertexAttrSizes, + double[] xform, double[] nxform, + float[] varray); + + // used to Build Dlist GeometryArray by Reference with java arrays + abstract void buildGAForByRef(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int[] texIndex, int texstride, Object[] texCoords, + double[] xform, double[] nxform); + + // used to Build Dlist GeometryArray by Reference with NIO buffer + // NOTE: NIO buffers are no longer supported in display lists. We + // have no plans to add this support. + /* + abstract void buildGAForBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, Object vcoords, + int colorIndex, Object cdata, + int normalIndex, Object ndata, + int texcoordmaplength, + int[] texcoordoffset, + int[] texIndex, int texstride, Object[] texCoords, + double[] xform, double[] nxform); + */ + + + // --------------------------------------------------------------------- + + // + // IndexedGeometryArrayRetained methods + // + + // by-copy or interleaved, by reference, Java arrays + abstract void executeIndexedGeometry(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + float[] varray, float[] cdata, + int cdirty, + int[] indexCoord); + + // interleaved, by reference, nio buffer + abstract void executeIndexedGeometryBuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + Object varray, float[] cdata, + int cdirty, + int[] indexCoord); + + // non interleaved, by reference, Java arrays + abstract void executeIndexedGeometryVA(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + float[] vfcoords, double[] vdcoords, + float[] cfdata, byte[] cbdata, + float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord); + + // non interleaved, by reference, nio buffer + abstract void executeIndexedGeometryVABuffer(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + Object vcoords, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + Object normal, + int vertexAttrCount, int[] vertexAttrSizes, + Object[] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord); + + // by-copy geometry + abstract void buildIndexedGeometry(Context ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int[] texCoordSetMap, + int texCoordSetMapLen, + int[] texCoordSetMapOffset, + double[] xform, double[] nxform, + float[] varray, int[] indexCoord); + + + // --------------------------------------------------------------------- + + // + // GraphicsContext3D methods + // + + // Native method for readRaster + abstract void readRaster(Context ctx, + int type, int xSrcOffset, int ySrcOffset, + int width, int height, int hCanvas, + int imageDataType, + int imageFormat, + Object imageBuffer, + int depthFormat, + Object depthBuffer); + + // --------------------------------------------------------------------- + + // + // CgShaderProgramRetained methods + // + + // ShaderAttributeValue methods + + abstract ShaderError setCgUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value); + + abstract ShaderError setCgUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value); + + abstract ShaderError setCgUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value); + + abstract ShaderError setCgUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + abstract ShaderError setCgUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value); + + abstract ShaderError setCgUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + abstract ShaderError setCgUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value); + + abstract ShaderError setCgUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + abstract ShaderError setCgUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + abstract ShaderError setCgUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + // ShaderAttributeArray methods + + abstract ShaderError setCgUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setCgUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setCgUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setCgUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setCgUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setCgUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setCgUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setCgUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setCgUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setCgUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + // abstract interfaces for shader compilation, etc. + abstract ShaderError createCgShader(Context ctx, int shaderType, ShaderId[] shaderId); + abstract ShaderError destroyCgShader(Context ctx, ShaderId shaderId); + abstract ShaderError compileCgShader(Context ctx, ShaderId shaderId, String program); + + abstract ShaderError createCgShaderProgram(Context ctx, ShaderProgramId[] shaderProgramId); + abstract ShaderError destroyCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId); + abstract ShaderError linkCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId, + ShaderId[] shaderIds); + abstract void lookupCgVertexAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, boolean[] errArr); + abstract void lookupCgShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, ShaderAttrLoc[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr); + + abstract ShaderError useCgShaderProgram(Context ctx, ShaderProgramId shaderProgramId); + + + // --------------------------------------------------------------------- + + // + // GLSLShaderProgramRetained methods + // + + // ShaderAttributeValue methods + + abstract ShaderError setGLSLUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int value); + + abstract ShaderError setGLSLUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float value); + + abstract ShaderError setGLSLUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value); + + abstract ShaderError setGLSLUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + abstract ShaderError setGLSLUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value); + + abstract ShaderError setGLSLUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + abstract ShaderError setGLSLUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int[] value); + + abstract ShaderError setGLSLUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + abstract ShaderError setGLSLUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + abstract ShaderError setGLSLUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + float[] value); + + // ShaderAttributeArray methods + + abstract ShaderError setGLSLUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setGLSLUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setGLSLUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setGLSLUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setGLSLUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setGLSLUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setGLSLUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setGLSLUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setGLSLUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setGLSLUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, + int numElements, + float[] value); + + // abstract interfaces for shader compilation, etc. + abstract ShaderError createGLSLShader(Context ctx, int shaderType, ShaderId[] shaderId); + abstract ShaderError destroyGLSLShader(Context ctx, ShaderId shaderId); + abstract ShaderError compileGLSLShader(Context ctx, ShaderId shaderId, String program); + + abstract ShaderError createGLSLShaderProgram(Context ctx, ShaderProgramId[] shaderProgramId); + abstract ShaderError destroyGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId); + abstract ShaderError linkGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId, + ShaderId[] shaderIds); + abstract ShaderError bindGLSLVertexAttrName(Context ctx, ShaderProgramId shaderProgramId, + String attrName, int attrIndex); + abstract void lookupGLSLShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, + int numAttrNames, String[] attrNames, ShaderAttrLoc[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr); + + abstract ShaderError useGLSLShaderProgram(Context ctx, ShaderProgramId shaderProgramId); + + + // --------------------------------------------------------------------- + + // + // ImageComponent2DRetained methods + // + + // free d3d surface referred to by id + abstract void freeD3DSurface(ImageComponent2DRetained image, int hashId); + + + // --------------------------------------------------------------------- + + // + // J3DBuffer methods + // + + // Method to verify that we can access a direct NIO buffer + // from native code + boolean checkNativeBufferAccess(java.nio.Buffer buffer) { + // Return true by default. Pipeline can override and implement, if + // we decide that it is necessary. + return true; + } + + // --------------------------------------------------------------------- + + // + // Renderer methods + // + + abstract void cleanupRenderer(); + + + // --------------------------------------------------------------------- + + // + // ColoringAttributesRetained methods + // + + abstract void updateColoringAttributes(Context ctx, + float dRed, float dGreen, float dBlue, + float red, float green, float blue, + float alpha, + boolean lEnable, + int shadeModel); + + + // --------------------------------------------------------------------- + + // + // DirectionalLightRetained methods + // + + abstract void updateDirectionalLight(Context ctx, + int lightSlot, float red, float green, + float blue, float x, float y, float z); + + + // --------------------------------------------------------------------- + + // + // PointLightRetained methods + // + + abstract void updatePointLight(Context ctx, + int lightSlot, float red, float green, + float blue, float ax, float ay, float az, + float px, float py, float pz); + + + // --------------------------------------------------------------------- + + // + // SpotLightRetained methods + // + + abstract void updateSpotLight(Context ctx, + int lightSlot, float red, float green, + float blue, float ax, float ay, float az, + float px, float py, float pz, float spreadAngle, + float concentration, float dx, float dy, + float dz); + + + // --------------------------------------------------------------------- + + // + // ExponentialFogRetained methods + // + + abstract void updateExponentialFog(Context ctx, + float red, float green, float blue, + float density); + + + // --------------------------------------------------------------------- + + // + // LinearFogRetained methods + // + + abstract void updateLinearFog(Context ctx, + float red, float green, float blue, + double fdist, double bdist); + + + // --------------------------------------------------------------------- + + // + // LineAttributesRetained methods + // + + abstract void updateLineAttributes(Context ctx, + float lineWidth, int linePattern, + int linePatternMask, + int linePatternScaleFactor, + boolean lineAntialiasing); + + + // --------------------------------------------------------------------- + + // + // MaterialRetained methods + // + + abstract void updateMaterial(Context ctx, + float red, float green, float blue, float alpha, + float ared, float agreen, float ablue, + float ered, float egreen, float eblue, + float dred, float dgreen, float dblue, + float sred, float sgreen, float sblue, + float shininess, int colorTarget, boolean enable); + + + // --------------------------------------------------------------------- + + // + // ModelClipRetained methods + // + + abstract void updateModelClip(Context ctx, int planeNum, boolean enableFlag, + double A, double B, double C, double D); + + + // --------------------------------------------------------------------- + + // + // PointAttributesRetained methods + // + + abstract void updatePointAttributes(Context ctx, float pointSize, boolean pointAntialiasing); + + + // --------------------------------------------------------------------- + + // + // PolygonAttributesRetained methods + // + + abstract void updatePolygonAttributes(Context ctx, + int polygonMode, int cullFace, + boolean backFaceNormalFlip, + float polygonOffset, + float polygonOffsetFactor); + + + // --------------------------------------------------------------------- + + // + // RenderingAttributesRetained methods + // + + abstract void updateRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride, + boolean depthBufferEnable, + boolean depthBufferWriteEnable, + int depthTestFunction, + float alphaTestValue, int alphaTestFunction, + boolean ignoreVertexColors, + boolean rasterOpEnable, int rasterOp, + boolean userStencilAvailable, boolean stencilEnable, + int stencilFailOp, int stencilZFailOp, int stencilZPassOp, + int stencilFunction, int stencilReferenceValue, + int stencilCompareMask, int stencilWriteMask ); + + + // --------------------------------------------------------------------- + + // + // TexCoordGenerationRetained methods + // + + /** + * This method updates the native context: + * trans contains eyeTovworld transform in d3d + * trans contains vworldToEye transform in ogl + */ + abstract void updateTexCoordGeneration(Context ctx, + boolean enable, int genMode, int format, + float planeSx, float planeSy, float planeSz, float planeSw, + float planeTx, float planeTy, float planeTz, float planeTw, + float planeRx, float planeRy, float planeRz, float planeRw, + float planeQx, float planeQy, float planeQz, float planeQw, + double[] trans); + + + // --------------------------------------------------------------------- + + // + // TransparencyAttributesRetained methods + // + + abstract void updateTransparencyAttributes(Context ctx, + float alpha, int geometryType, + int polygonMode, + boolean lineAA, boolean pointAA, + int transparencyMode, + int srcBlendFunction, + int dstBlendFunction); + + + // --------------------------------------------------------------------- + + // + // TextureAttributesRetained methods + // + + abstract void updateTextureAttributes(Context ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, float red, + float green, float blue, float alpha, + int textureFormat); + + abstract void updateRegisterCombiners(Context ctx, + double[] transform, boolean isIdentity, int textureMode, + int perspCorrectionMode, float red, + float green, float blue, float alpha, + int textureFormat, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale); + + abstract void updateTextureColorTable(Context ctx, int numComponents, + int colorTableSize, + int[] colorTable); + + abstract void updateCombiner(Context ctx, + int combineRgbMode, int combineAlphaMode, + int[] combineRgbSrc, int[] combineAlphaSrc, + int[] combineRgbFcn, int[] combineAlphaFcn, + int combineRgbScale, int combineAlphaScale); + + + // --------------------------------------------------------------------- + + // + // TextureUnitStateRetained methods + // + + abstract void updateTextureUnitState(Context ctx, int unitIndex, boolean enableFlag); + + + // --------------------------------------------------------------------- + + // + // TextureRetained methods + // Texture2DRetained methods + // + + abstract void bindTexture2D(Context ctx, int objectId, boolean enable); + + abstract void updateTexture2DImage(Context ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object data); + + abstract void updateTexture2DSubImage(Context ctx, + int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object data); + + abstract void updateTexture2DLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod); + + abstract void updateTexture2DLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ); + + abstract void updateTexture2DBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha); + + abstract void updateTexture2DFilterModes(Context ctx, + int minFilter, int magFilter); + + abstract void updateTexture2DSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts); + + abstract void updateTexture2DFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts); + + abstract void updateTexture2DAnisotropicFilter(Context ctx, float degree); + + + // --------------------------------------------------------------------- + + // + // Texture3DRetained methods + // + + abstract void bindTexture3D(Context ctx, int objectId, boolean enable); + + abstract void updateTexture3DImage(Context ctx, + int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, int depth, + int boundaryWidth, + int imageDataType, Object imageData); + + abstract void updateTexture3DSubImage(Context ctx, + int level, + int xoffset, int yoffset, int zoffset, + int textureFormat, int imageFormat, + int imgXoffset, int imgYoffset, int imgZoffset, + int tilew, int tileh, + int width, int height, int depth, + int imageDataType, Object imageData); + + abstract void updateTexture3DLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod); + + abstract void updateTexture3DLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ); + + abstract void updateTexture3DBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + int boundaryModeR, float boundaryRed, + float boundaryGreen, float boundaryBlue, + float boundaryAlpha); + + abstract void updateTexture3DFilterModes(Context ctx, + int minFilter, int magFilter); + + abstract void updateTexture3DSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts); + + abstract void updateTexture3DFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts); + + abstract void updateTexture3DAnisotropicFilter(Context ctx, float degree); + + + // --------------------------------------------------------------------- + + // + // TextureCubeMapRetained methods + // + + abstract void bindTextureCubeMap(Context ctx, int objectId, boolean enable); + + abstract void updateTextureCubeMapImage(Context ctx, + int face, int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object imageData); + + abstract void updateTextureCubeMapSubImage(Context ctx, + int face, int level, int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object imageData); + + abstract void updateTextureCubeMapLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod); + + abstract void updateTextureCubeMapLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ); + + abstract void updateTextureCubeMapBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha); + + abstract void updateTextureCubeMapFilterModes(Context ctx, + int minFilter, int magFilter); + + abstract void updateTextureCubeMapSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts); + + abstract void updateTextureCubeMapFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts); + + abstract void updateTextureCubeMapAnisotropicFilter(Context ctx, float degree); + + // --------------------------------------------------------------------- + + // + // MasterControl methods + // + + // Method to return the AWT object + abstract long getAWT(); + + // Method to initialize the native J3D library + abstract boolean initializeJ3D(boolean disableXinerama); + + // Maximum lights supported by the native API + abstract int getMaximumLights(); + + + // --------------------------------------------------------------------- + + // + // Canvas3D methods - native wrappers + // + + // This is the native method for creating the underlying graphics context. + abstract Context createNewContext(Canvas3D cv, long display, Drawable drawable, + long fbConfig, Context shareCtx, boolean isSharedCtx, + boolean offScreen, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable); + + abstract void createQueryContext(Canvas3D cv, long display, Drawable drawable, + long fbConfig, boolean offScreen, int width, int height, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable); + + // This is the native for creating offscreen buffer + abstract Drawable createOffScreenBuffer(Canvas3D cv, Context ctx, long display, long fbConfig, int width, int height); + + abstract void destroyOffScreenBuffer(Canvas3D cv, Context ctx, long display, long fbConfig, Drawable drawable); + + // This is the native for reading the image from the offscreen buffer + abstract void readOffScreenBuffer(Canvas3D cv, Context ctx, int format, int type, Object data, int width, int height); + + // The native method for swapBuffers + abstract int swapBuffers(Canvas3D cv, Context ctx, long dpy, Drawable drawable); + + // notify D3D that Canvas is resize + abstract int resizeD3DCanvas(Canvas3D cv, Context ctx); + + // notify D3D to toggle between FullScreen and window mode + abstract int toggleFullScreenMode(Canvas3D cv, Context ctx); + + // native method for setting Material when no material is present + abstract void updateMaterialColor(Context ctx, float r, float g, float b, float a); + + abstract void destroyContext(long display, Drawable drawable, Context ctx); + + // This is the native method for doing accumulation. + abstract void accum(Context ctx, float value); + + // This is the native method for doing accumulation return. + abstract void accumReturn(Context ctx); + + // This is the native method for clearing the accumulation buffer. + abstract void clearAccum(Context ctx); + + // This is the native method for getting the number of lights the underlying + // native library can support. + abstract int getNumCtxLights(Context ctx); + + // Native method for decal 1st child setup + abstract boolean decal1stChildSetup(Context ctx); + + // Native method for decal nth child setup + abstract void decalNthChildSetup(Context ctx); + + // Native method for decal reset + abstract void decalReset(Context ctx, boolean depthBufferEnable); + + // Native method for decal reset + abstract void ctxUpdateEyeLightingEnable(Context ctx, boolean localEyeLightingEnable); + + // The following three methods are used in multi-pass case + + // native method for setting blend color + abstract void setBlendColor(Context ctx, float red, float green, + float blue, float alpha); + + // native method for setting blend func + abstract void setBlendFunc(Context ctx, int src, int dst); + + // native method for setting fog enable flag + abstract void setFogEnableFlag(Context ctx, boolean enableFlag); + + // Setup the full scene antialising in D3D and ogl when GL_ARB_multisamle supported + abstract void setFullSceneAntialiasing(Context ctx, boolean enable); + + abstract void setGlobalAlpha(Context ctx, float alpha); + + // Native method to update separate specular color control + abstract void updateSeparateSpecularColorEnable(Context ctx, boolean control); + + // Initialization for D3D when scene begin + abstract void beginScene(Context ctx); + abstract void endScene(Context ctx); + + // True under Solaris, + // False under windows when display mode <= 8 bit + abstract boolean validGraphicsMode(); + + // native method for setting light enables + abstract void setLightEnables(Context ctx, long enableMask, int maxLights); + + // native method for setting scene ambient + abstract void setSceneAmbient(Context ctx, float red, float green, float blue); + + // native method for disabling fog + abstract void disableFog(Context ctx); + + // native method for disabling modelClip + abstract void disableModelClip(Context ctx); + + // native method for setting default RenderingAttributes + abstract void resetRenderingAttributes(Context ctx, + boolean depthBufferWriteEnableOverride, + boolean depthBufferEnableOverride); + + // native method for setting default texture + abstract void resetTextureNative(Context ctx, int texUnitIndex); + + // native method for activating a particular texture unit + abstract void activeTextureUnit(Context ctx, int texUnitIndex); + + // native method for setting default TexCoordGeneration + abstract void resetTexCoordGeneration(Context ctx); + + // native method for setting default TextureAttributes + abstract void resetTextureAttributes(Context ctx); + + // native method for setting default PolygonAttributes + abstract void resetPolygonAttributes(Context ctx); + + // native method for setting default LineAttributes + abstract void resetLineAttributes(Context ctx); + + // native method for setting default PointAttributes + abstract void resetPointAttributes(Context ctx); + + // native method for setting default TransparencyAttributes + abstract void resetTransparency(Context ctx, int geometryType, + int polygonMode, boolean lineAA, + boolean pointAA); + + // native method for setting default ColoringAttributes + abstract void resetColoringAttributes(Context ctx, + float r, float g, + float b, float a, + boolean enableLight); + + /** + * This native method makes sure that the rendering for this canvas + * gets done now. + */ + abstract void syncRender(Context ctx, boolean wait); + + // The native method that sets this ctx to be the current one + abstract boolean useCtx(Context ctx, long display, Drawable drawable); + + // Optionally release the context. A pipeline may override this and + // returns true if the context was released. + boolean releaseCtx(Context ctx, long dpy) { + return false; + } + + abstract void clear(Context ctx, float r, float g, float b); + + abstract void textureFillBackground(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY); + + abstract void textureFillRaster(Context ctx, float texMinU, float texMaxU, float texMinV, float texMaxV, + float mapMinX, float mapMaxX, float mapMinY, float mapMaxY, float mapZ, float alpha); + + abstract void executeRasterDepth(Context ctx, float posX, float posY, float posZ, + int srcOffsetX, int srcOffsetY, int rasterWidth, int rasterHeight, int depthWidth, int depthHeight, + int depthType, Object depthData); + + // The native method for setting the ModelView matrix. + abstract void setModelViewMatrix(Context ctx, double[] viewMatrix, double[] modelMatrix); + + // The native method for setting the Projection matrix. + abstract void setProjectionMatrix(Context ctx, double[] projMatrix); + + // The native method for setting the Viewport. + abstract void setViewport(Context ctx, int x, int y, int width, int height); + + // used for display Lists + abstract void newDisplayList(Context ctx, int displayListId); + abstract void endDisplayList(Context ctx); + abstract void callDisplayList(Context ctx, int id, boolean isNonUniformScale); + + abstract void freeDisplayList(Context ctx, int id); + abstract void freeTexture(Context ctx, int id); + + abstract void texturemapping(Context ctx, + int px, int py, + int xmin, int ymin, int xmax, int ymax, + int texWidth, int texHeight, + int rasWidth, + int format, int objectId, + byte[] image, + int winWidth, int winHeight); + + abstract boolean initTexturemapping(Context ctx, int texWidth, + int texHeight, int objectId); + + + // Set internal render mode to one of FIELD_ALL, FIELD_LEFT or + // FIELD_RIGHT. Note that it is up to the caller to ensure that + // stereo is available before setting the mode to FIELD_LEFT or + // FIELD_RIGHT. The boolean isTRUE for double buffered mode, FALSE + // foe single buffering. + abstract void setRenderMode(Context ctx, int mode, boolean doubleBuffer); + + // Set glDepthMask. + abstract void setDepthBufferWriteEnable(Context ctx, boolean mode); + + + // --------------------------------------------------------------------- + + // + // Canvas3D / GraphicsConfigTemplate3D methods - logic dealing with + // native graphics configuration or drawing surface + // + + // Return a graphics config based on the one passed in. Note that we can + // assert that the input config is non-null and was created from a + // GraphicsConfigTemplate3D. + // This method must return a valid GraphicsConfig, or else it must throw + // an exception if one cannot be returned. + abstract GraphicsConfiguration getGraphicsConfig(GraphicsConfiguration gconfig); + + // Get the native FBconfig pointer + abstract long getFbConfig(GraphicsConfigInfo gcInfo); + + // Get best graphics config from pipeline + abstract GraphicsConfiguration getBestConfiguration(GraphicsConfigTemplate3D gct, + GraphicsConfiguration[] gc); + + // Determine whether specified graphics config is supported by pipeline + abstract boolean isGraphicsConfigSupported(GraphicsConfigTemplate3D gct, + GraphicsConfiguration gc); + + // Methods to get actual capabilities from Canvas3D + abstract boolean hasDoubleBuffer(Canvas3D cv); + abstract boolean hasStereo(Canvas3D cv); + abstract int getStencilSize(Canvas3D cv); + abstract boolean hasSceneAntialiasingMultisample(Canvas3D cv); + abstract boolean hasSceneAntialiasingAccum(Canvas3D cv); + + // Methods to get native WS display and screen + abstract long getDisplay(); + abstract int getScreen(GraphicsDevice graphicsDevice); + + + // --------------------------------------------------------------------- + + // + // DrawingSurfaceObject methods + // + + // Method to construct a new DrawingSurfaceObject + abstract DrawingSurfaceObject createDrawingSurfaceObject(Canvas3D cv); + + // Method to free the drawing surface object + abstract void freeDrawingSurface(Canvas3D cv, DrawingSurfaceObject drawingSurfaceObject); + + // Method to free the native drawing surface object + abstract void freeDrawingSurfaceNative(Object o); + +} diff --git a/src/classes/share/javax/media/j3d/PointAttributesRetained.java b/src/classes/share/javax/media/j3d/PointAttributesRetained.java index b5d7536..207119b 100644 --- a/src/classes/share/javax/media/j3d/PointAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/PointAttributesRetained.java @@ -112,13 +112,8 @@ class PointAttributesRetained extends NodeComponentRetained { /** * Update the native context */ - native void updateNative(long ctx, float pointSize, boolean pointAntialiasing); - - /** - * Update the native context - */ - void updateNative(long ctx) { - updateNative(ctx, pointSize, pointAntialiasing); + void updateNative(Context ctx) { + Pipeline.getPipeline().updatePointAttributes(ctx, pointSize, pointAntialiasing); } @@ -167,7 +162,7 @@ class PointAttributesRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.POINTATTRIBUTES_CHANGED; createMessage.universe = null; @@ -180,7 +175,7 @@ class PointAttributesRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.POINTATTRIBUTES_CHANGED; diff --git a/src/classes/share/javax/media/j3d/PointLightRetained.java b/src/classes/share/javax/media/j3d/PointLightRetained.java index 34f390e..d93926f 100644 --- a/src/classes/share/javax/media/j3d/PointLightRetained.java +++ b/src/classes/share/javax/media/j3d/PointLightRetained.java @@ -173,18 +173,14 @@ class PointLightRetained extends LightRetained { * updates a point light. This includes its color, attenuation, * and its transformed position. */ - native void updateLight(long ctx, int lightSlot, float red, float green, - float blue, float ax, float ay, float az, - float px, float py, float pz); - - void update(long ctx, int lightSlot, double scale) { + void update(Context ctx, int lightSlot, double scale) { validateAttenuationInEc(scale); - updateLight(ctx, lightSlot, color.x, color.y, color.z, - attenuation.x, linearAttenuationInEc, - quadraticAttenuationInEc, - xformPosition.x, xformPosition.y, - xformPosition.z); - + Pipeline.getPipeline().updatePointLight(ctx, + lightSlot, color.x, color.y, color.z, + attenuation.x, linearAttenuationInEc, + quadraticAttenuationInEc, + xformPosition.x, xformPosition.y, + xformPosition.z); } void setLive(SetLiveState s) { @@ -300,7 +296,7 @@ class PointLightRetained extends LightRetained { void sendMessage(int attrMask, Object attr) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.universe = universe; createMessage.type = J3dMessage.LIGHT_CHANGED; diff --git a/src/classes/share/javax/media/j3d/PolygonAttributesRetained.java b/src/classes/share/javax/media/j3d/PolygonAttributesRetained.java index 1dbcc6c..243c6db 100644 --- a/src/classes/share/javax/media/j3d/PolygonAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/PolygonAttributesRetained.java @@ -235,19 +235,10 @@ class PolygonAttributesRetained extends NodeComponentRetained { /** * Updates the native context */ - native void updateNative(long ctx, - int polygonMode, int cullFace, - boolean backFaceNormalFlip, - float polygonOffset, - float polygonOffsetFactor); - - /** - * Updates the native context - */ - void updateNative(long ctx) { - updateNative(ctx, - polygonMode, cullFace, backFaceNormalFlip, - polygonOffset, polygonOffsetFactor); + void updateNative(Context ctx) { + Pipeline.getPipeline().updatePolygonAttributes(ctx, + polygonMode, cullFace, backFaceNormalFlip, + polygonOffset, polygonOffsetFactor); } /** @@ -308,7 +299,7 @@ class PolygonAttributesRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.POLYGONATTRIBUTES_CHANGED; createMessage.universe = null; @@ -320,7 +311,7 @@ class PolygonAttributesRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.POLYGONATTRIBUTES_CHANGED; diff --git a/src/classes/share/javax/media/j3d/QuadArrayRetained.java b/src/classes/share/javax/media/j3d/QuadArrayRetained.java index a2ceb62..ab47626 100644 --- a/src/classes/share/javax/media/j3d/QuadArrayRetained.java +++ b/src/classes/share/javax/media/j3d/QuadArrayRetained.java @@ -438,13 +438,13 @@ class QuadArrayRetained extends GeometryArrayRetained { int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); - Point3d pnt0 = getPoint3d(); - Point3d pnt1 = getPoint3d(); - Point3d pnt2 = getPoint3d(); - Point3d pnt3 = getPoint3d(); - Vector3d vec = getVector3d(); - Vector3d normal = getVector3d(); - Vector3d tmpvec = getVector3d(); + Point3d pnt0 = new Point3d(); + Point3d pnt1 = new Point3d(); + Point3d pnt2 = new Point3d(); + Point3d pnt3 = new Point3d(); + Vector3d vec = new Vector3d(); + Vector3d normal = new Vector3d(); + Vector3d tmpvec = new Vector3d(); double area; double totalarea = 0; @@ -497,13 +497,6 @@ class QuadArrayRetained extends GeometryArrayRetained { centroid.y *= area; centroid.z *= area; } - freeVector3d(tmpvec); - freeVector3d(vec); - freeVector3d(normal); - freePoint3d(pnt0); - freePoint3d(pnt1); - freePoint3d(pnt2); - freePoint3d(pnt3); } int getClassType() { diff --git a/src/classes/share/javax/media/j3d/Raster.java b/src/classes/share/javax/media/j3d/Raster.java index f65cd07..1bdbe55 100644 --- a/src/classes/share/javax/media/j3d/Raster.java +++ b/src/classes/share/javax/media/j3d/Raster.java @@ -226,6 +226,9 @@ public class Raster extends Geometry { * color data * @param depthComponent the DepthComponent object containing the depth * (z-buffer) data + * + * @exception IllegalArgumentException if the image class of the specified + * ImageComponent2D is ImageClass.NIO_IMAGE_BUFFER. */ public Raster(Point3f pos, int type, @@ -259,7 +262,10 @@ public class Raster extends Geometry { * @param image the ImageComponent2D object containing the * color data * @param depthComponent the DepthComponent object containing the depth - * (z-buffer) data + * (z-buffer) data + * + * @exception IllegalArgumentException if the image class of the specified + * ImageComponent2D is ImageClass.NIO_IMAGE_BUFFER. */ public Raster(Point3f pos, int type, @@ -297,6 +303,9 @@ public class Raster extends Geometry { * @param depthComponent the DepthComponent object containing the depth * (z-buffer) data * + * @exception IllegalArgumentException if the image class of the specified + * ImageComponent2D is ImageClass.NIO_IMAGE_BUFFER. + * * @since Java 3D 1.3 */ public Raster(Point3f pos, @@ -308,6 +317,7 @@ public class Raster extends Geometry { ImageComponent2D image, DepthComponent depthComponent) { + // set default read capabilities setDefaultReadCapabilities(readCapabilities); @@ -617,15 +627,36 @@ public class Raster extends Geometry { /** * Sets the pixel array used to copy pixels to/from a Canvas3D. * This is used when the type is RASTER_COLOR or RASTER_COLOR_DEPTH. + * * @param image the ImageComponent2D object containing the * color data + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * + * @exception IllegalSharingException if this Raster is live and + * the specified image is being used by a Canvas3D as an off-screen buffer. + * + * @exception IllegalArgumentException if the image class of the specified + * ImageComponent2D is ImageClass.NIO_IMAGE_BUFFER. + * */ public void setImage(ImageComponent2D image) { + if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_IMAGE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("Raster3")); + + // Do illegal sharing check + if(image != null) { + ImageComponent2DRetained imageRetained = (ImageComponent2DRetained) image.retained; + if(imageRetained.getUsedByOffScreen()) { + if(isLive()) { + throw new IllegalSharingException(J3dI18N.getString("Raster12")); + } + } + } + ((RasterRetained)this.retained).setImage(image); } diff --git a/src/classes/share/javax/media/j3d/RasterRetained.java b/src/classes/share/javax/media/j3d/RasterRetained.java index 85356a7..5a20a45 100644 --- a/src/classes/share/javax/media/j3d/RasterRetained.java +++ b/src/classes/share/javax/media/j3d/RasterRetained.java @@ -31,37 +31,20 @@ class RasterRetained extends GeometryRetained { */ int type = Raster.RASTER_COLOR; - int clipMode = Raster.CLIP_POSITION; - Point3f position = new Point3f(); - int xSrcOffset = 0; - int ySrcOffset = 0; - - // Used internally in CLIP_IMAGE mode - private int xOffset = 0; - private int yOffset = 0; - - int width = 0; - int height = 0; - int xDstOffset = 0; - int yDstOffset = 0; + private int clipMode = Raster.CLIP_POSITION; + private Point3f position = new Point3f(); + private int xSrcOffset = 0; + private int ySrcOffset = 0; + private int width = 0; + private int height = 0; + private int xDstOffset = 0; + private int yDstOffset = 0; ImageComponent2DRetained image = null; + Texture2DRetained texture = null; DepthComponentRetained depthComponent = null; - float lastAlpha = 1.0f; - - private Point3d adjPos; // Position of the Raster after adjusting for dstOffset - private Point2d winCoord; // Position of Raster in window coordinates - private Transform3D vwip; // Vworld to Image plate transform - // false when computeWinCoord() get null RenderMolecule. - // In this case rendering is skip. - private boolean validVwip; - RasterRetained() { this.geoType = GEO_TYPE_RASTER; - - vwip = new Transform3D(); - adjPos = new Point3d(); - winCoord = new Point2d(); } /** @@ -183,18 +166,16 @@ class RasterRetained extends GeometryRetained { this.width = width; this.height = height; geomLock.unLock(); - } - + } /** - * Sets the size of the array of pixels to be copied. + * Gets the size of the array of pixels to be copied. * @param size the new size */ final void getSize(Dimension size) { size.setSize(width, height); } - /** * Sets the destination pixel offset of the upper-left * corner of the rendered image relative to the transformed position. @@ -218,42 +199,79 @@ class RasterRetained extends GeometryRetained { /** + * Initializes the raster image to the specified image. + * @param image new ImageCompoent2D object used as the raster image + */ + final void initImage(ImageComponent2D img) { + + int texFormat; + + if(img == null) { + image = null; + texture = null; + return; + } + + image = (ImageComponent2DRetained) img.retained; + image.setEnforceNonPowerOfTwoSupport(true); + switch(image.getNumberOfComponents()) { + case 1: + texFormat = Texture.INTENSITY; + break; + case 2: + texFormat = Texture.LUMINANCE_ALPHA; + break; + case 3: + texFormat = Texture.RGB; + break; + case 4: + texFormat = Texture.RGBA; + break; + default: + assert false; + return; + } + + Texture2D tex2D = new Texture2D(Texture.BASE_LEVEL, texFormat, + img.getWidth(), img.getHeight()); + texture = (Texture2DRetained) tex2D.retained; + texture.setUseAsRaster(true); + texture.initImage(0,img); + + } + + /** * Sets the pixel array used to copy pixels to/from a Canvas3D. * This is used when the type is RASTER_COLOR or RASTER_COLOR_DEPTH. * @param image the ImageComponent2D object containing the * color data */ - final void setImage(ImageComponent2D image) { - ImageComponent2DRetained oldImage = this.image; - - if (this.source.isLive()) { - - if (this.image != null) { - this.image.clearLive(refCount); - } - if (image != null) { - ((ImageComponent2DRetained)image.retained).setLive(inBackgroundGroup, refCount); - } - } - - geomLock.getLock(); - if (image != null) { - ImageComponent2DRetained rimage = - (ImageComponent2DRetained)image.retained; - rimage.setRasterRef(); - this.image = rimage; - } else { - this.image = null; - } - - - - // Set the lastAlpha to 1.0f - lastAlpha = 1.0f; - geomLock.unLock(); - sendChangedMessage((J3dThread.UPDATE_RENDER|J3dThread.UPDATE_RENDERING_ATTRIBUTES), - oldImage, this.image); - } + final void setImage(ImageComponent2D img) { + + if((img != null) && + (img.getImageClass() == ImageComponent.ImageClass.NIO_IMAGE_BUFFER)) { + throw new IllegalArgumentException(J3dI18N.getString("Background14")); + } + + TextureRetained oldTex = this.texture; + geomLock.getLock(); + if (source.isLive()) { + if (this.texture != null) { + this.texture.clearLive(refCount); + } + } + + initImage(img); + if (source.isLive()) { + if (texture != null) { + texture.setLive(inBackgroundGroup, refCount); + } + + sendChangedMessage((J3dThread.UPDATE_RENDER|J3dThread.UPDATE_RENDERING_ATTRIBUTES), + oldTex, this.texture); + } + geomLock.unLock(); + } /** * Retrieves the current pixel array object. @@ -271,7 +289,8 @@ class RasterRetained extends GeometryRetained { * depth (z-buffer) data */ final void setDepthComponent(DepthComponent depthComponent) { - if (this.source.isLive()) { + geomLock.getLock(); + if (this.source.isLive()) { if (this.depthComponent != null) { this.depthComponent.clearLive(refCount); } @@ -279,7 +298,7 @@ class RasterRetained extends GeometryRetained { ((DepthComponentRetained)depthComponent.retained).setLive(inBackgroundGroup, refCount); } } - geomLock.getLock(); + if (depthComponent == null) { this.depthComponent = null; } else { @@ -301,8 +320,8 @@ class RasterRetained extends GeometryRetained { void setLive(boolean inBackgroundGroup, int refCount) { super.doSetLive(inBackgroundGroup, refCount); - if (image != null) { - image.setLive(inBackgroundGroup, refCount); + if (texture != null) { + texture.setLive(inBackgroundGroup, refCount); } if (depthComponent != null) { depthComponent.setLive(inBackgroundGroup, refCount); @@ -321,8 +340,8 @@ class RasterRetained extends GeometryRetained { void clearLive(int refCount) { super.clearLive(refCount); - if (image != null) - image.clearLive(refCount); + if (texture != null) + texture.clearLive(refCount); if (depthComponent != null) depthComponent.clearLive(refCount); } @@ -373,7 +392,7 @@ class RasterRetained extends GeometryRetained { int numMessages = universeList.size(); J3dMessage[] m = new J3dMessage[numMessages]; for (int i=0; i<numMessages; i++) { - m[i] = VirtualUniverse.mc.getMessage(); + m[i] = new J3dMessage(); m[i].type = J3dMessage.GEOMETRY_CHANGED; m[i].threads = threads; m[i].args[0] = Shape3DRetained. @@ -393,168 +412,83 @@ class RasterRetained extends GeometryRetained { } - /** - * Native method that does the rendering - */ - native void execute(long ctx, GeometryRetained geo, - boolean updateAlpha, float alpha, - int type, int width, int height, - int xSrcOffset, int ySrcOffset, - float x, float y, float z, byte[] image); - /* - native void executeTiled(long ctx, GeometryRetained geo, - int format, int width, int height, - int xSrcOffset, int ySrcOffset, - int deltaw, int deltah, - float x, float y, float z, byte[] image); - */ - - void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, - boolean updateAlpha, float alpha, - boolean multiScreen, int screen, - boolean ignoreVertexColors, int pass) { - - // Compute the offset position of the raster - // This has to be done at render time because we need access - // to the Canvas3D info - - // Check if adjusted position needs to be computed - - validVwip = true; - adjPos.set((double)position.x, (double)position.y, (double)position.z); - - if(xDstOffset != 0 || yDstOffset != 0) { - getOffsetPos(cv, ra, adjPos); - } - - xOffset = xSrcOffset; - yOffset = ySrcOffset; - // Check if the image needs to be clipped - - if (clipMode == Raster.CLIP_IMAGE) - clipImage(cv, ra, adjPos); - - if (!validVwip) { - return; - } - if ((image != null) && !image.imageYdownCacheDirty) { - // If its a null image do nothing .. - if (image != null && image.imageYdown[0] != null) { - // Handle alpha, if necessary - // Note, raster always makes a copy, so we can update alpha - // in the image - if (updateAlpha) { - // Update Alpha value per screen - // If the image is by reference, force a copy, since - // we need to copy the alpha values - image.updateAlpha(cv, screen, alpha); - execute(cv.ctx, this, updateAlpha, alpha, - type, width, height, xOffset, yOffset, - (float)adjPos.x, (float)adjPos.y , (float)adjPos.z, - image.imageYdown[screen]); - } - else { - execute(cv.ctx, this, updateAlpha, alpha, - type, width, height, xOffset, yOffset, - (float)adjPos.x, (float)adjPos.y , (float)adjPos.z, - image.imageYdown[0]); - } - } - } - /* - else { - // Should never come here ... - if ((type & Raster.RASTER_COLOR) != 0){ - // Send down the tiles - int tilew = image.tilew; - int tileh = image.tileh; - int w = width, h = height; - int curw, curh; - int xo = xOffset, yo = yOffset; - float xpos = position.x, ypos = position.y; - // First find the tile {x.y} to start from - int tileX = 0, tileY = 0; - while (xo > tilew) { - tileX++; - xo -= tilew; - } - - while (yo > tileh) { - tileY++; - yo -= tileh; - } - int initTileY = image.minTileY+tileY; - int initTileX = image.minTileX+tileX; - int m,n; - int deltaw, deltah = 0; - curh = tileh - yo; - for (m = initTileY; m < image.minTileY+image.numYTiles; m++) { - curw = tilew - xo; - deltaw = 0; - w = width; - for (n = initTileX; n < image.minTileX+image.numXTiles; n++) { - java.awt.image.Raster ras; - ras = image.bImage[0].getTile(n,m); - byte[] tmpImage = ((DataBufferByte)ras.getDataBuffer()).getData(); - if (w <curw) { - curw = w; - } - executeTiled(cv.ctx, this, image.storedYdownFormat, - curw, - curh, - xo, yo, - deltaw, deltah, - (float)adjPos.x, (float)adjPos.y , (float)adjPos.z, - tmpImage); - - xo = 0; - w -= curw; - if (w == 0) - break; - deltaw += curw; - curw = tilew; - } - yo = 0; - h -= curh; - if (h == 0) - break; - deltah += curh; - curh = tileh; - if (h < curh) - curh = h; - xo = xOffset; - } - } - if ((type & Raster.RASTER_DEPTH) != 0) { - execute(cv.ctx, this, updateAlpha, alpha, - Raster.RASTER_DEPTH, width, height, - xOffset, yOffset, - (float)adjPos.x, (float)adjPos.y , (float)adjPos.z, - image.imageYdown[screen]); - } - } - */ + void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, + boolean updateAlpha, float alpha, + int screen, boolean ignoreVertexColors) { + + // Compute the offset position of the raster + // This has to be done at render time because we need access + // to the Canvas3D info + + // Check if adjusted position needs to be computed + Point3d adjPos = new Point3d(); // Position of the Raster after adjusting for dstOffset + adjPos.set(position); + + Point2d winCoord = new Point2d(); // Position of Raster in window coordinates + Transform3D localToImagePlate = new Transform3D(); // Local to Image plate transform + + Point3d clipCoord = computeWinCoord(cv, ra, winCoord, adjPos, localToImagePlate); + + // Test raster for out of bounds in Z. + if (clipCoord == null) { + return; + } + + if(clipMode == Raster.CLIP_POSITION) { + // Do trivial reject test on Raster position. + if(!isRasterClipPositionInside(clipCoord)) { + return; + } + } + + // Add the destination offset to the Raster position in window coordinates + winCoord.x += xDstOffset; + winCoord.y += yDstOffset; + + // System.err.println("Step 2 : adjPos " + adjPos + " winCoord " + winCoord); + + + if((type == Raster.RASTER_COLOR) || (type == Raster.RASTER_COLOR_DEPTH)) { + float devCoordZ = (float) (clipCoord.z * 0.5 - 0.5); + // Do textfill stuffs + if (texture != null) { + // setup Texture pipe. + cv.updateTextureForRaster(texture); + + cv.textureFill(this, winCoord, (float) devCoordZ, alpha); + + // Restore texture pipe. + cv.restoreTextureBin(); + } + + } + + if((type == Raster.RASTER_DEPTH) || (type == Raster.RASTER_COLOR_DEPTH)) { + + Point2i srcOffset = new Point2i(xSrcOffset, ySrcOffset); + + if (clipMode == Raster.CLIP_IMAGE) { + clipImage(cv, ra, winCoord, srcOffset); + } + + computeObjCoord(cv, winCoord, adjPos, localToImagePlate); + + cv.executeRasterDepth(cv.ctx, + (float) adjPos.x, + (float) adjPos.y, + (float) adjPos.z, + srcOffset.x, + srcOffset.y, + width, + height, + depthComponent.width, + depthComponent.height, + depthComponent.type, + ((DepthComponentIntRetained) depthComponent).depthData); + + } } - /** - * Computes the position of the origin of this Raster in object coordinates - * The origin is the top-left corner offset by the destination offset - * The offset position is returned in objCoord - * - * @param objCoord - Position of the Raster in object coordinates - * @return nothing. The offset position is returned in objCoord - */ - private void getOffsetPos(Canvas3D canvas, RenderAtom ra, Point3d objCoord) { - computeWinCoord(canvas, ra, winCoord, objCoord); - - // Add the destination offset to the Raster position in window coordinates - winCoord.x -= xDstOffset; - winCoord.y -= yDstOffset; - - // Now back transform this offset pt. from window to object coordinates - computeObjCoord(canvas, winCoord, objCoord); - // pt. is now in object space again - } /** * Clips the image against the window. This method simulates @@ -564,29 +498,12 @@ class RasterRetained extends GeometryRetained { * clipping against the right and bottom edges will be handled by * the underlying graphics library automatically. */ - private void clipImage(Canvas3D canvas, RenderAtom ra, Point3d objCoord) { - // check if window coordinates have already been calculated by - // getOffsetPos(). - - if(xDstOffset == 0 && yDstOffset == 0) { - double x = objCoord.x; - double y = objCoord.y; - double z = objCoord.z; - computeWinCoord(canvas, ra, winCoord, objCoord); - - if ((winCoord.x > 0) && (winCoord.y > 0)) { - objCoord.x = x; - objCoord.y = y; - objCoord.z = z; - return; // no need to clip - } - } else { - if ((winCoord.x > 0) && (winCoord.y > 0)) { - return; - } - } - - + private void clipImage(Canvas3D canvas, RenderAtom ra, Point2d winCoord, Point2i srcOffset) { + + if ((winCoord.x > 0) && (winCoord.y > 0)) { + return; + } + // Check if the Raster point will be culled // Note that w use 1 instead of 0, because when hardware // tranform the coordinate back to winCoord it may get @@ -595,37 +512,32 @@ class RasterRetained extends GeometryRetained { // (see bug 4732965) if(winCoord.x < 1) { // Negate the window position and use this as the offset - xOffset = (int)-winCoord.x+1; + srcOffset.x = (int)-winCoord.x+1; winCoord.x = 1; } if(winCoord.y < 1) { // Negate the window position and use this as the offset - yOffset = (int)-winCoord.y+1; + srcOffset.y = (int)-winCoord.y+1; winCoord.y = 1; } //check if user-specified subimage is smaller than the clipped image - if (xOffset < xSrcOffset) - xOffset = xSrcOffset; - if(yOffset < ySrcOffset) - yOffset = ySrcOffset; - // back transform to object coords - if(xDstOffset == 0 && yDstOffset == 0) - // Image plate to local Xform needs to be computed - computeObjCoord(canvas, winCoord, objCoord); - else { - // vwip should contain the Imageplate to Local transform - // (it was computed by computeObjCoord). - // We can simply use the previously computed value here - canvas.getPixelLocationInImagePlate(winCoord.x, winCoord.y, - objCoord.z, objCoord); - vwip.transform(objCoord); - } + if (srcOffset.x < xSrcOffset) + srcOffset.x = xSrcOffset; + if(srcOffset.y < ySrcOffset) + srcOffset.y = ySrcOffset; + + } + + private boolean isRasterClipPositionInside(Point3d clipCoord) { + return (clipCoord.x >= -1.0) && (clipCoord.x <= 1.0) && + (clipCoord.y >= -1.0) && (clipCoord.y <= 1.0); } - private void computeObjCoord(Canvas3D canvas, Point2d winCoord, Point3d objCoord) { + private void computeObjCoord(Canvas3D canvas, Point2d winCoord, Point3d objCoord, + Transform3D localToImagePlate) { // Back transform this pt. from window to object coordinates // Assumes this method is ALWAYS called after computeWinCoord has been // called. computeWinCoord calculates the Vworld to Image Plate Xform. @@ -635,29 +547,52 @@ class RasterRetained extends GeometryRetained { objCoord); // Get image plate to object coord transform // inv(P x M) - vwip.invert(); - vwip.transform(objCoord); + localToImagePlate.invert(); + localToImagePlate.transform(objCoord); } - private void computeWinCoord(Canvas3D canvas, RenderAtom ra, - Point2d winCoord, Point3d objCoord) { + private Point3d computeWinCoord(Canvas3D canvas, RenderAtom ra, + Point2d winCoord, Point3d objCoord, + Transform3D localToImagePlate) { // Get local to Vworld transform RenderMolecule rm = ra.renderMolecule; if (rm == null) { // removeRenderAtom() may set ra.renderMolecule to null // in RenderBin before this renderer thread run. - validVwip = false; - return; - } - // MT safe issue: We can't reference ra.renderMolecule below since + return null; + } + + // MT safe issue: We can't reference ra.renderMolecule below since // RenderBin thread may set it to null anytime. Use rm instead. Transform3D lvw = rm.localToVworld[rm.localToVworldIndex[ NodeRetained.LAST_LOCAL_TO_VWORLD]]; - + + + Point3d clipCoord3 = new Point3d(); + clipCoord3.set(objCoord); + Point4d clipCoord4 = new Point4d(); + + // Transform point from local coord. to clipping coord. + lvw.transform(clipCoord3); + canvas.vworldToEc.transform(clipCoord3); + canvas.projTrans.transform(clipCoord3, clipCoord4); + + // clip check in Z + if((clipCoord4.w <= 0.0) || + (clipCoord4.z > clipCoord4.w) || (-clipCoord4.z > clipCoord4.w)) { + + return null; + } + double invW = 1.0 / clipCoord4.w; + + clipCoord3.x = clipCoord4.x * invW; + clipCoord3.y = clipCoord4.y * invW; + clipCoord3.z = clipCoord4.z * invW; + // Get Vworld to image plate Xform - canvas.getLastVworldToImagePlate(vwip); + canvas.getLastVworldToImagePlate(localToImagePlate); // v' = vwip x lvw x v // where v' = transformed vertex, @@ -666,13 +601,16 @@ class RasterRetained extends GeometryRetained { // v = vertex // Compute composite local to image plate Xform - vwip.mul(lvw); + localToImagePlate.mul(lvw); // Transform the Raster's position from object to world coordinates - vwip.transform(objCoord); + localToImagePlate.transform(objCoord); + // Get the window coordinates of this point canvas.getPixelLocationFromImagePlate(objCoord, winCoord); + + return clipCoord3; } int getClassType() { diff --git a/src/classes/share/javax/media/j3d/RenderBin.java b/src/classes/share/javax/media/j3d/RenderBin.java index a9cfe36..81cc46a 100644 --- a/src/classes/share/javax/media/j3d/RenderBin.java +++ b/src/classes/share/javax/media/j3d/RenderBin.java @@ -94,18 +94,6 @@ class RenderBin extends J3dStructure implements ObjectUpdate { */ ArrayList positionDirtyList = new ArrayList(5); - - /** - * A set of freelists for RenderBin type objects - */ - ArrayList lightBinFreelist = new ArrayList(5); - ArrayList envSetFreelist = new ArrayList(5); - ArrayList attrBinFreelist = new ArrayList(5); - ArrayList shaderBinFreelist = new ArrayList(5); - ArrayList textureBinFreelist = new ArrayList(5); - ArrayList renderMoleculeFreelist = new ArrayList(5); - ArrayList transparentInfoFreeList = new ArrayList(5); - /** * Used when ColoringAttributes is null */ @@ -176,9 +164,8 @@ class RenderBin extends J3dStructure implements ObjectUpdate { private Comparator transparencySortComparator = null; - ArrayList toBeAddedTextureResourceFreeList = new ArrayList(5); - ArrayList displayListResourceFreeList = new ArrayList(5); - boolean resourceToFree = false; + private ArrayList toBeAddedTextureResourceFreeList = new ArrayList(5); + private ArrayList displayListResourceFreeList = new ArrayList(5); // a list of top level OrderedGroups ArrayList orderedBins = new ArrayList(5); @@ -197,7 +184,8 @@ class RenderBin extends J3dStructure implements ObjectUpdate { int envDirty = 0; - boolean reEvaluateBg = true; + private boolean reEvaluateBg = true; + private boolean reloadBgTexture = true; boolean reEvaluateClip = true; @@ -305,13 +293,6 @@ class RenderBin extends J3dStructure implements ObjectUpdate { */ ArrayList dirtyReferenceGeomList = new ArrayList(5); - - /** - * used by geometry execute routines to determine if the - * alpha values can be zapped - */ - boolean multiScreen = false; - // list of all Oriented RenderAtoms ArrayList orientedRAs = new ArrayList(5); @@ -411,7 +392,6 @@ class RenderBin extends J3dStructure implements ObjectUpdate { TextureRetained tex; Integer texIdObj; int size; - DetailTextureImage dtex; // System.out.println("dirtyRenderMoleculeList.size = "+dirtyRenderMoleculeList.size()); // System.out.println("reEvaluateBg = "+reEvaluateBg); @@ -704,23 +684,31 @@ class RenderBin extends J3dStructure implements ObjectUpdate { //System.out.println("newNodeComponentlist.size= " + size); Canvas3D canvases[] = view.getCanvases(); for (i = 0; i < size; i++) { - // Evaluate the nodeComponentList for all the canvases - ImageComponentRetained nc = (ImageComponentRetained)newNodeComponentList.get(i); - // Only evalaute extension for by-ref Images - if (nc.isByReference()) { - nc.geomLock.getLock(); - for (j = 0; j <canvases.length; j++) { - // If the context is null, then the extension - // will be evaluated during context creation in - // the renderer - if (canvases[j].ctx != 0) { - nc.evaluateExtensions(canvases[j].extensionsSupported); - } - } - nc.geomLock.unLock(); - } - nodeComponentList.add(nc); - } + // Evaluate the nodeComponentList for all the canvases + ImageComponent2DRetained nc = (ImageComponent2DRetained)newNodeComponentList.get(i); + if (nc.isByReference()) { + nc.geomLock.getLock(); + for (j = 0; j <canvases.length; j++) { + // If the context is null, then the extension + // will be evaluated during context creation in + // the renderer + if (canvases[j].ctx != null) { + nc.evaluateExtensions(canvases[j]); + } + } + nc.geomLock.unLock(); + } else { + for (j = 0; j <canvases.length; j++) { + // If the context is null, then the extension + // will be evaluated during context creation in + // the renderer + if (canvases[j].ctx != null) { + nc.evaluateExtensions(canvases[j]); + } + } + } + nodeComponentList.add(nc); + } } size = removeNodeComponentList.size(); @@ -737,22 +725,30 @@ class RenderBin extends J3dStructure implements ObjectUpdate { Canvas3D canvases[] = view.getCanvases(); for (i = 0; i < size; i++) { // Evaluate the nodeComponentList for all the canvases - ImageComponentRetained nc = - (ImageComponentRetained)dirtyNodeComponentList.get(i); - // Only evalaute extension for by-ref Images + ImageComponent2DRetained nc = + (ImageComponent2DRetained)dirtyNodeComponentList.get(i); if (nc.isByReference()) { nc.geomLock.getLock(); for (j = 0; j <canvases.length; j++) { // If the context is null, then the extension // will be evaluated during context creation in // the renderer - if (canvases[j].ctx != 0) { - nc.evaluateExtensions( - canvases[j].extensionsSupported); + if (canvases[j].ctx != null) { + nc.evaluateExtensions( canvases[j]); } } nc.geomLock.unLock(); } + else { + for (j = 0; j <canvases.length; j++) { + // If the context is null, then the extension + // will be evaluated during context creation in + // the renderer + if (canvases[j].ctx != null) { + nc.evaluateExtensions(canvases[j]); + } + } + } } } @@ -768,8 +764,9 @@ class RenderBin extends J3dStructure implements ObjectUpdate { } view.vDirtyMask |= View.CLIP_DIRTY; } - - multiScreen = ((view.getScreens()).length > 1); + + // Issue 113 - multiScreen no longer used +// multiScreen = ((view.getScreens()).length > 1); // renderBin is ready now, so send the offScreen message size = offScreenMessage.size(); @@ -1089,7 +1086,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { ra = arr[i]; GeometryArrayRetained geo = (GeometryArrayRetained) ra.geometry(); - if ((cv.ctx != 0) && + if ((cv.ctx != null) && ((geo.resourceCreationMask & cv.canvasBit) == 0) || (geo.getDlistTimeStamp(cv.canvasBit) != cv.ctxTimeStamp)) { @@ -1107,7 +1104,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { // add this geometry's dlist to be freed if (geo.isDlistUserSetEmpty(this)) { - if (cv.ctx != 0) { + if (cv.ctx != null) { canvases[j].displayListResourceFreeList.add(geo.dlistObj); } geo.resourceCreationMask &= ~canvases[j].canvasBit; @@ -1153,6 +1150,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { dirtyRenderMoleculeList.clear(); dirtyReferenceGeomList.clear(); reEvaluateBg = false; + reloadBgTexture = false; textureBinList.clear(); newNodeComponentList.clear(); removeNodeComponentList.clear(); @@ -1174,7 +1172,6 @@ class RenderBin extends J3dStructure implements ObjectUpdate { RenderMolecule rm; TextureRetained tex; Integer texIdObj; - DetailTextureImage dtex; if (rdr == null) return; @@ -1235,25 +1232,6 @@ class RenderBin extends J3dStructure implements ObjectUpdate { rdr.textureIdResourceFreeList.add(texIdObj); tex.resourceCreationMask &= ~rdr.rendererBit; } - if (tex instanceof Texture2DRetained) { - dtex = ((Texture2DRetained) tex).detailTexture; - if ((dtex != null) && - ((dtex.resourceCreationMask[tex.format] & rdr.rendererBit) != 0)) { - id = dtex.objectIds[tex.format]; - if ((id >= rdr.textureIDResourceTable.size()) || - (rdr.textureIDResourceTable.get(id) != dtex)) { - id = rdr.textureIDResourceTable.indexOf(dtex); - if (id <= 0) { - continue; - } - } - texIdObj = new Integer(id); - if (!rdr.textureIdResourceFreeList.contains(texIdObj)) { - rdr.textureIdResourceFreeList.add(texIdObj); - dtex.resourceCreationMask[tex.format] &= ~rdr.rendererBit; - } - } - } } } @@ -1282,7 +1260,6 @@ class RenderBin extends J3dStructure implements ObjectUpdate { RenderMolecule rm; TextureRetained tex; Integer texIdObj; - DetailTextureImage dtex; // update dirtyRenderMoleculeList for each canvas for (i = 0; i < canvases.length; i++) { @@ -1330,35 +1307,11 @@ class RenderBin extends J3dStructure implements ObjectUpdate { } } - if ((tex.resourceCreationMask & cv.canvasBit) != 0) { texIdObj = new Integer(id); cv.textureIdResourceFreeList.add(texIdObj); tex.resourceCreationMask &= ~cv.canvasBit; } - if (tex instanceof Texture2DRetained) { - dtex = ((Texture2DRetained) tex).detailTexture; - if ((dtex != null) && - ((dtex.resourceCreationMask[tex.format] & cv.canvasBit) != 0)) { - id = dtex.objectIds[tex.format]; - if ((id >= cv.textureIDResourceTable.size()) || - (cv.textureIDResourceTable.get(id) != dtex)) { - id = cv.textureIDResourceTable.indexOf(dtex); - if (id <= 0) { - continue; - } - } - texIdObj = new Integer(id); - // XXXX: The following code seems wrong -- why add it to - // the list if it is already there? Maybe one is for the - // texture and the other (idential value) is for the - // detail texture? - if (cv.textureIdResourceFreeList.contains(texIdObj)) { - cv.textureIdResourceFreeList.add(texIdObj); - dtex.resourceCreationMask[tex.format] &= ~cv.canvasBit; - } - } - } } // Take care of display list that should be freed size = displayListResourceFreeList.size(); @@ -1427,8 +1380,10 @@ class RenderBin extends J3dStructure implements ObjectUpdate { break; case J3dMessage.BACKGROUND_CHANGED: BackgroundRetained bg = (BackgroundRetained)m.args[0]; - if (universe.renderingEnvironmentStructure.isBgScopedToThisView(bg, view)) + if (universe.renderingEnvironmentStructure.isBgScopedToThisView(bg, view)) { reEvaluateBg = true; + reloadBgTexture = true; + } m.decRefcount(); break; case J3dMessage.CLIP_CHANGED: @@ -3167,19 +3122,26 @@ System.out.println("......tb.soleUser= " + addGeometryDlist(ra); // Raster send this message only for setImage() - if (g instanceof RasterRetained) { - Object[] objs = (Object[]) args[2]; - ImageComponentRetained oldImage = (ImageComponentRetained) objs[0]; - ImageComponentRetained newImage = (ImageComponentRetained) objs[1]; - - RasterRetained geo = (RasterRetained)ra.geometry(); - if (oldImage != null && oldImage.isByReference()) { - removeNodeComponent(oldImage); - } - if (newImage != null && newImage.isByReference()) { - addNodeComponent(newImage); - } - } + if (g instanceof RasterRetained) { + Object[] objs = (Object[]) args[2]; + Texture2DRetained oldTex = (Texture2DRetained) objs[0]; + Texture2DRetained newTex = (Texture2DRetained) objs[1]; + + RasterRetained geo = (RasterRetained)ra.geometry(); + if (oldTex != null) { + addTextureResourceFreeList(oldTex); + ImageComponentRetained oldImage = oldTex.images[0][0]; + if (oldImage != null) { + removeNodeComponent(oldImage); + } + } + if (newTex != null) { + ImageComponentRetained newImage = newTex.images[0][0]; + if (newImage != null) { + addNodeComponent(newImage); + } + } + } } @@ -3223,7 +3185,8 @@ System.out.println("......tb.soleUser= " + ArrayList rmList, ArrayList dlistPerRinfoList, ArrayList raList, boolean useSharedCtx ) { int size, i, bitMask; - long ctx, timeStamp; + Context ctx; + long timeStamp; if (useSharedCtx) { ctx = cv.screen.renderer.sharedCtx; @@ -3285,10 +3248,9 @@ System.out.println("......tb.soleUser= " + } void removeRenderMolecule(RenderMolecule rm) { - renderMoleculeFreelist.add(rm); - if ((rm.primaryMoleculeType &(RenderMolecule.DLIST_MOLECULE|RenderMolecule.SEPARATE_DLIST_PER_RINFO_MOLECULE)) != 0) - renderMoleculeList.remove(rm); + if ((rm.primaryMoleculeType &(RenderMolecule.DLIST_MOLECULE|RenderMolecule.SEPARATE_DLIST_PER_RINFO_MOLECULE)) != 0) + renderMoleculeList.remove(rm); } void updateAllRenderMolecule(Canvas3D cv) { @@ -3422,7 +3384,7 @@ System.out.println("......tb.soleUser= " + for(int k = 0; k < ra.rListInfo.length; k++) { if (ra.rListInfo[k].localToVworld == null) { - ra.rListInfo[k].localToVworld = VirtualUniverse.mc.getTransform3D(null); + ra.rListInfo[k].localToVworld = new Transform3D(); } } @@ -4474,7 +4436,7 @@ System.out.println("......tb.soleUser= " + ra.dirtyMask |= RenderAtom.IS_ORIENTED; for(int k = 0; k < ra.rListInfo.length; k++) { if (ra.rListInfo[k].localToVworld == null) { - ra.rListInfo[k].localToVworld = VirtualUniverse.mc.getTransform3D(null); + ra.rListInfo[k].localToVworld = new Transform3D(); } } } @@ -4702,18 +4664,12 @@ System.out.println("......tb.soleUser= " + * This gets a new EnviornmentSet. It creates one if there are none * on the freelist. */ - private EnvironmentSet getEnvironmentSet(RenderAtom ra, LightRetained[] lights, - FogRetained fog, ModelClipRetained modelClip) { - EnvironmentSet envSet; - - if (envSetFreelist.size() > 0) { - envSet = (EnvironmentSet)envSetFreelist.remove( - envSetFreelist.size()-1); - envSet.reset(ra, lights, fog, modelClip); - } else { - envSet = new EnvironmentSet(ra, lights, fog, modelClip, this); - } - return (envSet); + private EnvironmentSet getEnvironmentSet(RenderAtom ra, LightRetained[] lights, + FogRetained fog, ModelClipRetained modelClip) { + EnvironmentSet envSet; + + envSet = new EnvironmentSet(ra, lights, fog, modelClip, this); + return (envSet); } /** @@ -4925,14 +4881,7 @@ System.out.println("......tb.soleUser= " + * on the freelist. */ private ShaderBin getShaderBin(ShaderAppearanceRetained sApp) { - ShaderBin shaderBin; - if (shaderBinFreelist.size() > 0) { - shaderBin = (ShaderBin)shaderBinFreelist.remove(shaderBinFreelist.size()-1); - shaderBin.reset(sApp, this); - } else { - shaderBin = new ShaderBin( sApp, this); - } - return (shaderBin); + return new ShaderBin( sApp, this); } /** @@ -4940,17 +4889,7 @@ System.out.println("......tb.soleUser= " + * on the freelist. */ private AttributeBin getAttributeBin(AppearanceRetained app, RenderingAttributesRetained ra) { - AttributeBin attrBin; - if (attrBinFreelist.size() > 0) { - attrBin = (AttributeBin)attrBinFreelist.remove( - attrBinFreelist.size()-1); - attrBin.reset(app, ra, this); - } else { - - - attrBin = new AttributeBin(app, ra, this); - } - return (attrBin); + return new AttributeBin(app, ra, this); } /** @@ -4958,17 +4897,12 @@ System.out.println("......tb.soleUser= " + * on the freelist. */ private LightBin getLightBin(int maxLights, BackgroundRetained bg, boolean inOpaque) { - LightBin lightBin; - - if (lightBinFreelist.size() > 0) { - lightBin = (LightBin)lightBinFreelist.remove( - lightBinFreelist.size()-1); - lightBin.reset(inOpaque); - } else { - lightBin = new LightBin(maxLights, this, inOpaque); - } - lightBin.geometryBackground = bg; - return (lightBin); + LightBin lightBin; + + lightBin = new LightBin(maxLights, this, inOpaque); + + lightBin.geometryBackground = bg; + return (lightBin); } /** @@ -4976,49 +4910,30 @@ System.out.println("......tb.soleUser= " + * on the freelist. */ private TextureBin getTextureBin(TextureUnitStateRetained texUnitState[], - AppearanceRetained app) { - TextureBin textureBin; - - if (textureBinFreelist.size() > 0) { - textureBin = (TextureBin)textureBinFreelist.remove( - textureBinFreelist.size()-1); - textureBin.reset(texUnitState, app); - } else { - textureBin = new TextureBin(texUnitState, app, this); - } - - return (textureBin); + AppearanceRetained app) { + return new TextureBin(texUnitState, app, this); } /** * This gets a new RenderMolecule. It creates one if there are none * on the freelist. */ - private RenderMolecule getRenderMolecule(GeometryAtom ga, - PolygonAttributesRetained polya, - LineAttributesRetained linea, - PointAttributesRetained pointa, - MaterialRetained material, - ColoringAttributesRetained cola, - TransparencyAttributesRetained transa, - RenderingAttributesRetained ra, - TextureUnitStateRetained[] texUnits, - Transform3D[] transform, - int[] transformIndex) { - RenderMolecule renderMolecule; - - if (renderMoleculeFreelist.size() > 0) { - renderMolecule = (RenderMolecule)renderMoleculeFreelist.remove( - renderMoleculeFreelist.size()-1); - renderMolecule.reset(ga, polya, linea, pointa, material, - cola, transa, ra, texUnits, transform, transformIndex); - } else { - renderMolecule = new RenderMolecule(ga, polya, linea, pointa, - material, cola, transa, ra, - texUnits, - transform, transformIndex, this); - } - return (renderMolecule); + private RenderMolecule getRenderMolecule(GeometryAtom ga, + PolygonAttributesRetained polya, + LineAttributesRetained linea, + PointAttributesRetained pointa, + MaterialRetained material, + ColoringAttributesRetained cola, + TransparencyAttributesRetained transa, + RenderingAttributesRetained ra, + TextureUnitStateRetained[] texUnits, + Transform3D[] transform, + int[] transformIndex) { + + return new RenderMolecule(ga, polya, linea, pointa, + material, cola, transa, ra, + texUnits, + transform, transformIndex, this); } @@ -5197,7 +5112,6 @@ System.out.println("......tb.soleUser= " + // gotten from the freelist from one frame to another canvases[i].lightBin = null; } - lightBinFreelist.add(lbin); lbin.prev = null; lbin.next = null; } @@ -5358,41 +5272,50 @@ System.out.println("......tb.soleUser= " + * Sets the new background color. */ void setBackground(BackgroundRetained back) { - - boolean cvDirty = false; - BackgroundRetained oldGeomBack = geometryBackground; - geometryBackground = null; - - if (back != null) { - background.initColor(back.color); - background.initImageScaleMode(back.imageScaleMode); - background.geometryBranch = back.geometryBranch; + + boolean cvDirty = false; + BackgroundRetained oldGeomBack = geometryBackground; + geometryBackground = null; + + if (back != null) { + background.initColor(back.color); + background.initImageScaleMode(back.imageScaleMode); + background.geometryBranch = back.geometryBranch; if (background.geometryBranch != null) { geometryBackground = back; } - if (background.image != null) { - if (background.image.isByReference()) - removeNodeComponent(background.image); - } - if (back.image != null) { - // May need to optimize later - background.initImage((ImageComponent2D)back.image.source); - if (back.image.isByReference()) { - addNodeComponent(back.image); - } - } else { - background.initImage(null); - } - if (oldGeomBack == null) { - cvDirty = true; - } - } else { - background.initColor(black); - background.geometryBranch = null; - background.initImage(null); - if (oldGeomBack != null) { - cvDirty = true; - } + // Release resources associated with old BG and initialize new BG + // if the old and new BG images are different or if the + // reloadBgTexture flag is set. + if (background.image != back.image || reloadBgTexture) { + if (background.image != null) { + assert background.texture != null; + addTextureResourceFreeList(background.texture); + removeNodeComponent(background.image); + } + if (back.image != null) { + // May need to optimize later + background.initImage((ImageComponent2D)back.image.source); + addNodeComponent(back.image); + } else { + background.initImage(null); + } + } + if (oldGeomBack == null) { + cvDirty = true; + } + } else { + background.initColor(black); + background.geometryBranch = null; + if (background.image != null) { + assert background.texture != null; + addTextureResourceFreeList(background.texture); + removeNodeComponent(background.image); + } + background.initImage(null); + if (oldGeomBack != null) { + cvDirty = true; + } } // Need to reEvaluate View cache since doInfinite @@ -6005,12 +5928,6 @@ System.out.println("......tb.soleUser= " + nodeComponentList.clear(); orientedRAs.clear(); bhTreesArrList.clear(); - lightBinFreelist.clear(); - envSetFreelist.clear(); - attrBinFreelist.clear(); - shaderBinFreelist.clear(); - textureBinFreelist.clear(); - renderMoleculeFreelist.clear(); // clean up any messages that are queued up, since they are // irrelevant @@ -6142,7 +6059,6 @@ System.out.println("......tb.soleUser= " + } t.prev = null; t.next = null; - transparentInfoFreeList.add(t); tb.parentTInfo = null; } else { @@ -6168,7 +6084,6 @@ System.out.println("......tb.soleUser= " + } t.prev = null; t.next = null; - transparentInfoFreeList.add(t); tb.parentTInfo = null; } @@ -6202,7 +6117,6 @@ System.out.println("......tb.soleUser= " + } t.prev = null; t.next = null; - transparentInfoFreeList.add(t); nElements--; r.parentTInfo[i] = null; } @@ -6261,15 +6175,7 @@ System.out.println("......tb.soleUser= " + } TransparentRenderingInfo getTransparentInfo() { - TransparentRenderingInfo tinfo; - - if (transparentInfoFreeList.size() > 0) { - tinfo = (TransparentRenderingInfo)transparentInfoFreeList.remove(transparentInfoFreeList.size()-1); - } else { - tinfo = new TransparentRenderingInfo(); - } - return (tinfo); - + return new TransparentRenderingInfo(); } TransparentRenderingInfo computeDirtyAcrossTransparentBins(TextureBin tb, TransparentRenderingInfo startinfo) { @@ -6370,7 +6276,6 @@ System.out.println("......tb.soleUser= " + for (i = 0; i < size; i++) { TextureBin tb = (TextureBin)allTransparentObjects.get(i); - transparentInfoFreeList.add(tb.parentTInfo); tb.parentTInfo = null; RenderMolecule r = tb.transparentRMList; // For each renderMolecule @@ -6429,7 +6334,6 @@ System.out.println("......tb.soleUser= " + if (r.parentTInfo[j] == null) continue; - transparentInfoFreeList.add(r.parentTInfo[j]); r.parentTInfo[j] = null; } if (r.renderMolecule.textureBin.parentTInfo == null) { @@ -6919,6 +6823,15 @@ System.out.println("......tb.soleUser= " + renderAtoms.remove(renderAtoms.indexOf(ra)); removeARenderAtom(ra); } + + // This code segment is to handle the texture resource cleanup + // for Raster object. + GeometryAtom geomAtom = (GeometryAtom) nodes[n]; + GeometryRetained geomRetained = geomAtom.geometryArray[0]; + if ((geomRetained != null) && + (geomRetained instanceof RasterRetained )) { + addTextureResourceFreeList(((RasterRetained)geomRetained).texture); + } } else if (nodes[n] instanceof AlternateAppearanceRetained) { altAppearanceDirty = true; @@ -6978,7 +6891,9 @@ System.out.println("......tb.soleUser= " + } - void freeAllDisplayListResources(Canvas3D cv) { + void freeAllDisplayListResources(Canvas3D cv, Context ctx) { + + assert ctx != null; int i; int size = renderMoleculeList.size(); @@ -6989,7 +6904,7 @@ System.out.println("......tb.soleUser= " + renderMoleculeList.toArray(false); for (i = 0 ; i < size; i++) { - rmArr[i].releaseAllPrimaryDisplayListResources(cv); + rmArr[i].releaseAllPrimaryDisplayListResources(cv, ctx); } } @@ -7012,7 +6927,7 @@ System.out.println("......tb.soleUser= " + // Canvas in the renderer. However, since the // display lists will be recreated, it doesn't // really matter. - cv.freeDisplayList(cv.ctx, geo.dlistId); + cv.freeDisplayList(ctx, geo.dlistId); geo.resourceCreationMask &= ~mask; } } diff --git a/src/classes/share/javax/media/j3d/RenderMethod.java b/src/classes/share/javax/media/j3d/RenderMethod.java index 8641375..a714cfd 100644 --- a/src/classes/share/javax/media/j3d/RenderMethod.java +++ b/src/classes/share/javax/media/j3d/RenderMethod.java @@ -22,6 +22,6 @@ interface RenderMethod { /** * The actual rendering code for this RenderMethod */ - abstract boolean render(RenderMolecule rm, Canvas3D cv, int pass, + abstract boolean render(RenderMolecule rm, Canvas3D cv, RenderAtomListInfo ra, int dirtyBits); } diff --git a/src/classes/share/javax/media/j3d/RenderMolecule.java b/src/classes/share/javax/media/j3d/RenderMolecule.java index 2bc58a6..a0c24b9 100644 --- a/src/classes/share/javax/media/j3d/RenderMolecule.java +++ b/src/classes/share/javax/media/j3d/RenderMolecule.java @@ -390,14 +390,16 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen geo = ga.geometryArray[k]; k++; } - - if (ga.source.appearance != null) { - soleUser = ((ga.source.appearance.changedFrequent & RM_COMPONENTS) != 0); - } - else { - soleUser = false; + + // Issue 249 - check for sole user only if property is set + soleUser = false; + if (VirtualUniverse.mc.allowSoleUser) { + if (ga.source.appearance != null) { + soleUser = ((ga.source.appearance.changedFrequent & RM_COMPONENTS) != 0); + } } - // Set the appearance only for soleUser case + + // Set the appearance only for soleUser case if (soleUser) appHandle = ga.source.appearance; else @@ -674,8 +676,8 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen if (localeLocalToVworld == null) { localeLocalToVworld = new Transform3D[2]; } - localeLocalToVworld[0] = VirtualUniverse.mc.getTransform3D(null); - localeLocalToVworld[1] = VirtualUniverse.mc.getTransform3D(null); + localeLocalToVworld[0] = new Transform3D(); + localeLocalToVworld[1] = new Transform3D(); localeTranslation = new Vector3d(); ga.locale.hiRes.difference(renderBin.locale.hiRes, localeTranslation); translate(); @@ -1072,16 +1074,9 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen rinfo.next.prev = rinfo.prev; } } - // If this renderAtom has localTransform, - // return transform to freelist - if (primaryMoleculeType == RenderMolecule.TEXT3D_MOLECULE) { - if (!rinfo.renderAtom.inRenderBin()) { - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, rinfo.localToVworld); - - } - } + // If the molecule type is Raster, then add it to the lock list - else if (primaryMoleculeType == RASTER) { + if (primaryMoleculeType == RASTER) { RasterRetained geo = (RasterRetained)rinfo.geometry(); renderBin.removeGeometryFromLockList(geo); if (geo.image != null) @@ -1161,10 +1156,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen displayListId = 0; displayListIdObj = null; } - // If the locale is different, return xform to freelist if (locale != renderBin.locale) { - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - localeLocalToVworld[0]); localeLocalToVworld = null; } textureBin.removeRenderMolecule(this); @@ -1297,18 +1289,16 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen ((geo.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0)) { renderBin.addGeometryToLockList(geo); // Add the geometry to the dirty list only if the geometry is by - // refernce and there is color and we need to use alpha and its - // not multiScreen + // refernce and there is color and we need to use alpha + // Issue 113 - ignore multiScreen if ((( geo.vertexFormat & GeometryArray.BY_REFERENCE)!=0) && (geo.c4fAllocated == 0) && ((geo.vertexFormat & GeometryArray.COLOR) != 0) && - useAlpha && - !renderBin.multiScreen) { + useAlpha) { renderBin.addDirtyReferenceGeometry(geo); } } } - } addRAs = addRAs.nextAdd; renderAtom.nextAdd = null; @@ -1749,13 +1739,12 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen ((geo.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0)) { renderBin.addGeometryToLockList(geo); // Add the geometry to the dirty list only if the geometry is by - // refernce and there is color and we need to use alpha and its - // not multiScreen + // reference and there is color and we need to use alpha + // Issue 113 - ignore multiScreen if ((( geo.vertexFormat & GeometryArray.BY_REFERENCE)!=0) && (geo.c4fAllocated == 0) && ((geo.vertexFormat & GeometryArray.COLOR) != 0) && - useAlpha && - !renderBin.multiScreen) { + useAlpha) { renderBin.addDirtyReferenceGeometry(geo); } } @@ -1791,6 +1780,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen * Renders this RenderMolecule */ boolean render(Canvas3D cv, int pass, int dirtyBits) { + assert pass < 0; boolean isVisible = isSwitchOn(); @@ -1847,24 +1837,16 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen modeSupportDL) { if (primaryMoleculeType != SEPARATE_DLIST_PER_RINFO_MOLECULE) { - - if ((primaryRenderMethod != VirtualUniverse.mc.getDisplayListRenderMethod()) && - (pass == TextureBin.USE_DISPLAYLIST)) { - pass = TextureBin.USE_VERTEXARRAY; - } - if (primaryRenderMethod.render(this, cv, pass, primaryRenderAtomList,dirtyBits)) + if (primaryRenderMethod.render(this, cv, primaryRenderAtomList,dirtyBits)) isVisible = true; } else { - if (renderBin.dlistRenderMethod.renderSeparateDlistPerRinfo(this, cv, pass,primaryRenderAtomList,dirtyBits)) + if (renderBin.dlistRenderMethod.renderSeparateDlistPerRinfo(this, cv, primaryRenderAtomList,dirtyBits)) isVisible = true; } } else { - if (pass == TextureBin.USE_DISPLAYLIST) { - pass = TextureBin.USE_VERTEXARRAY; - } - if(cachedVertexArrayRenderMethod.render(this, cv, pass, + if(cachedVertexArrayRenderMethod.render(this, cv, primaryRenderAtomList, dirtyBits)) { isVisible = true; @@ -1875,10 +1857,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen else { // TEXT3D or ORIENTEDSHAPE3D if (primaryRenderAtomList != null) { - if (pass == TextureBin.USE_DISPLAYLIST) { - pass = TextureBin.USE_VERTEXARRAY; - } - if(primaryRenderMethod.render(this, cv, pass, primaryRenderAtomList, + if(primaryRenderMethod.render(this, cv, primaryRenderAtomList, dirtyBits)) { isVisible = true; } @@ -1886,19 +1865,15 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen } if (separateDlistRenderAtomList != null) { - if (modeSupportDL) { - if(renderBin.dlistRenderMethod. - renderSeparateDlists(this, cv, pass, - separateDlistRenderAtomList, - dirtyBits)) { - isVisible = true; - } + if (modeSupportDL) { + if(renderBin.dlistRenderMethod.renderSeparateDlists(this, cv, + separateDlistRenderAtomList, + dirtyBits)) { + isVisible = true; + } } else { - if (pass == TextureBin.USE_DISPLAYLIST) { - pass = TextureBin.USE_VERTEXARRAY; - } - if(cachedVertexArrayRenderMethod.render(this, cv, pass, + if(cachedVertexArrayRenderMethod.render(this, cv, separateDlistRenderAtomList, dirtyBits)) { isVisible = true; @@ -1910,10 +1885,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen // XXXX: In the case of independent primitives such as quads, // it would still be better to call multi draw arrays if (vertexArrayRenderAtomList != null) { - if (pass == TextureBin.USE_DISPLAYLIST) { - pass = TextureBin.USE_VERTEXARRAY; - } - if(cachedVertexArrayRenderMethod.render(this, cv, pass, + if(cachedVertexArrayRenderMethod.render(this, cv, vertexArrayRenderAtomList, dirtyBits)) { isVisible = true; @@ -2121,6 +2093,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen } void transparentSortRender(Canvas3D cv, int pass, TransparentRenderingInfo tinfo) { + assert pass < 0; Transform3D modelMatrix = trans[localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]]; @@ -2169,12 +2142,12 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen // System.out.println("cachedVertexArrayRenderMethod = "+cachedVertexArrayRenderMethod); // System.out.println("tinfo.rInfo = "+tinfo.rInfo); if (modeSupportDL) { - renderBin.dlistRenderMethod.renderSeparateDlistPerRinfo(this, cv, pass, + renderBin.dlistRenderMethod.renderSeparateDlistPerRinfo(this, cv, tinfo.rInfo, ALL_DIRTY_BITS); } else { - cachedVertexArrayRenderMethod.render(this, cv, pass, tinfo.rInfo,ALL_DIRTY_BITS); + cachedVertexArrayRenderMethod.render(this, cv, tinfo.rInfo,ALL_DIRTY_BITS); } tinfo.rInfo.next = save; } @@ -2184,7 +2157,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen tinfo.rInfo.next = null; // System.out.println("cachedVertexArrayRenderMethod = "+cachedVertexArrayRenderMethod); // System.out.println("tinfo.rInfo = "+tinfo.rInfo); - cachedVertexArrayRenderMethod.render(this, cv, pass, tinfo.rInfo, + cachedVertexArrayRenderMethod.render(this, cv, tinfo.rInfo, ALL_DIRTY_BITS); tinfo.rInfo.next = save; } @@ -2194,19 +2167,19 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen RenderAtomListInfo save= tinfo.rInfo.next; tinfo.rInfo.next = null; if (modeSupportDL) { - renderBin.dlistRenderMethod.renderSeparateDlists(this, cv, pass, + renderBin.dlistRenderMethod.renderSeparateDlists(this, cv, tinfo.rInfo, ALL_DIRTY_BITS); } else { - cachedVertexArrayRenderMethod.render(this, cv, pass, tinfo.rInfo, + cachedVertexArrayRenderMethod.render(this, cv, tinfo.rInfo, ALL_DIRTY_BITS); } tinfo.rInfo.next = save; } else { RenderAtomListInfo save= tinfo.rInfo.next; - primaryRenderMethod.render(this, cv, pass, primaryRenderAtomList, + primaryRenderMethod.render(this, cv, primaryRenderAtomList, ALL_DIRTY_BITS); tinfo.rInfo.next = save; } @@ -2264,7 +2237,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen } - void releaseAllPrimaryDisplayListResources(Canvas3D cv) { + void releaseAllPrimaryDisplayListResources(Canvas3D cv, Context ctx) { if (primaryRenderAtomList != null) { if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) { RenderAtomListInfo ra = primaryRenderAtomList; @@ -2272,14 +2245,14 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen while (ra != null) { id = ra.renderAtom.dlistIds[ra.index]; if (id > 0) { - cv.freeDisplayList(cv.ctx, id); + cv.freeDisplayList(ctx, id); } ra = ra.next; } } else if (primaryMoleculeType == DLIST_MOLECULE) { if (displayListId > 0) { - cv.freeDisplayList(cv.ctx, displayListId); + cv.freeDisplayList(ctx, displayListId); } } } @@ -2985,13 +2958,6 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen void handleLocaleChange() { if (locale == renderBin.locale) { if (localToVworld != localeLocalToVworld) { - if (localeTranslation != null) { - // return to the freelist; - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - localeLocalToVworld[0]); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - localeLocalToVworld[1]); - } localeLocalToVworld = localToVworld; localeTranslation = null; } @@ -3000,11 +2966,6 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen // Using the localToVworl then, go back to making a new copy if (localeTranslation == null) { localeLocalToVworld = new Transform3D[2]; - /* - localeLocalToVworld[0] = VirtualUniverse.mc.getTransform3D(null); - localeLocalToVworld[1] = VirtualUniverse.mc.getTransform3D(null); - */ - localeLocalToVworld[0] = new Transform3D(); localeLocalToVworld[1] = new Transform3D(); diff --git a/src/classes/share/javax/media/j3d/Renderer.java b/src/classes/share/javax/media/j3d/Renderer.java index db0d8b3..3c73a7e 100644 --- a/src/classes/share/javax/media/j3d/Renderer.java +++ b/src/classes/share/javax/media/j3d/Renderer.java @@ -25,7 +25,7 @@ import java.util.*; class Renderer extends J3dThread { - int objectId = -1; + // This action causes this thread to wait static final int WAIT = 0; @@ -78,26 +78,26 @@ class Renderer extends J3dThread { boolean sharedStereoZBuffer; // This is the id for the underlying sharable graphics context - long sharedCtx = 0; + Context sharedCtx = null; // since the sharedCtx id can be the same as the previous one, // we need to keep a time stamp to differentiate the contexts with the // same id long sharedCtxTimeStamp = 0; - // display id - to free shared context - long display; - int window; + // display and drawable, used to free shared context + private long sharedCtxDisplay = 0; + private Drawable sharedCtxDrawable = null; /** * This is the id of the current rendering context */ - long currentCtx = -1; + Context currentCtx = null; /** - * This is the id of the current rendering window + * This is the id of the current rendering drawable */ - long currentWindow = 0; + Drawable currentDrawable = null; // an unique bit to identify this renderer int rendererBit = 0; @@ -132,22 +132,21 @@ class Renderer extends J3dThread { Screen3D onScreen; Screen3D offScreen; - // full screen anti-aliasing projection matrices - double accumLeftProjMat[] = new double[16]; - double accumRightProjMat[] = new double[16]; - double accumInfLeftProjMat[] = new double[16]; - double accumInfRightProjMat[] = new double[16]; + // full screen anti-aliasing projection matrices + Transform3D accumLeftProj = new Transform3D(); + Transform3D accumRightProj = new Transform3D(); + Transform3D accumInfLeftProj = new Transform3D(); + Transform3D accumInfRightProj = new Transform3D(); // rendering messages J3dMessage m[]; int nmesg = 0; // List of contexts created - ArrayList listOfCtxs = new ArrayList(); + ArrayList<Context> listOfCtxs = new ArrayList<Context>(); // Parallel list of canvases - ArrayList listOfCanvases = new ArrayList(); - + ArrayList<Canvas3D> listOfCanvases = new ArrayList<Canvas3D>(); boolean needToRebuildDisplayList = false; boolean needToResendTextureDown = false; @@ -161,8 +160,6 @@ class Renderer extends J3dThread { // It is used when sharedCtx = true; ArrayList textureIDResourceTable = new ArrayList(5); - native void D3DCleanUp(); - private synchronized int newInstanceNum() { return (++numInstances); } @@ -215,112 +212,133 @@ class Renderer extends J3dThread { opArg = ((Integer)args[0]).intValue(); try { - if (opArg == SWAP) { - - Object [] swapArray = (Object[])args[2]; - - view = (View)args[3]; - - for (i=0; i<swapArray.length; i++) { - cv = (Canvas3D) swapArray[i]; - if (!cv.isRunning) { - continue; - } - - doneSwap: try { - - if (!cv.validCanvas) { - continue; - } - - if (cv.active && (cv.ctx != 0) && - (cv.view != null) && (cv.imageReady)) { - if (cv.useDoubleBuffer) { - synchronized (cv.drawingSurfaceObject) { - if (cv.validCtx) { - if (VirtualUniverse.mc.doDsiRenderLock) { - // Set doDsiLock flag for rendering based on system - // property, If we force DSI lock for swap - // buffer, we lose most of the parallelism that having - // multiple renderers gives us. - - if (!cv.drawingSurfaceObject.renderLock()) { - break doneSwap; - } - cv.makeCtxCurrent(); - cv.syncRender(cv.ctx, true); - status = cv.swapBuffers(cv.ctx, - cv.screen.display, - cv.window); - if (status != Canvas3D.NOCHANGE) { - cv.resetRendering(status); - } - cv.drawingSurfaceObject.unLock(); - } else { - cv.makeCtxCurrent(); - - cv.syncRender(cv.ctx, true); - status = cv.swapBuffers(cv.ctx, - cv.screen.display, - cv.window); - if (status != Canvas3D.NOCHANGE) { - cv.resetRendering(status); - } - - } - } - } - } - cv.view.inCanvasCallback = true; - try { - cv.postSwap(); - } catch (RuntimeException e) { - System.err.println("Exception occurred during Canvas3D callback:"); - e.printStackTrace(); - } - // reset flag - cv.imageReady = false; - cv.view.inCanvasCallback = false; - // Clear canvasDirty bit ONLY when postSwap() success - - // Set all dirty bits except environment set and lightbin - // they are only set dirty if the last used light bin or - // environment set values for this canvas change between - // one frame and other - - if (!cv.ctxChanged) { - cv.canvasDirty = (0xffff & ~(Canvas3D.LIGHTBIN_DIRTY | - Canvas3D.LIGHTENABLES_DIRTY | - Canvas3D.AMBIENTLIGHT_DIRTY | - Canvas3D.MODELCLIP_DIRTY | - Canvas3D.VIEW_MATRIX_DIRTY | - Canvas3D.FOG_DIRTY)); - // Force reload of transform next frame - cv.modelMatrix = null; - - // Force the cached renderAtom to null - cv.ra = null; - } else { - cv.ctxChanged = false; - } - } - } catch (NullPointerException ne) { - //ne.printStackTrace(); - if (VirtualUniverse.mc.doDsiRenderLock) { - cv.drawingSurfaceObject.unLock(); - } - } - } - - if (view != null) { // STOP_TIMER - // incElapsedFrames() is delay until MC:updateMirroObject - if (view.viewCache.getDoHeadTracking()) { - VirtualUniverse.mc.sendRunMessage(view, - J3dThread.RENDER_THREAD); - } - } - - } else if (opArg == REQUESTCLEANUP) { + if (opArg == SWAP) { + + Object [] swapArray = (Object[])args[2]; + + view = (View)args[3]; + + for (i=0; i<swapArray.length; i++) { + cv = (Canvas3D) swapArray[i]; + if (!cv.isRunning) { + continue; + } + + doneSwap: try { + + if (!cv.validCanvas) { + continue; + } + + if (cv.active && (cv.ctx != null) && + (cv.view != null) && (cv.imageReady)) { + if (cv.useDoubleBuffer) { + synchronized (cv.drawingSurfaceObject) { + if (cv.validCtx) { + if (VirtualUniverse.mc.doDsiRenderLock) { + // Set doDsiLock flag for rendering based on system + // property, If we force DSI lock for swap + // buffer, we lose most of the parallelism that having + // multiple renderers gives us. + + if (!cv.drawingSurfaceObject.renderLock()) { + break doneSwap; + } + cv.makeCtxCurrent(); + cv.syncRender(cv.ctx, true); + status = cv.swapBuffers(cv.ctx, + cv.screen.display, + cv.drawable); + if (status != Canvas3D.NOCHANGE) { + cv.resetRendering(status); + } + cv.drawingSurfaceObject.unLock(); + } else { + cv.makeCtxCurrent(); + + cv.syncRender(cv.ctx, true); + status = cv.swapBuffers(cv.ctx, + cv.screen.display, + cv.drawable); + if (status != Canvas3D.NOCHANGE) { + cv.resetRendering(status); + } + + } + } + } + } + cv.view.inCanvasCallback = true; + try { + cv.postSwap(); + } catch (RuntimeException e) { + System.err.println("Exception occurred during Canvas3D callback:"); + e.printStackTrace(); + } catch (Error e) { + // Issue 264 - catch Error so Renderer doesn't die + System.err.println("Error occurred during Canvas3D callback:"); + e.printStackTrace(); + } + // reset flag + cv.imageReady = false; + cv.view.inCanvasCallback = false; + // Clear canvasDirty bit ONLY when postSwap() success + + // Set all dirty bits except environment set and lightbin + // they are only set dirty if the last used light bin or + // environment set values for this canvas change between + // one frame and other + + if (!cv.ctxChanged) { + cv.canvasDirty = (0xffff & ~(Canvas3D.LIGHTBIN_DIRTY | + Canvas3D.LIGHTENABLES_DIRTY | + Canvas3D.AMBIENTLIGHT_DIRTY | + Canvas3D.MODELCLIP_DIRTY | + Canvas3D.VIEW_MATRIX_DIRTY | + Canvas3D.FOG_DIRTY)); + // Force reload of transform next frame + cv.modelMatrix = null; + + // Force the cached renderAtom to null + cv.ra = null; + } else { + cv.ctxChanged = false; + } + } + } catch (NullPointerException ne) { + // Ignore NPE + if (VirtualUniverse.mc.doDsiRenderLock) { + cv.drawingSurfaceObject.unLock(); + } + } catch (RuntimeException ex) { + ex.printStackTrace(); + + if (VirtualUniverse.mc.doDsiRenderLock) { + cv.drawingSurfaceObject.unLock(); + } + + // Issue 260 : indicate fatal error and notify error listeners + cv.setFatalError(); + RenderingError err = + new RenderingError(RenderingError.UNEXPECTED_RENDERING_ERROR, + J3dI18N.getString("Renderer0")); + err.setCanvas3D(cv); + err.setGraphicsDevice(cv.graphicsConfiguration.getDevice()); + notifyErrorListeners(err); + } + + cv.releaseCtx(); + } + + if (view != null) { // STOP_TIMER + // incElapsedFrames() is delay until MC:updateMirroObject + if (view.viewCache.getDoHeadTracking()) { + VirtualUniverse.mc.sendRunMessage(view, + J3dThread.RENDER_THREAD); + } + } + + } else if (opArg == REQUESTCLEANUP) { Integer mtype = (Integer) args[2]; if (mtype == MasterControl.REMOVEALLCTXS_CLEANUP) { @@ -329,12 +347,12 @@ class Renderer extends J3dThread { } else if (mtype == MasterControl.FREECONTEXT_CLEANUP) { // from MasterControl freeContext(View v) cv = (Canvas3D) args[1]; - removeCtx(cv, cv.screen.display, cv.window, cv.ctx, + removeCtx(cv, cv.screen.display, cv.drawable, cv.ctx, true, true, false); } else if (mtype == MasterControl.RESETCANVAS_CLEANUP) { // from MasterControl RESET_CANVAS postRequest cv = (Canvas3D) args[1]; - if (cv.ctx != 0) { + if (cv.ctx != null) { cv.makeCtxCurrent(); } cv.freeContextResources(cv.screen.renderer, true, cv.ctx); @@ -344,22 +362,27 @@ class Renderer extends J3dThread { Canvas3D c = (Canvas3D) obj[0]; removeCtx(c, ((Long) obj[1]).longValue(), - ((Integer) obj[2]).intValue(), - ((Long) obj[3]).longValue(), + (Drawable) obj[2], + (Context) obj[3], false, !c.offScreen, false); } return; } else { // RENDER || REQUESTRENDER - int renderType; nmesg = 0; int totalMessages = 0; if (opArg == RENDER) { m = renderMessage; - m[0] = VirtualUniverse.mc.getMessage(); - m[0].type = J3dMessage.RENDER_RETAINED; + m[0] = new J3dMessage(); + // Issue 131: Set appropriate message type + if (((Canvas3D)args[1]).offScreen) { + m[0].type = J3dMessage.RENDER_OFFSCREEN; + } + else { + m[0].type = J3dMessage.RENDER_RETAINED; + } m[0].incRefcount(); m[0].args[0] = args[1]; totalMessages = 1; @@ -370,7 +393,7 @@ class Renderer extends J3dThread { return; } } - + doneRender: while (nmesg < totalMessages) { @@ -383,20 +406,19 @@ class Renderer extends J3dThread { Integer reqType = (Integer) m[nmesg].args[2]; Canvas3D c = (Canvas3D) secondArg; if (reqType == MasterControl.SET_GRAPHICSCONFIG_FEATURES) { - NativeConfigTemplate3D nct = - GraphicsConfigTemplate3D.nativeTemplate; + try { if (c.offScreen) { // offScreen canvas neither supports // double buffering nor stereo c.doubleBufferAvailable = false; c.stereoAvailable = false; } else { - c.doubleBufferAvailable = nct.hasDoubleBuffer(c); - c.stereoAvailable = nct.hasStereo(c); + c.doubleBufferAvailable = c.hasDoubleBuffer(); + c.stereoAvailable = c.hasStereo(); } // Setup stencil related variables. - c.actualStencilSize = nct.getStencilSize(c); + c.actualStencilSize = c.getStencilSize(); boolean userOwnsStencil = c.requestedStencilSize > 0; c.userStencilAvailable = @@ -404,35 +426,53 @@ class Renderer extends J3dThread { c.systemStencilAvailable = (!userOwnsStencil && (c.actualStencilSize > 0)); - /* - System.out.println("Renderer :check for nct configuration"); - System.out.println("-- userStencilAvailable " + - c.userStencilAvailable); - System.out.println("-- systemStencilAvailable " + - c.systemStencilAvailable); - */ - c.sceneAntialiasingMultiSamplesAvailable = - nct.hasSceneAntialiasingMultisample(c); + c.hasSceneAntialiasingMultisample(); if (c.sceneAntialiasingMultiSamplesAvailable) { c.sceneAntialiasingAvailable = true; } else { c.sceneAntialiasingAvailable = - nct.hasSceneAntialiasingAccum(c); + c.hasSceneAntialiasingAccum(); } + } catch (RuntimeException ex) { + ex.printStackTrace(); + + // Issue 260 : indicate fatal error and notify error listeners + c.setFatalError(); + RenderingError err = + new RenderingError(RenderingError.GRAPHICS_CONFIG_ERROR, + J3dI18N.getString("Renderer1")); + err.setCanvas3D(c); + err.setGraphicsDevice(c.graphicsConfiguration.getDevice()); + notifyErrorListeners(err); + } GraphicsConfigTemplate3D.runMonitor(J3dThread.NOTIFY); } else if (reqType == MasterControl.SET_QUERYPROPERTIES){ - c.createQueryContext(); + try { + c.createQueryContext(); + } catch (RuntimeException ex) { + ex.printStackTrace(); + + // Issue 260 : indicate fatal error and notify error listeners + c.setFatalError(); + RenderingError err = + new RenderingError(RenderingError.CONTEXT_CREATION_ERROR, + J3dI18N.getString("Renderer2")); + err.setCanvas3D(c); + err.setGraphicsDevice(c.graphicsConfiguration.getDevice()); + notifyErrorListeners(err); + } // currentCtx change after we create a new context GraphicsConfigTemplate3D.runMonitor(J3dThread.NOTIFY); - currentCtx = -1; - currentWindow = 0; + currentCtx = null; + currentDrawable = null; } } else if (secondArg instanceof Integer) { - // message from TextureRetained finalize() method - // to free texture id - freeTextureID(((Integer) secondArg).intValue(), (String)m[nmesg].args[2]); + // Issue 121 - This was formerly used as a message from + // the now-nonexistant TextureRetained finalize() method + // to free the texture id + throw new AssertionError(); } else if (secondArg instanceof GeometryArrayRetained) { // message from GeometryArrayRetained // clearLive() to free D3D array @@ -441,20 +481,49 @@ class Renderer extends J3dThread { GraphicsConfigTemplate3D gct = (GraphicsConfigTemplate3D) secondArg; Integer reqType = (Integer) m[nmesg].args[2]; - if (reqType == MasterControl.GETBESTCONFIG) { - gct.testCfg = - gct.nativeTemplate.getBestConfiguration(gct, - (GraphicsConfiguration []) gct.testCfg); + if (reqType == MasterControl.GETBESTCONFIG) { + GraphicsConfiguration gcfg = null; + GraphicsConfiguration [] gcList = (GraphicsConfiguration []) gct.testCfg; + try { + gcfg = Pipeline.getPipeline().getBestConfiguration(gct, gcList); + } catch (NullPointerException npe) { + npe.printStackTrace(); + } catch (RuntimeException ex) { + ex.printStackTrace(); + + // Issue 260 : notify error listeners + RenderingError err = + new RenderingError(RenderingError.GRAPHICS_CONFIG_ERROR, + J3dI18N.getString("Renderer3")); + err.setGraphicsDevice(gcList[0].getDevice()); + notifyErrorListeners(err); + } + + gct.testCfg = gcfg; } else if (reqType == MasterControl.ISCONFIGSUPPORT) { - if (gct.nativeTemplate.isGraphicsConfigSupported(gct, - (GraphicsConfiguration) gct.testCfg)) { - gct.testCfg = Boolean.TRUE; - } else { - gct.testCfg = Boolean.FALSE; - } - } + boolean rval = false; + GraphicsConfiguration gc = (GraphicsConfiguration) gct.testCfg; + try { + if (Pipeline.getPipeline().isGraphicsConfigSupported(gct, gc)) { + rval = true; + } + } catch (NullPointerException npe) { + npe.printStackTrace(); + } catch (RuntimeException ex) { + ex.printStackTrace(); + + // Issue 260 : notify error listeners + RenderingError err = + new RenderingError(RenderingError.GRAPHICS_CONFIG_ERROR, + J3dI18N.getString("Renderer4")); + err.setGraphicsDevice(gc.getDevice()); + notifyErrorListeners(err); + } + + gct.testCfg = Boolean.valueOf(rval); + } gct.runMonitor(J3dThread.NOTIFY); - } + } m[nmesg++].decRefcount(); continue; @@ -467,28 +536,45 @@ class Renderer extends J3dThread { if (renderType == J3dMessage.CREATE_OFFSCREENBUFFER) { // Fix for issue 18. // Fix for issue 20. - canvas.window = - canvas.createOffScreenBuffer(canvas.ctx, - canvas.screen.display, - canvas.vid, - canvas.fbConfig, - canvas.offScreenCanvasSize.width, - canvas.offScreenCanvasSize.height); + + canvas.drawable = null; + try { + canvas.drawable = + canvas.createOffScreenBuffer(canvas.ctx, + canvas.screen.display, + canvas.fbConfig, + canvas.offScreenCanvasSize.width, + canvas.offScreenCanvasSize.height); + } catch (RuntimeException ex) { + ex.printStackTrace(); + } + + if (canvas.drawable == null) { + // Issue 260 : indicate fatal error and notify error listeners + canvas.setFatalError(); + RenderingError err = + new RenderingError(RenderingError.OFF_SCREEN_BUFFER_ERROR, + J3dI18N.getString("Renderer5")); + err.setCanvas3D(canvas); + err.setGraphicsDevice(canvas.graphicsConfiguration.getDevice()); + notifyErrorListeners(err); + } + canvas.offScreenBufferPending = false; m[nmesg++].decRefcount(); continue; } else if (renderType == J3dMessage.DESTROY_CTX_AND_OFFSCREENBUFFER) { - // Fix for issue 175. - // destroy ctx. - // Should be able to collaspe both call into one. Will do this in 1.5, - // it is a little risky for 1.4 beta3. - removeCtx(canvas, canvas.screen.display, canvas.window, canvas.ctx, - false, !canvas.offScreen, false); - // destroy offScreenBuffer. - removeCtx(canvas, canvas.screen.display, canvas.window, 0, - false, !canvas.offScreen, true); - + Object[] obj = m[nmesg].args; + + // Fix for issue 175: destroy ctx & off-screen buffer + // Fix for issue 340: get display, drawable & ctx from msg + removeCtx(canvas, + ((Long) obj[1]).longValue(), + (Drawable) obj[2], + (Context) obj[3], + false, !canvas.offScreen, true); + canvas.offScreenBufferPending = false; m[nmesg++].decRefcount(); continue; @@ -525,8 +611,13 @@ class Renderer extends J3dThread { VirtualUniverse.mc.resendTexTimestamp++; needToResendTextureDown = false; } - - if (canvas.ctx != 0) { + + if (canvas.isFatalError()) { + continue; + } + + try { + if (canvas.ctx != null) { // ctx may not construct until doClear(); canvas.beginScene(); } @@ -583,17 +674,11 @@ class Renderer extends J3dThread { case GraphicsContext3D.SET_MODEL_TRANSFORM: t3d = (Transform3D)m[nmesg].args[2]; canvas.graphicsContext3D.doSetModelTransform(t3d); - // return t3d to freelist. t3d was gotten from GraphicsContext3D - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - t3d); break; case GraphicsContext3D.MULTIPLY_MODEL_TRANSFORM: - t3d = (Transform3D)m[nmesg].args[2]; - canvas.graphicsContext3D.doMultiplyModelTransform(t3d); - // return t3d to freelist. t3d was gotten from GraphicsContext3D - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - t3d); - break; + t3d = (Transform3D)m[nmesg].args[2]; + canvas.graphicsContext3D.doMultiplyModelTransform(t3d); + break; case GraphicsContext3D.SET_SOUND: canvas.graphicsContext3D.doSetSound( (Sound)m[nmesg].args[2], @@ -643,6 +728,9 @@ class Renderer extends J3dThread { ((Point) ar[3]).y, (ImageObserver) ar[4]); break; + case GraphicsContext3D.DISPOSE2D: + canvas.graphics2D.doDispose(); + break; case GraphicsContext3D.SET_MODELCLIP: canvas.graphicsContext3D.doSetModelClip( (ModelClip)m[nmesg].args[2]); @@ -651,30 +739,53 @@ class Renderer extends J3dThread { break; } - if (canvas.ctx != 0) { + if (canvas.ctx != null) { canvas.endScene(); } + } catch (RuntimeException ex) { + ex.printStackTrace(); + + // Issue 260 : indicate fatal error and notify error listeners + canvas.setFatalError(); + RenderingError err = + new RenderingError(RenderingError.CONTEXT_CREATION_ERROR, + J3dI18N.getString("Renderer6")); + err.setCanvas3D(canvas); + err.setGraphicsDevice(canvas.graphicsConfiguration.getDevice()); + notifyErrorListeners(err); + } + m[nmesg++].decRefcount(); } else { // retained mode rendering m[nmesg++].decRefcount(); + + if (canvas.isFatalError()) { + continue; + } ImageComponent2DRetained offBufRetained = null; if (renderType == J3dMessage.RENDER_OFFSCREEN) { - if (canvas.window == 0 || !canvas.active) { + // Issue 131: set offScreenRendering flag here, since it + // otherwise won't be set for auto-off-screen rendering + // (which doesn't use renderOffScreenBuffer) + canvas.offScreenRendering = true; + if (canvas.drawable == null || !canvas.active) { canvas.offScreenRendering = false; continue; } else { offBufRetained = (ImageComponent2DRetained) canvas.offScreenBuffer.retained; - if (offBufRetained.isByReference()) { - offBufRetained.geomLock.getLock(); - offBufRetained.evaluateExtensions( - canvas.extensionsSupported); - } + if (offBufRetained.isByReference()) { + offBufRetained.geomLock.getLock(); + } + + offBufRetained.evaluateExtensions(canvas); + } + } else if (!canvas.active) { continue; } @@ -687,8 +798,6 @@ class Renderer extends J3dThread { canvas.drawingSurfaceObject.getDrawingSurfaceObjectInfo(); } - boolean background_image_update = false; - renderBin = canvas.view.renderBin; // setup rendering context @@ -698,8 +807,9 @@ class Renderer extends J3dThread { if (canvas.useSharedCtx) { - if (sharedCtx == 0) { - display = canvas.screen.display; + if (sharedCtx == null) { + sharedCtxDisplay = canvas.screen.display; + sharedCtxDrawable = canvas.drawable; // Always lock for context create if (!canvas.drawingSurfaceObject.renderLock()) { @@ -707,17 +817,35 @@ class Renderer extends J3dThread { offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } + canvas.offScreenRendering = false; break doneRender; } synchronized (VirtualUniverse.mc.contextCreationLock) { - sharedCtx = canvas.createNewContext(0, true); - if (sharedCtx == 0) { + sharedCtx = null; + try { + sharedCtx = canvas.createNewContext(null, true); + } catch (RuntimeException ex) { + ex.printStackTrace(); + } + + if (sharedCtx == null) { canvas.drawingSurfaceObject.unLock(); if ((offBufRetained != null) && offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } + canvas.offScreenRendering = false; + + // Issue 260 : indicate fatal error and notify error listeners + canvas.setFatalError(); + RenderingError err = + new RenderingError(RenderingError.CONTEXT_CREATION_ERROR, + J3dI18N.getString("Renderer7")); + err.setCanvas3D(canvas); + err.setGraphicsDevice(canvas.graphicsConfiguration.getDevice()); + notifyErrorListeners(err); + break doneRender; } sharedCtxTimeStamp = @@ -730,9 +858,7 @@ class Renderer extends J3dThread { } } - if (canvas.ctx == 0) { - - display = canvas.screen.display; + if (canvas.ctx == null) { // Always lock for context create if (!canvas.drawingSurfaceObject.renderLock()) { @@ -740,19 +866,36 @@ class Renderer extends J3dThread { offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } + canvas.offScreenRendering = false; break doneRender; } synchronized (VirtualUniverse.mc.contextCreationLock) { - canvas.ctx = canvas.createNewContext(sharedCtx, false); + canvas.ctx = null; + try { + canvas.ctx = canvas.createNewContext(sharedCtx, false); + } catch (RuntimeException ex) { + ex.printStackTrace(); + } - if (canvas.ctx == 0) { + if (canvas.ctx == null) { canvas.drawingSurfaceObject.unLock(); if ((offBufRetained != null) && offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } - break doneRender; + canvas.offScreenRendering = false; + + // Issue 260 : indicate fatal error and notify error listeners + canvas.setFatalError(); + RenderingError err = + new RenderingError(RenderingError.CONTEXT_CREATION_ERROR, + J3dI18N.getString("Renderer7")); + err.setCanvas3D(canvas); + err.setGraphicsDevice(canvas.graphicsConfiguration.getDevice()); + notifyErrorListeners(err); + + break doneRender; } if (canvas.graphics2D != null) { @@ -761,13 +904,15 @@ class Renderer extends J3dThread { canvas.ctxTimeStamp = VirtualUniverse.mc.getContextTimeStamp(); - listOfCtxs.add(new Long(canvas.ctx)); + listOfCtxs.add(canvas.ctx); listOfCanvases.add(canvas); if (renderBin.nodeComponentList.size() > 0) { for (i = 0; i < renderBin.nodeComponentList.size(); i++) { NodeComponentRetained nc = (NodeComponentRetained)renderBin.nodeComponentList.get(i); - nc.evaluateExtensions(canvas.extensionsSupported); + if(nc instanceof ImageComponent2DRetained) { + ((ImageComponent2DRetained)nc).evaluateExtensions(canvas); + } } } @@ -781,11 +926,6 @@ class Renderer extends J3dThread { canvas.createTexUnitState(); } - // Create the texture unit state map - if (canvas.texUnitStateMap == null) { - canvas.createTexUnitStateMap(); - } - canvas.resetImmediateRendering(Canvas3D.NOCHANGE); canvas.drawingSurfaceObject.contextValidated(); @@ -808,6 +948,7 @@ class Renderer extends J3dThread { offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } + canvas.offScreenRendering = false; break doneRender; } @@ -822,13 +963,6 @@ class Renderer extends J3dThread { canvas.freeResourcesInFreeList(canvas.ctx); } - // save the BACKGROUND_IMAGE_DIRTY before canvas.updateViewCache - // clean it - synchronized (canvas.dirtyMaskLock) { - background_image_update = - ((canvas.cvDirtyMask[Canvas3D.RENDERER_DIRTY_IDX] & Canvas3D.BACKGROUND_IMAGE_DIRTY) != 0); - } - if (VirtualUniverse.mc.doDsiRenderLock) { canvas.drawingSurfaceObject.unLock(); } @@ -848,6 +982,7 @@ class Renderer extends J3dThread { offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } + canvas.offScreenRendering = false; break doneRender; } @@ -933,14 +1068,14 @@ class Renderer extends J3dThread { canvas.sceneAntialiasingAvailable) { if (!VirtualUniverse.mc.isD3D() && - ((canvas.extensionsSupported & Canvas3D.ARB_MULTISAMPLE) == 0) || + ((canvas.extensionsSupported & Canvas3D.MULTISAMPLE) == 0) || !canvas.sceneAntialiasingMultiSamplesAvailable) { doAccum = true; num_accum_passes = NUM_ACCUMULATION_SAMPLES; System.arraycopy( cvCache.getLeftProjection().mat, - 0, accumLeftProjMat, 0, 16); + 0, accumLeftProj.mat, 0, 16); accumDxFactor = ( @@ -952,29 +1087,29 @@ class Renderer extends J3dThread { canvas.canvasViewCache.getCanvasHeight())*canvas.view.fieldOfView; - accumLeftX = accumLeftProjMat[3]; - accumLeftY = accumLeftProjMat[7]; + accumLeftX = accumLeftProj.mat[3]; + accumLeftY = accumLeftProj.mat[7]; if (useStereo) { System.arraycopy( cvCache.getRightProjection().mat, - 0, accumRightProjMat, 0, 16); - accumRightX = accumRightProjMat[3]; - accumRightY = accumRightProjMat[7]; + 0, accumRightProj.mat, 0, 16); + accumRightX = accumRightProj.mat[3]; + accumRightY = accumRightProj.mat[7]; } if (renderBin.geometryBackground != null) { System.arraycopy( cvCache.getInfLeftProjection().mat, - 0, accumInfLeftProjMat, 0, 16); - accumInfLeftX = accumInfLeftProjMat[3]; - accumInfLeftY = accumInfLeftProjMat[7]; + 0, accumInfLeftProj.mat, 0, 16); + accumInfLeftX = accumInfLeftProj.mat[3]; + accumInfLeftY = accumInfLeftProj.mat[7]; if (useStereo) { System.arraycopy( cvCache.getInfRightProjection().mat, - 0, accumInfRightProjMat, 0, 16); - accumInfRightX = accumInfRightProjMat[3]; - accumInfRightY = accumInfRightProjMat[7]; + 0, accumInfRightProj.mat, 0, 16); + accumInfRightX = accumInfRightProj.mat[3]; + accumInfRightY = accumInfRightProj.mat[7]; } } } else { @@ -1005,39 +1140,6 @@ class Renderer extends J3dThread { Canvas3D.FIELD_ALL, canvas.useDoubleBuffer); - // Support DVR - /* - System.out.println("canvas.supportVideoResize() is " + - canvas.supportVideoResize()); - */ - if(canvas.supportVideoResize()) { - if(canvas.view.dvrResizeCompensation != - canvas.cachedDvrResizeCompensation) { - /* - System.out.println("Renderer : dvrResizeComp " + - canvas.view.dvrResizeCompensation); - */ - canvas.videoResizeCompensation(canvas.ctx, - canvas.view.dvrResizeCompensation); - canvas.cachedDvrResizeCompensation = - canvas.view.dvrResizeCompensation; - - } - if(canvas.view.dvrFactor != canvas.cachedDvrFactor) { - /* - System.out.println("Renderer : dvrFactor is " + - canvas.view.dvrFactor); - */ - canvas.videoResize(canvas.ctx, - canvas.screen.display, - canvas.window, - canvas.view.dvrFactor); - canvas.cachedDvrFactor = canvas.view.dvrFactor; - - } - - } - canvas.beginScene(); // this is if the background image resizes with the canvas @@ -1049,41 +1151,9 @@ class Renderer extends J3dThread { // and not in stereo mode if (!doAccum && !sharedStereoZBuffer) { BackgroundRetained bg = renderBin.background; - if (!VirtualUniverse.mc.isBackgroundTexture) { - canvas.clear(canvas.ctx, - bg.color.x, - bg.color.y, - bg.color.z, - winWidth, - winHeight, - bg.image, - bg.imageScaleMode, - (bg.image != null? - bg.image.imageYdown[0]:null)); - } else { - if ((bg.texImage != null) && - (objectId == -1)) { - objectId = VirtualUniverse.mc. - getTexture2DId(); - } - canvas.textureclear(canvas.ctx, - bg.xmax, - bg.ymax, - bg.color.x, - bg.color.y, - bg.color.z, - winWidth, - winHeight, - objectId, - bg.imageScaleMode, - bg.texImage, - background_image_update); - } -// canvas.clear(canvas.ctx, -// bg.color.x, -// bg.color.y, -// bg.color.z, -// bg.image); + + canvas.clear(bg, winWidth, winHeight); + } // handle preRender callback @@ -1095,18 +1165,22 @@ class Renderer extends J3dThread { try { canvas.preRender(); } catch (RuntimeException e) { - System.err.println("Exception occurred " + - "during Canvas3D callback:"); + System.err.println("Exception occurred during Canvas3D callback:"); e.printStackTrace(); + } catch (Error e) { + // Issue 264 - catch Error so Renderer doesn't die + System.err.println("Error occurred during Canvas3D callback:"); + e.printStackTrace(); } canvas.view.inCanvasCallback = false; - + if ((VirtualUniverse.mc.doDsiRenderLock) && (!canvas.drawingSurfaceObject.renderLock())) { if ((offBufRetained != null) && offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } + canvas.offScreenRendering = false; break doneRender; } @@ -1130,82 +1204,54 @@ class Renderer extends J3dThread { accumDy = ACCUM_SAMPLES_Y[apass] * accumDyFactor; - accumLeftProjMat[3] = accumLeftX + - accumLeftProjMat[0] * accumDx + - accumLeftProjMat[1] * accumDy; + accumLeftProj.mat[3] = accumLeftX + + accumLeftProj.mat[0] * accumDx + + accumLeftProj.mat[1] * accumDy; - accumLeftProjMat[7] = accumLeftY + - accumLeftProjMat[4] * accumDx + - accumLeftProjMat[5] * accumDy; + accumLeftProj.mat[7] = accumLeftY + + accumLeftProj.mat[4] * accumDx + + accumLeftProj.mat[5] * accumDy; if (useStereo) { - accumRightProjMat[3] = accumRightX + - accumRightProjMat[0] * accumDx + - accumRightProjMat[1] * accumDy; + accumRightProj.mat[3] = accumRightX + + accumRightProj.mat[0] * accumDx + + accumRightProj.mat[1] * accumDy; - accumRightProjMat[7] = accumRightY + - accumRightProjMat[4] * accumDx + - accumRightProjMat[5] * accumDy; + accumRightProj.mat[7] = accumRightY + + accumRightProj.mat[4] * accumDx + + accumRightProj.mat[5] * accumDy; } if (renderBin.geometryBackground != null) { - accumInfLeftProjMat[3] = accumInfLeftX + - accumInfLeftProjMat[0] * accumDx + - accumInfLeftProjMat[1] * accumDy; + accumInfLeftProj.mat[3] = accumInfLeftX + + accumInfLeftProj.mat[0] * accumDx + + accumInfLeftProj.mat[1] * accumDy; - accumInfLeftProjMat[7] = accumInfLeftY + - accumInfLeftProjMat[4] * accumDx + - accumInfLeftProjMat[5] * accumDy; + accumInfLeftProj.mat[7] = accumInfLeftY + + accumInfLeftProj.mat[4] * accumDx + + accumInfLeftProj.mat[5] * accumDy; if (useStereo) { - accumInfRightProjMat[3] = + accumInfRightProj.mat[3] = accumInfRightX + - accumInfRightProjMat[0] * accumDx + - accumInfRightProjMat[1] * accumDy; + accumInfRightProj.mat[0] * accumDx + + accumInfRightProj.mat[1] * accumDy; - accumInfRightProjMat[7] = + accumInfRightProj.mat[7] = accumInfRightY + - accumInfRightProjMat[4] * accumDx + - accumInfRightProjMat[5] * accumDy; + accumInfRightProj.mat[4] * accumDx + + accumInfRightProj.mat[5] * accumDy; } - } + } } // clear background for stereo and // accumulation buffer cases if (doAccum || sharedStereoZBuffer) { BackgroundRetained bg = renderBin.background; - if (!VirtualUniverse.mc.isBackgroundTexture) { - canvas.clear(canvas.ctx, - bg.color.x, - bg.color.y, - bg.color.z, - winWidth, - winHeight, - bg.image, - bg.imageScaleMode, - (bg.image != null?bg.image.imageYdown[0]:null)); - } - else { - if ((bg.texImage != null) && - (objectId == -1)) { - objectId = VirtualUniverse.mc. - getTexture2DId(); - } - - canvas.textureclear(canvas.ctx, - bg.xmax, - bg.ymax, - bg.color.x, - bg.color.y, - bg.color.z, - winWidth, - winHeight, - objectId, - bg.imageScaleMode, - bg.texImage, - background_image_update); - } + + canvas.clear(bg, winWidth, winHeight); + } // render background geometry @@ -1217,24 +1263,22 @@ class Renderer extends J3dThread { cvCache.getInfLeftVpcToEc(); if (doAccum) { canvas.setProjectionMatrix( - canvas.ctx, - accumInfLeftProjMat); + canvas.ctx, accumInfLeftProj); } else { canvas.setProjectionMatrix( canvas.ctx, - cvCache.getInfLeftProjection().mat); + cvCache.getInfLeftProjection()); } } else { canvas.vpcToEc = cvCache.getInfRightVpcToEc(); if (doAccum) { canvas.setProjectionMatrix( - canvas.ctx, - accumInfRightProjMat); + canvas.ctx, accumInfRightProj); } else { canvas.setProjectionMatrix( canvas.ctx, - cvCache.getInfRightProjection().mat); + cvCache.getInfRightProjection()); } } canvas.vworldToEc.mul(canvas.vpcToEc, @@ -1248,20 +1292,19 @@ class Renderer extends J3dThread { if (pass == 0) { canvas.vpcToEc = cvCache.getLeftVpcToEc(); if (doAccum) { - canvas.setProjectionMatrix( - canvas.ctx, accumLeftProjMat); + canvas.setProjectionMatrix(canvas.ctx, accumLeftProj); } else { canvas.setProjectionMatrix(canvas.ctx, - cvCache.getLeftProjection().mat); + cvCache.getLeftProjection()); } } else { canvas.vpcToEc = cvCache.getRightVpcToEc(); if (doAccum) { canvas.setProjectionMatrix( - canvas.ctx, accumRightProjMat); + canvas.ctx, accumRightProj); } else { canvas.setProjectionMatrix(canvas.ctx, - cvCache.getRightProjection().mat); + cvCache.getRightProjection()); } } canvas.vworldToEc.mul(canvas.vpcToEc, @@ -1295,9 +1338,12 @@ class Renderer extends J3dThread { try { canvas.renderField(stereo_mode); } catch (RuntimeException e) { - System.err.println("Exception occurred during " + - "Canvas3D callback:"); - e.printStackTrace(); + System.err.println("Exception occurred during Canvas3D callback:"); + e.printStackTrace(); + } catch (Error e) { + // Issue 264 - catch Error so Renderer doesn't die + System.err.println("Error occurred during Canvas3D callback:"); + e.printStackTrace(); } canvas.view.inCanvasCallback = false; if ((VirtualUniverse.mc.doDsiRenderLock) && @@ -1306,6 +1352,7 @@ class Renderer extends J3dThread { offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } + canvas.offScreenRendering = false; break doneRender; } @@ -1340,8 +1387,11 @@ class Renderer extends J3dThread { try { canvas.postRender(); } catch (RuntimeException e) { - System.err.println("Exception occurred during " + - "Canvas3D callback:"); + System.err.println("Exception occurred during Canvas3D callback:"); + e.printStackTrace(); + } catch (Error e) { + // Issue 264 - catch Error so Renderer doesn't die + System.err.println("Error occurred during Canvas3D callback:"); e.printStackTrace(); } canvas.view.inCanvasCallback = false; @@ -1351,6 +1401,7 @@ class Renderer extends J3dThread { canvas.syncRender(canvas.ctx, true); canvas.endOffScreenRendering(); + canvas.offScreenRendering = false; // do the postSwap for offscreen here canvas.view.inCanvasCallback = true; @@ -1359,16 +1410,20 @@ class Renderer extends J3dThread { } catch (RuntimeException e) { System.err.println("Exception occurred during Canvas 3D callback:"); e.printStackTrace(); + } catch (Error e) { + // Issue 264 - catch Error so Renderer doesn't die + System.err.println("Error occurred during Canvas3D callback:"); + e.printStackTrace(); } if (offBufRetained.isByReference()) { offBufRetained.geomLock.unLock(); } - canvas.offScreenRendering = false; canvas.view.inCanvasCallback = false; - } + canvas.releaseCtx(); + } canvas.endScene(); @@ -1425,10 +1480,11 @@ class Renderer extends J3dThread { Arrays.fill(m, 0, totalMessages, null); } } - } catch (NullPointerException ne) { + } catch (NullPointerException ne) { + // Print NPE, but otherwise ignore it ne.printStackTrace(); if (canvas != null) { - if (canvas.ctx != 0) { + if (canvas.ctx != null) { canvas.endScene(); } // drawingSurfaceObject will safely ignore @@ -1436,16 +1492,35 @@ class Renderer extends J3dThread { canvas.drawingSurfaceObject.unLock(); } - } + } catch (RuntimeException ex) { + ex.printStackTrace(); + + if (canvas != null) { + if (canvas.ctx != null) { + canvas.endScene(); + } + // drawingSurfaceObject will safely ignore + // this request if this is not lock before + canvas.drawingSurfaceObject.unLock(); + } + + // Issue 260 : indicate fatal error and notify error listeners + canvas.setFatalError(); + RenderingError err = + new RenderingError(RenderingError.UNEXPECTED_RENDERING_ERROR, + J3dI18N.getString("Renderer8")); + err.setCanvas3D(canvas); + if (canvas != null) { + err.setGraphicsDevice(canvas.graphicsConfiguration.getDevice()); + } + notifyErrorListeners(err); + } } // resource clean up void shutdown() { removeAllCtxs(); - - if (VirtualUniverse.mc.isD3D()) { - D3DCleanUp(); - } + Pipeline.getPipeline().cleanupRenderer(); } void cleanup() { @@ -1454,8 +1529,10 @@ class Renderer extends J3dThread { rendererStructure = new RendererStructure(); bgVworldToVpc = new Transform3D(); numframes = 0.0f; - sharedCtx = 0; + sharedCtx = null; sharedCtxTimeStamp = 0; + sharedCtxDisplay = 0; + sharedCtxDrawable = null; dirtyRenderMoleculeList.clear(); dirtyRenderAtomList.clear(); dirtyDlistPerRinfoList.clear(); @@ -1467,24 +1544,22 @@ class Renderer extends J3dThread { nmesg = 0; lasttime = 0; currtime = 0; - display = 0; } - // This is only invoked from removeCtx()/removeAllCtxs() // with drawingSurface already lock - final void makeCtxCurrent(long sharedCtx, long display, int window) { - if (sharedCtx != currentCtx || window != currentWindow) { - Canvas3D.useCtx(sharedCtx, display, window); + final void makeCtxCurrent(Context sharedCtx, long display, Drawable drawable) { + if (sharedCtx != currentCtx || drawable != currentDrawable) { + Canvas3D.useCtx(sharedCtx, display, drawable); /* - if(!Canvas3D.useCtx(sharedCtx, display, window)) { + if(!Canvas3D.useCtx(sharedCtx, display, drawable)) { Thread.dumpStack(); System.err.println("useCtx Fail"); } */ currentCtx = sharedCtx; - currentWindow = window; + currentDrawable = drawable; } } @@ -1492,67 +1567,65 @@ class Renderer extends J3dThread { // Canvas3D postRequest() offScreen rendering since the // user thread will not wait for it. Also we can just // reuse it as Canvas3D did not destroy. - private void removeCtx(Canvas3D cv, long display, int window, long ctx, + private void removeCtx(Canvas3D cv, long display, Drawable drawable, Context ctx, boolean resetCtx, boolean freeBackground, boolean destroyOffScreenBuffer) { - synchronized (VirtualUniverse.mc.contextCreationLock) { - // Fix for issue 18. - // Since we are now the renderer thread, - // we can safely execute destroyOffScreenBuffer. - if(destroyOffScreenBuffer) { - cv.destroyOffScreenBuffer(ctx, display, cv.fbConfig, window); - cv.offScreenBufferPending = false; - } - - if (ctx != 0) { - int idx = listOfCtxs.indexOf(new Long(ctx)); + if (ctx != null) { + int idx = listOfCtxs.indexOf(ctx); if (idx >= 0) { listOfCtxs.remove(idx); listOfCanvases.remove(idx); - // display is always 0 under windows - if ((MasterControl.isWin32 || (display != 0)) && - (window != 0) && cv.added) { + // Issue 326 : don't check display variable here + if ((drawable != null) && cv.added) { // cv.ctx may reset to -1 here so we // always use the ctx pass in. if (cv.drawingSurfaceObject.renderLock()) { // if it is the last one, free shared resources - if (sharedCtx != 0) { + if (sharedCtx != null) { if (listOfCtxs.isEmpty()) { - makeCtxCurrent(sharedCtx, display, window); + makeCtxCurrent(sharedCtx, sharedCtxDisplay, sharedCtxDrawable); freeResourcesInFreeList(null); freeContextResources(); - Canvas3D.destroyContext(display, window, sharedCtx); - currentCtx = -1; - currentWindow = 0; + Canvas3D.destroyContext(sharedCtxDisplay, sharedCtxDrawable, sharedCtx); + currentCtx = null; + currentDrawable = null; } else { freeResourcesInFreeList(cv); } - cv.makeCtxCurrent(ctx, display, window); + cv.makeCtxCurrent(ctx, display, drawable); } else { - cv.makeCtxCurrent(ctx, display, window); + cv.makeCtxCurrent(ctx, display, drawable); cv.freeResourcesInFreeList(ctx); } cv.freeContextResources(this, freeBackground, ctx); - Canvas3D.destroyContext(display, window, ctx); - currentCtx = -1; - currentWindow = 0; + Canvas3D.destroyContext(display, drawable, ctx); + currentCtx = null; + currentDrawable = null; cv.drawingSurfaceObject.unLock(); } } } if (resetCtx) { - cv.ctx = 0; + cv.ctx = null; } - if ((sharedCtx != 0) && listOfCtxs.isEmpty()) { - sharedCtx = 0; + if ((sharedCtx != null) && listOfCtxs.isEmpty()) { + sharedCtx = null; sharedCtxTimeStamp = 0; } cv.ctxTimeStamp = 0; } + + // Fix for issue 18. + // Since we are now the renderer thread, + // we can safely execute destroyOffScreenBuffer. + if(destroyOffScreenBuffer) { + cv.destroyOffScreenBuffer(ctx, display, cv.fbConfig, drawable); + cv.offScreenBufferPending = false; + } } } @@ -1564,41 +1637,41 @@ class Renderer extends J3dThread { for (int i=listOfCanvases.size()-1; i >=0; i--) { cv = (Canvas3D) listOfCanvases.get(i); - if ((cv.screen != null) && (cv.ctx != 0)) { - if ((MasterControl.isWin32 || (display != 0)) && - (cv.window != 0) && cv.added) { + if ((cv.screen != null) && (cv.ctx != null)) { + // Issue 326 : don't check display variable here + if ((cv.drawable != null) && cv.added) { if (cv.drawingSurfaceObject.renderLock()) { // We need to free sharedCtx resource // first before last non-sharedCtx to // workaround Nvidia driver bug under Linux // that crash on freeTexture ID:4685156 - if ((i == 0) && (sharedCtx != 0)) { - makeCtxCurrent(sharedCtx, display, window); + if ((i == 0) && (sharedCtx != null)) { + makeCtxCurrent(sharedCtx, sharedCtxDisplay, sharedCtxDrawable); freeResourcesInFreeList(null); freeContextResources(); - Canvas3D.destroyContext(display, window, sharedCtx); - currentCtx = -1; - currentWindow = 0; + Canvas3D.destroyContext(sharedCtxDisplay, sharedCtxDrawable, sharedCtx); + currentCtx = null; + currentDrawable = null; } cv.makeCtxCurrent(); cv.freeResourcesInFreeList(cv.ctx); cv.freeContextResources(this, true, cv.ctx); Canvas3D.destroyContext(cv.screen.display, - cv.window, + cv.drawable, cv.ctx); - currentCtx = -1; - currentWindow = 0; + currentCtx = null; + currentDrawable = null; cv.drawingSurfaceObject.unLock(); } } } - cv.ctx = 0; + cv.ctx = null; cv.ctxTimeStamp = 0; } - if (sharedCtx != 0) { - sharedCtx = 0; + if (sharedCtx != null) { + sharedCtx = null; sharedCtxTimeStamp = 0; } listOfCanvases.clear(); @@ -1606,49 +1679,6 @@ class Renderer extends J3dThread { } } - void freeTextureID(int texId, String texture) { - Canvas3D currentCanvas = null; - - // get the current canvas - for (int i=listOfCtxs.size()-1; i >= 0; i--) { - Canvas3D c = (Canvas3D) listOfCanvases.get(i); - if (c.ctx == currentCtx) { - currentCanvas = c; - break; - } - } - - if (currentCanvas == null) { - return; - } - - synchronized (VirtualUniverse.mc.contextCreationLock) { - if (sharedCtx != 0) { - currentCanvas.makeCtxCurrent(sharedCtx); - // OGL share context is used - Canvas3D.freeTexture(sharedCtx, texId); - } else { - for (int i=listOfCtxs.size()-1; i >= 0; i--) { - Canvas3D c = (Canvas3D) listOfCanvases.get(i); - c.makeCtxCurrent(); - Canvas3D.freeTexture(c.ctx, texId); - } - } - // restore current context - currentCanvas.makeCtxCurrent(); - } - // Issue 162: TEMPORARY FIX -- don't free the texture ID, since it will - // be freed once per canvas / screen and will subsequently cause the ID - // to be used for multiple textures. -// if (texture.equals("2D")){ -// VirtualUniverse.mc.freeTexture2DId(texId); -// } -// else if(texture.equals("3D")){ -// VirtualUniverse.mc.freeTexture3DId(texId); -// } - } - - // handle free resource in the FreeList void freeResourcesInFreeList(Canvas3D cv) { Iterator it; @@ -1684,7 +1714,18 @@ class Renderer extends J3dThread { textureIDResourceTable.size() + " val = " + val); } else { - textureIDResourceTable.set(val, null); + Object obj = textureIDResourceTable.get(val); + if (obj instanceof TextureRetained) { + TextureRetained tex = (TextureRetained) obj; + synchronized (tex.resourceLock) { + tex.resourceCreationMask &= ~rendererBit; + if (tex.resourceCreationMask == 0) { + tex.freeTextureId(val); + } + } + } + + textureIDResourceTable.set(val, null); } Canvas3D.freeTexture(sharedCtx, val); } @@ -1711,7 +1752,6 @@ class Renderer extends J3dThread { void freeContextResources() { Object obj; TextureRetained tex; - DetailTextureImage detailTex; for (int id = textureIDResourceTable.size()-1; id > 0; id--) { obj = textureIDResourceTable.get(id); @@ -1727,17 +1767,44 @@ class Renderer extends J3dThread { tex.freeTextureId(id); } } - } else if (obj instanceof DetailTextureImage) { - detailTex = (DetailTextureImage) obj; - detailTex.freeDetailTextureId(id, rendererBit); } - } textureIDResourceTable.clear(); // displayList is free in Canvas.freeContextResources() } + + /** + * Send a message to the notification thread, which will call the + * shader error listeners. + */ + static void notifyErrorListeners(RenderingError err) { + J3dNotification notification = new J3dNotification(); + notification.type = J3dNotification.RENDERING_ERROR; + notification.universe = null;//cv.view.universe; + notification.args[0] = err; + VirtualUniverse.mc.sendNotification(notification); + } -} + // Default rendering error listener class + private static RenderingErrorListener defaultErrorListener = null; + synchronized static RenderingErrorListener getDefaultErrorListener() { + if (defaultErrorListener == null) { + defaultErrorListener = new DefaultErrorListener(); + } + + return defaultErrorListener; + } + + static class DefaultErrorListener implements RenderingErrorListener { + public void errorOccurred(RenderingError error) { + System.err.println(); + System.err.println("DefaultRenderingErrorListener.errorOccurred:"); + error.printVerbose(); + System.exit(1); + } + } + +} diff --git a/src/classes/share/javax/media/j3d/RenderingAttributesRetained.java b/src/classes/share/javax/media/j3d/RenderingAttributesRetained.java index 0558b83..c7c80a0 100644 --- a/src/classes/share/javax/media/j3d/RenderingAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/RenderingAttributesRetained.java @@ -491,28 +491,13 @@ class RenderingAttributesRetained extends NodeComponentRetained { * Updates the native context. */ - // TODO : Need to handle stencil operation on the native side -- Chien - native void updateNative(long ctx, - boolean depthBufferWriteEnableOverride, - boolean depthBufferEnableOverride, - boolean depthBufferEnable, - boolean depthBufferWriteEnable, - int depthTestFunction, - float alphaTestValue, int alphaTestFunction, - boolean ignoreVertexColors, - boolean rasterOpEnable, int rasterOp, - boolean userStencilAvailable, boolean stencilEnable, - int stencilFailOp, int stencilZFailOp, int stencilZPassOp, - int stencilFunction, int stencilReferenceValue, - int stencilCompareMask, int stencilWriteMask ); - /** * Updates the native context. */ void updateNative(Canvas3D c3d, boolean depthBufferWriteEnableOverride, boolean depthBufferEnableOverride) { - updateNative(c3d.ctx, + Pipeline.getPipeline().updateRenderingAttributes(c3d.ctx, depthBufferWriteEnableOverride, depthBufferEnableOverride, depthBufferEnable, depthBufferWriteEnable, depthTestFunction, alphaTestValue, alphaTestFunction, ignoreVertexColors, @@ -658,7 +643,7 @@ class RenderingAttributesRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.RENDERINGATTRIBUTES_CHANGED; createMessage.universe = null; @@ -671,7 +656,7 @@ class RenderingAttributesRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; if (attrMask == VISIBLE) createMessage.threads |= J3dThread.UPDATE_GEOMETRY; diff --git a/src/classes/share/javax/media/j3d/RenderingError.java b/src/classes/share/javax/media/j3d/RenderingError.java new file mode 100644 index 0000000..d86e834 --- /dev/null +++ b/src/classes/share/javax/media/j3d/RenderingError.java @@ -0,0 +1,253 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.awt.GraphicsDevice; +import java.io.PrintStream; + +/** + * RenderingError is a container object that holds the details of + * a runtime error that occurs in the Java 3D rendering system. + * + * @since Java 3D 1.5 + */ +public class RenderingError extends Object { + private int errorCode = NO_ERROR; + private String errorMessage = null; + private String detailMessage = null; + private GraphicsDevice graphicsDevice = null; + private Canvas3D canvas = null; + + /** + * Indicates that no error occurred. + */ + public static final int NO_ERROR = 0; + + /** + * Indicates that an unexpected rendering exception was caught by the + * Java 3D renderer thread. + */ + public static final int UNEXPECTED_RENDERING_ERROR = 1; + + /** + * Indicates that an error occurred while getting the best graphics + * configuration or while testing whether a given graphics config is + * supported. + */ + public static final int GRAPHICS_CONFIG_ERROR = 2; + + /** + * Indicates that an error occurred while creating an OpenGL or D3D + * graphics context. This can happen either when querying + * the Canvas3D properties or when rendering. + */ + public static final int CONTEXT_CREATION_ERROR = 3; + + /** + * Indicates a error in creating a rendering buffer for an off-screen + * Canvas3D. + */ + public static final int OFF_SCREEN_BUFFER_ERROR = 4; + + + /** + * Constructs a new RenderingError object indicating no error. The + * error code is set to <code>NO_ERROR</code>. All other fields + * are initialized to null, including the error message. + */ + public RenderingError() { + } + + /** + * Constructs a new RenderingError object with the given error code + * and message. All other fields are initialized to null. + * + * @param errorCode the error code for this rendering error. + * @param errorMessage a short error message describing this + * rendering error. + */ + public RenderingError(int errorCode, String errorMessage) { + this.errorCode = errorCode; + this.errorMessage = errorMessage; + } + + /** + * Prints a verbose error report to System.err. This verbose + * output includes the error code, error message, detail message, + * and all relevant Java 3D objects. + */ + public void printVerbose() { + printVerbose(System.err); + } + + /** + * Prints a verbose error report to the specified PrintStream. + * This verbose output includes the error code, error message, + * detail message, and all relevant Java 3D objects. + * + * @param printStream the print stream on which to print the error + * report. + */ + public void printVerbose(PrintStream printStream) { + printStream.println(this); + if (graphicsDevice != null) { + printStream.println("graphicsDevice = " + graphicsDevice); + } + if (canvas != null) { + printStream.println("canvas = " + canvas); + } + + if (detailMessage != null) { + printStream.println(); + printStream.println("Detail Message"); + printStream.println("--------------"); + printStream.println(detailMessage); + } + } + + /** + * Sets the error code for this rendering error. This represents the + * type of error that occurred. + * + * @param errorCode the error code for this rendering error. + */ + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + /** + * Returns the error code for this rendering error. + * + * @return the error code. + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Sets the error message for this rendering error. This is a short + * message describing the error, and is included as part of + * toString(). + * + * @param errorMessage a short error message describing this + * rendering error. + */ + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + /** + * Returns the error message for this rendering error. + * + * @return a short error message describing this rendering error. + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Sets the detail message for this rendering error. This is a more + * detailed error message that is not included as part of toString(). + * + * @param detailMessage a detailed message describing this + * error in more detail. + */ + public void setDetailMessage(String detailMessage) { + this.detailMessage = detailMessage; + } + + /** + * Returns the detail message for this rendering error. + * + * @return the detail message for this rendering error. + */ + public String getDetailMessage() { + return detailMessage; + } + + /** + * Sets the graphics device associated with this rendering error. + * + * @param graphicsDevice the graphics device associated with this rendering error. + */ + public void setGraphicsDevice(GraphicsDevice graphicsDevice) { + this.graphicsDevice = graphicsDevice; + } + + /** + * Returns the graphics device associated with this rendering error. + * + * @return the graphics device associated with this rendering error. + */ + public GraphicsDevice getGraphicsDevice() { + return this.graphicsDevice; + } + + /** + * Sets the canvas associated with this rendering error. + * + * @param canvas the canvas associated with this rendering error. + */ + public void setCanvas3D(Canvas3D canvas) { + this.canvas = canvas; + } + + /** + * Returns the canvas associated with this rendering error. + * + * @return the canvas associated with this rendering error. + */ + public Canvas3D getCanvas3D() { + return this.canvas; + } + + + /** + * Returns a short string that describes this rendering error. The + * string is composed of the textual description of the errorCode, + * a ": ", and the errorMessage field. If the errorMessage is + * null then the ": " and the errorMessage are omitted. + * + * @return a string representation of this rendering error. + */ + public String toString() { + // Concatenate string representation of error code with error message + String errorCodeStr; + switch (errorCode) { + case NO_ERROR: + errorCodeStr = "NO_ERROR"; + break; + case UNEXPECTED_RENDERING_ERROR: + errorCodeStr = "UNEXPECTED_RENDERING_ERROR"; + break; + case GRAPHICS_CONFIG_ERROR: + errorCodeStr = "GRAPHICS_CONFIG_ERROR"; + break; + case CONTEXT_CREATION_ERROR: + errorCodeStr = "CONTEXT_CREATION_ERROR"; + break; + case OFF_SCREEN_BUFFER_ERROR: + errorCodeStr = "OFF_SCREEN_BUFFER_ERROR"; + break; + + default: + errorCodeStr = "UNKNOWN ERROR CODE (" + errorCode + ")"; + } + + if (errorMessage == null) { + return errorCodeStr; + } + + return errorCodeStr + ": " + errorMessage; + } +} diff --git a/src/classes/share/javax/media/j3d/RenderingErrorListener.java b/src/classes/share/javax/media/j3d/RenderingErrorListener.java new file mode 100644 index 0000000..b621775 --- /dev/null +++ b/src/classes/share/javax/media/j3d/RenderingErrorListener.java @@ -0,0 +1,29 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Listener interface for monitoring Java 3D rendering errors. + * + * @see VirtualUniverse#addRenderingErrorListener + * + * @since Java 3D 1.5 + */ +public interface RenderingErrorListener { + /** + * Invoked when an error occurs in the Java 3D rendering system. + * + * @param error object that contains the details of the error. + */ + public void errorOccurred(RenderingError error); +} diff --git a/src/classes/share/javax/media/j3d/Screen3D.java b/src/classes/share/javax/media/j3d/Screen3D.java index 6633b99..017947b 100644 --- a/src/classes/share/javax/media/j3d/Screen3D.java +++ b/src/classes/share/javax/media/j3d/Screen3D.java @@ -97,8 +97,10 @@ public class Screen3D extends Object { // an off-screen Canvas3D or with one or more on-screen Canvas3Ds boolean offScreen; - // The display connection (X11 only) and the screen ID + // The display connection (native OGL pipeline on X11 only) long display; + + // Screen number int screen; // The width and height of the screen in meters. @@ -353,18 +355,14 @@ public class Screen3D extends Object { * associated with an off-screen Canvas3D */ Screen3D(GraphicsConfiguration graphicsConfiguration, boolean offScreen) { - NativeScreenInfo nativeScreenInfo; - this.offScreen = offScreen; this.graphicsDevice = graphicsConfiguration.getDevice(); screenViewCache = new ScreenViewCache(this); - nativeScreenInfo = new NativeScreenInfo(graphicsDevice); - // Get the display from the native code (X11 only) and the - // screen ID - display = nativeScreenInfo.getDisplay(); - screen = nativeScreenInfo.getScreen(); + // Get the display handle and the screen number from the Pipeline + display = Pipeline.getPipeline().getDisplay(); + screen = Pipeline.getPipeline().getScreen(graphicsDevice); if (debug) System.out.println("Screen3D: display " + display + diff --git a/src/classes/share/javax/media/j3d/SetLiveState.java b/src/classes/share/javax/media/j3d/SetLiveState.java index bffd18f..d7b0000 100644 --- a/src/classes/share/javax/media/j3d/SetLiveState.java +++ b/src/classes/share/javax/media/j3d/SetLiveState.java @@ -248,5 +248,10 @@ class SetLiveState extends Object { //transformTargetThreads = 0; hashkeyIndex = null; + + // Fix for issue 75 + parentBranchGroupPaths = null; + branchGroupPaths = null; + orderedPaths = null; } } diff --git a/src/classes/share/javax/media/j3d/ShaderAppearanceRetained.java b/src/classes/share/javax/media/j3d/ShaderAppearanceRetained.java index 9815827..b5dc6f9 100644 --- a/src/classes/share/javax/media/j3d/ShaderAppearanceRetained.java +++ b/src/classes/share/javax/media/j3d/ShaderAppearanceRetained.java @@ -281,7 +281,7 @@ class ShaderAppearanceRetained extends AppearanceRetained { ArrayList gaList = Shape3DRetained.getGeomAtomsList(mirror.users, univList); // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.SHADER_APPEARANCE_CHANGED; createMessage.universe = null; @@ -294,7 +294,7 @@ class ShaderAppearanceRetained extends AppearanceRetained { //System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.SHADER_APPEARANCE_CHANGED; @@ -328,8 +328,20 @@ class ShaderAppearanceRetained extends AppearanceRetained { return flag; } + // Issue 209 - implement the compile method + // Simply pass along to the NodeComponents + void compile(CompileState compState) { + super.compile(compState); + + if (shaderProgram != null) { + shaderProgram.compile(compState); + } + + if (shaderAttributeSet != null) { + shaderAttributeSet.compile(compState); + } + } - boolean isOpaque(int geoType) { if (!super.isOpaque(geoType)) { diff --git a/src/classes/share/javax/media/j3d/ShaderAttrLoc.java b/src/classes/share/javax/media/j3d/ShaderAttrLoc.java new file mode 100644 index 0000000..f7c5a88 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttrLoc.java @@ -0,0 +1,22 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Tagging interface for shader attribute location objects. The rendering + * pipelines will define concrete classes that implement this interface. All + * code that uses the tagged objects will be in the pipelines. + */ +interface ShaderAttrLoc { + // No methods or constants defined at this time +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeObjectRetained.java b/src/classes/share/javax/media/j3d/ShaderAttributeObjectRetained.java index 7d5ede7..efd4bc3 100644 --- a/src/classes/share/javax/media/j3d/ShaderAttributeObjectRetained.java +++ b/src/classes/share/javax/media/j3d/ShaderAttributeObjectRetained.java @@ -125,7 +125,7 @@ abstract class ShaderAttributeObjectRetained extends ShaderAttributeRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.SHADER_ATTRIBUTE_CHANGED; createMessage.universe = null; @@ -138,7 +138,7 @@ abstract class ShaderAttributeObjectRetained extends ShaderAttributeRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.SHADER_ATTRIBUTE_CHANGED; @@ -283,4 +283,24 @@ abstract class ShaderAttributeObjectRetained extends ShaderAttributeRetained { this.classType = classType; } + + // Issue 320 : Override base class method so we can force changedFrequent + // to be set whenever the capability is writable, regardless of whether + // it is frequently writable. We must do this because the ShaderBin doesn't + // support updating shader attributes when changedFrequent is 0. + void setFrequencyChangeMask(int bit, int mask) { + if (source.getCapability(bit)) { + changedFrequent |= mask; + } else if (!source.isLive()) { + // Record the freq->infreq change only for non-live node components + changedFrequent &= ~mask; + } + } + + void handleFrequencyChange(int bit) { + if (bit == ShaderAttributeObject.ALLOW_VALUE_WRITE) { + setFrequencyChangeMask(bit, 0x1); + } + } + } diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeSetRetained.java b/src/classes/share/javax/media/j3d/ShaderAttributeSetRetained.java index 88952d9..ce03357 100644 --- a/src/classes/share/javax/media/j3d/ShaderAttributeSetRetained.java +++ b/src/classes/share/javax/media/j3d/ShaderAttributeSetRetained.java @@ -319,7 +319,7 @@ class ShaderAttributeSetRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED; createMessage.universe = null; @@ -332,7 +332,7 @@ class ShaderAttributeSetRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED; @@ -351,4 +351,24 @@ class ShaderAttributeSetRetained extends NodeComponentRetained { } + + // Issue 320 : Override base class method so we can force changedFrequent + // to be set whenever the capability is writable, regardless of whether + // it is frequently writable. We must do this because the ShaderBin doesn't + // support updating shader attributes when changedFrequent is 0. + void setFrequencyChangeMask(int bit, int mask) { + if (source.getCapability(bit)) { + changedFrequent |= mask; + } else if (!source.isLive()) { + // Record the freq->infreq change only for non-live node components + changedFrequent &= ~mask; + } + } + + void handleFrequencyChange(int bit) { + if (bit == ShaderAttributeSet.ALLOW_ATTRIBUTES_WRITE) { + setFrequencyChangeMask(bit, 0x1); + } + } + } diff --git a/src/classes/share/javax/media/j3d/ShaderBin.java b/src/classes/share/javax/media/j3d/ShaderBin.java index 83ca00f..056b9f4 100644 --- a/src/classes/share/javax/media/j3d/ShaderBin.java +++ b/src/classes/share/javax/media/j3d/ShaderBin.java @@ -270,8 +270,6 @@ class ShaderBin implements ObjectUpdate { t.clear(); - renderBin.textureBinFreelist.add(t); - if (textureBinList == null && addTextureBins.size() == 0 ) { // Note: Removal of this shaderBin as a user of the rendering // atttrs is done during removeRenderAtom() in RenderMolecule.java diff --git a/src/classes/share/javax/media/j3d/ShaderId.java b/src/classes/share/javax/media/j3d/ShaderId.java new file mode 100644 index 0000000..f5ca3c7 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderId.java @@ -0,0 +1,22 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Tagging interface for shader objects. The rendering pipelines + * will define concrete classes that implement this interface. All code that + * uses the tagged objects will be in the pipelines. + */ +interface ShaderId { + // No methods or constants defined at this time +} diff --git a/src/classes/share/javax/media/j3d/ShaderProgramId.java b/src/classes/share/javax/media/j3d/ShaderProgramId.java new file mode 100644 index 0000000..b3dd88c --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderProgramId.java @@ -0,0 +1,22 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Tagging interface for shader program objects. The rendering pipelines + * will define concrete classes that implement this interface. All code that + * uses the tagged objects will be in the pipelines. + */ +interface ShaderProgramId { + // No methods or constants defined at this time +} diff --git a/src/classes/share/javax/media/j3d/ShaderProgramRetained.java b/src/classes/share/javax/media/j3d/ShaderProgramRetained.java index 6d926bf..9524d4b 100644 --- a/src/classes/share/javax/media/j3d/ShaderProgramRetained.java +++ b/src/classes/share/javax/media/j3d/ShaderProgramRetained.java @@ -195,176 +195,176 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { } return shads; } - } - + } + /** * Method to create the native shader. */ - abstract ShaderError createShader(long ctx, ShaderRetained shader, long[] shaderIdArr); + abstract ShaderError createShader(Context ctx, ShaderRetained shader, ShaderId[] shaderIdArr); /** * Method to destroy the native shader. */ - abstract ShaderError destroyShader(long ctx, long shaderId); + abstract ShaderError destroyShader(Context ctx, ShaderId shaderId); /** * Method to compile the native shader. */ - abstract ShaderError compileShader(long ctx, long shaderId, String source); + abstract ShaderError compileShader(Context ctx, ShaderId shaderId, String source); /** * Method to create the native shader program. */ - abstract ShaderError createShaderProgram(long ctx, long[] shaderProgramIdArr); + abstract ShaderError createShaderProgram(Context ctx, ShaderProgramId[] shaderProgramIdArr); /** * Method to destroy the native shader program. */ - abstract ShaderError destroyShaderProgram(long ctx, long shaderProgramId); + abstract ShaderError destroyShaderProgram(Context ctx, ShaderProgramId shaderProgramId); /** * Method to link the native shader program. */ - abstract ShaderError linkShaderProgram(long ctx, long shaderProgramId, long[] shaderIds); + abstract ShaderError linkShaderProgram(Context ctx, ShaderProgramId shaderProgramId, ShaderId[] shaderIds); /** * Method to bind a vertex attribute name to the specified index. */ - abstract ShaderError bindVertexAttrName(long ctx, long shaderProgramId, String attrName, int attrIndex); + abstract ShaderError bindVertexAttrName(Context ctx, ShaderProgramId shaderProgramId, String attrName, int attrIndex); /** * Method to lookup a list of (uniform) shader attribute names and return * information about the attributes. */ - abstract void lookupShaderAttrNames(long ctx, long shaderProgramId, String[] attrNames, AttrNameInfo[] attrNameInfoArr); + abstract void lookupShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, String[] attrNames, AttrNameInfo[] attrNameInfoArr); /* * Method to lookup a list of vertex attribute names. */ - abstract void lookupVertexAttrNames(long ctx, long shaderProgramId, String[] attrNames, boolean[] errArr); + abstract void lookupVertexAttrNames(Context ctx, ShaderProgramId shaderProgramId, String[] attrNames, boolean[] errArr); /** * Method to use the native shader program. */ - abstract ShaderError enableShaderProgram(long ctx, long shaderProgramId); + abstract ShaderError enableShaderProgram(Context ctx, ShaderProgramId shaderProgramId); /** * Method to disable the native shader program. */ - abstract ShaderError disableShaderProgram(long ctx); + abstract ShaderError disableShaderProgram(Context ctx); // ShaderAttributeValue methods - abstract ShaderError setUniform1i(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform1i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int value); - abstract ShaderError setUniform1f(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform1f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, float value); - abstract ShaderError setUniform2i(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform2i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int[] value); - abstract ShaderError setUniform2f(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform2f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, float[] value); - abstract ShaderError setUniform3i(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform3i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int[] value); - abstract ShaderError setUniform3f(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, float[] value); - abstract ShaderError setUniform4i(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform4i(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int[] value); - abstract ShaderError setUniform4f(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, float[] value); - abstract ShaderError setUniformMatrix3f(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniformMatrix3f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, float[] value); - abstract ShaderError setUniformMatrix4f(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniformMatrix4f(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, float[] value); // ShaderAttributeArray methods - abstract ShaderError setUniform1iArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform1iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, int[] value); - abstract ShaderError setUniform1fArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform1fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, float[] value); - abstract ShaderError setUniform2iArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform2iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, int[] value); - abstract ShaderError setUniform2fArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform2fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, float[] value); - abstract ShaderError setUniform3iArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform3iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, int[] value); - abstract ShaderError setUniform3fArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, float[] value); - abstract ShaderError setUniform4iArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform4iArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, int[] value); - abstract ShaderError setUniform4fArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniform4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, float[] value); - abstract ShaderError setUniformMatrix3fArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniformMatrix3fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, float[] value); - abstract ShaderError setUniformMatrix4fArray(long ctx, - long shaderProgramId, - long uniformLocation, + abstract ShaderError setUniformMatrix4fArray(Context ctx, + ShaderProgramId shaderProgramId, + ShaderAttrLoc uniformLocation, int numElements, float[] value); @@ -505,9 +505,9 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { private ShaderError createShaderProgram(Canvas3D cv, int cvRdrIndex) { // Create shaderProgram resources if it has not been done. synchronized(resourceLock) { - assert(shaderProgramData[cvRdrIndex].getShaderProgramId() == 0); + assert shaderProgramData[cvRdrIndex].getShaderProgramId() == null; - long[] spIdArr = new long[1]; + ShaderProgramId[] spIdArr = new ShaderProgramId[1]; ShaderError err = createShaderProgram(cv.ctx, spIdArr); if(err != null) { return err; @@ -524,7 +524,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { private ShaderError linkShaderProgram(Canvas3D cv, int cvRdrIndex, ShaderRetained[] shaders) { synchronized(resourceLock) { - long[] shaderIds = new long[shaders.length]; + ShaderId[] shaderIds = new ShaderId[shaders.length]; for(int i=0; i<shaders.length; i++) { synchronized(shaders[i]) { shaderIds[i] = shaders[i].shaderIds[cvRdrIndex]; @@ -547,7 +547,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { private ShaderError bindVertexAttrName(Canvas3D cv, int cvRdrIndex, String attrName, int attrIndex) { assert(attrName != null); synchronized(resourceLock) { - long shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); + ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); // System.err.println("attrName = " + attrName); ShaderError err = bindVertexAttrName(cv.ctx, shaderProgramId, attrName, attrIndex); if (err != null) { @@ -559,7 +559,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { private void lookupVertexAttrNames(Canvas3D cv, int cvRdrIndex, String[] attrNames) { synchronized(resourceLock) { - long shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); + ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); boolean[] errArr = new boolean[attrNames.length]; lookupVertexAttrNames(cv.ctx, shaderProgramId, attrNames, errArr); @@ -580,7 +580,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { private void lookupShaderAttrNames(Canvas3D cv, int cvRdrIndex, String[] attrNames) { synchronized(resourceLock) { - long shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); + ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); AttrNameInfo[] attrNameInfoArr = new AttrNameInfo[attrNames.length]; lookupShaderAttrNames(cv.ctx, shaderProgramId, attrNames, attrNameInfoArr); @@ -588,8 +588,8 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { for (int i = 0; i < attrNames.length; i++) { shaderProgramData[cvRdrIndex].setAttrNameInfo(attrNames[i], attrNameInfoArr[i]); - // Report non-fatal error if location is invalid (-1) - if (attrNameInfoArr[i].getLocation() == -1) { + // Report non-fatal error if location is invalid + if (attrNameInfoArr[i].getLocation() == null) { String errMsg = "Attribute name lookup failed: " + attrNames[i]; ShaderError err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_LOOKUP_ERROR, errMsg); err.setShaderProgram((ShaderProgram)this.source); @@ -619,11 +619,11 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { synchronized(shader.resourceLock) { if(shader.shaderIds == null){ // We rely on Java to initial the array elements to 0 or false; - shader.shaderIds = new long[cvRdrIndex+1]; + shader.shaderIds = new ShaderId[cvRdrIndex+1]; shader.compiled = new boolean[cvRdrIndex+1]; } else if( shader.shaderIds.length <= cvRdrIndex) { // We rely on Java to initial the array elements to 0 or false; - long[] tempSIds = new long[cvRdrIndex+1]; + ShaderId[] tempSIds = new ShaderId[cvRdrIndex+1]; boolean[] tempCompiled = new boolean[cvRdrIndex+1]; System.arraycopy(shader.shaderIds, 0, @@ -637,12 +637,12 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { shader.compiled = tempCompiled; } - if(shader.shaderIds[cvRdrIndex] != 0) { + if(shader.shaderIds[cvRdrIndex] != null) { // We have already created the shaderId for this Canvas. return null; } - long[] shaderIdArr = new long[1]; + ShaderId[] shaderIdArr = new ShaderId[1]; ShaderError err = createShader(cv.ctx, shader, shaderIdArr); if(err != null) { return err; @@ -722,15 +722,15 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { return; } - // Nothing to do if the shaderId is 0 - if (shader.shaderIds[cvRdrIndex] == 0) { + // Nothing to do if the shaderId is null + if (shader.shaderIds[cvRdrIndex] == null) { return; } - // Destroy the native resource and set the ID to 0 for this canvas/renderer + // Destroy the native resource and set the ID to null for this canvas/renderer // Ignore any possible shader error, because there is no meaningful way to report it destroyShader(cv.ctx, shader.shaderIds[cvRdrIndex]); - shader.shaderIds[cvRdrIndex] = 0; + shader.shaderIds[cvRdrIndex] = null; } } @@ -756,13 +756,13 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { // return; // } - long shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); - // Nothing to do if the shaderProgramId is 0 - if (shaderProgramId == 0) { + ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); + // Nothing to do if the shaderProgramId is null + if (shaderProgramId == null) { return; } - // Destroy the native resource, set the ID to 0 for this canvas/renderer, + // Destroy the native resource, set the ID to null for this canvas/renderer, // and clear the bit in the resourceCreationMask // Ignore any possible shader error, because there is no meaningful way to report it destroyShaderProgram(cv.ctx, shaderProgramId); @@ -779,7 +779,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { void updateNative(Canvas3D cv, boolean enable) { // System.out.println("ShaderProgramRetained.updateNative : "); - final boolean useSharedCtx = cv.useSharedCtx && cv.screen.renderer.sharedCtx != 0; + final boolean useSharedCtx = cv.useSharedCtx && cv.screen.renderer.sharedCtx != null; final int cvRdrIndex = useSharedCtx ? cv.screen.renderer.rendererId : cv.canvasId; // Create ShaderProgramData object for this canvas/renderer if it doesn't already exist @@ -806,7 +806,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { } boolean loadShaderProgram = false; // flag indicating whether to reload all shaderProgram states - if (getShaderProgramData(cvRdrIndex).getShaderProgramId() == 0) { + if (getShaderProgramData(cvRdrIndex).getShaderProgramId() == null) { loadShaderProgram = true; } @@ -927,8 +927,8 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { /** * Update native value for ShaderAttributeValue class */ - ShaderError setUniformAttrValue(long ctx, long shaderProgramId, long loc, - ShaderAttributeValueRetained sav) { + ShaderError setUniformAttrValue(Context ctx, ShaderProgramId shaderProgramId, + ShaderAttrLoc loc, ShaderAttributeValueRetained sav) { switch (sav.getClassType()) { case ShaderAttributeObjectRetained.TYPE_INTEGER: @@ -981,8 +981,8 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { /** * Update native value for ShaderAttributeArray class */ - ShaderError setUniformAttrArray(long ctx, long shaderProgramId, long loc, - ShaderAttributeArrayRetained saa) { + ShaderError setUniformAttrArray(Context ctx, ShaderProgramId shaderProgramId, + ShaderAttrLoc loc, ShaderAttributeArrayRetained saa) { switch (saa.getClassType()) { case ShaderAttributeObjectRetained.TYPE_INTEGER: @@ -1035,7 +1035,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { void setShaderAttributes(Canvas3D cv, ShaderAttributeSetRetained attributeSet) { - final boolean useSharedCtx = cv.useSharedCtx && cv.screen.renderer.sharedCtx != 0; + final boolean useSharedCtx = cv.useSharedCtx && cv.screen.renderer.sharedCtx != null; final int cvRdrIndex = useSharedCtx ? cv.screen.renderer.rendererId : cv.canvasId; ShaderProgramData spData = getShaderProgramData(cvRdrIndex); @@ -1044,7 +1044,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { return; } - long shaderProgramId = spData.getShaderProgramId(); + ShaderProgramId shaderProgramId = spData.getShaderProgramId(); Iterator attrs = attributeSet.getAttrs().values().iterator(); while (attrs.hasNext()) { @@ -1060,8 +1060,8 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { String errMsg = "Attribute name not set in ShaderProgram: " + saRetained.getAttributeName(); // TODO: I18N err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_NAME_NOT_SET_ERROR, errMsg); } else { - long loc = attrNameInfo.getLocation(); - if (loc != -1) { + ShaderAttrLoc loc = attrNameInfo.getLocation(); + if (loc != null) { if (saRetained instanceof ShaderAttributeValueRetained) { ShaderAttributeValueRetained savRetained = (ShaderAttributeValueRetained)saRetained; if (attrNameInfo.isArray() || @@ -1111,7 +1111,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { class ShaderProgramData extends Object { // shaderProgramId use by native code. - private long shaderProgramId = 0; + private ShaderProgramId shaderProgramId = null; // linked flag for native. private boolean linked = false; @@ -1124,16 +1124,16 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { } void reset() { - shaderProgramId = 0; + shaderProgramId = null; linked = false; attrNameInfoMap.clear(); } - void setShaderProgramId(long shaderProgramId) { + void setShaderProgramId(ShaderProgramId shaderProgramId) { this.shaderProgramId = shaderProgramId; } - long getShaderProgramId() { + ShaderProgramId getShaderProgramId() { return this.shaderProgramId; } @@ -1159,11 +1159,11 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { // Data associated with an attribute name class AttrNameInfo { - void setLocation(long loc) { + void setLocation(ShaderAttrLoc loc) { this.loc = loc; } - long getLocation() { + ShaderAttrLoc getLocation() { return loc; } @@ -1184,7 +1184,7 @@ abstract class ShaderProgramRetained extends NodeComponentRetained { } // Location of attribute name in linked shader program - private long loc; + private ShaderAttrLoc loc; // boolean indicating whether the attribute is an array private boolean isArray; diff --git a/src/classes/share/javax/media/j3d/ShaderRetained.java b/src/classes/share/javax/media/j3d/ShaderRetained.java index 9965dba..213456f 100644 --- a/src/classes/share/javax/media/j3d/ShaderRetained.java +++ b/src/classes/share/javax/media/j3d/ShaderRetained.java @@ -26,7 +26,7 @@ abstract class ShaderRetained extends NodeComponentRetained { int shaderType; // shaderId use by native code. One per Canvas. - long[] shaderIds; + ShaderId[] shaderIds; boolean[] compiled; // Flag indicating whether a COMPILE_ERROR has occurred for this shader diff --git a/src/classes/share/javax/media/j3d/Shape3DRetained.java b/src/classes/share/javax/media/j3d/Shape3DRetained.java index 61e56b3..d051281 100644 --- a/src/classes/share/javax/media/j3d/Shape3DRetained.java +++ b/src/classes/share/javax/media/j3d/Shape3DRetained.java @@ -191,7 +191,7 @@ class Shape3DRetained extends LeafRetained { if (source.isLive()) { // Notify Geometry Structure to check for collision - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.COLLISION_BOUND_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM; message.universe = universe; @@ -221,7 +221,7 @@ class Shape3DRetained extends LeafRetained { super.setBounds(bounds); if (source.isLive() && !boundsAutoCompute) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.REGION_BOUND_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY | @@ -531,7 +531,7 @@ class Shape3DRetained extends LeafRetained { size = 1; J3dMessage[] createMessage = new J3dMessage[size]; // Send a message - createMessage[0] = VirtualUniverse.mc.getMessage(); + createMessage[0] = new J3dMessage(); createMessage[0].threads = targetThreads; createMessage[0].type = J3dMessage.SHAPE3D_CHANGED; createMessage[0].universe = universe; @@ -551,7 +551,7 @@ class Shape3DRetained extends LeafRetained { createMessage[0].args[3] = obj; createMessage[0].args[4] = getGeomAtomsArray(mirrorShape3D); if(visibleIsDirty) { - createMessage[1] = VirtualUniverse.mc.getMessage(); + createMessage[1] = new J3dMessage(); createMessage[1].threads = J3dThread.UPDATE_GEOMETRY; createMessage[1].type = J3dMessage.SHAPE3D_CHANGED; createMessage[1].universe = universe; @@ -584,7 +584,7 @@ class Shape3DRetained extends LeafRetained { if (((Shape3D)this.source).isLive()) { // Send a message - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.SHAPE3D_CHANGED; createMessage.universe = universe; @@ -1922,7 +1922,7 @@ class Shape3DRetained extends LeafRetained { } - J3dMessage changeMessage = VirtualUniverse.mc.getMessage(); + J3dMessage changeMessage = new J3dMessage(); changeMessage.type = J3dMessage.SHAPE3D_CHANGED; // Who to send this message to ? changeMessage.threads = J3dThread.UPDATE_RENDER | @@ -2002,7 +2002,7 @@ class Shape3DRetained extends LeafRetained { } super.setBoundsAutoCompute(autoCompute); if (source.isLive()) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY | @@ -2023,7 +2023,7 @@ class Shape3DRetained extends LeafRetained { getCombineBounds((BoundingBox)localBounds); synchronized(mirrorShape3D) { if (source.isLive()) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED; message.threads = J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY | @@ -2252,7 +2252,7 @@ class Shape3DRetained extends LeafRetained { // send a Shape GEOMETRY_CHANGED message for all geometry atoms - J3dMessage changeMessage = VirtualUniverse.mc.getMessage(); + J3dMessage changeMessage = new J3dMessage(); changeMessage.type = J3dMessage.SHAPE3D_CHANGED; changeMessage.threads = J3dThread.UPDATE_RENDER | J3dThread.UPDATE_TRANSFORM | @@ -2714,14 +2714,6 @@ class Shape3DRetained extends LeafRetained { } - static Point3d getPoint3d() { - return (Point3d)FreeListManager.getObject(FreeListManager.POINT3D); - } - - static void freePoint3d(Point3d p) { - FreeListManager.freeObject(FreeListManager.POINT3D, p); - } - void handleFrequencyChange(int bit) { int mask = 0; if (bit == Shape3D.ALLOW_GEOMETRY_WRITE) { diff --git a/src/classes/share/javax/media/j3d/SoundRetained.java b/src/classes/share/javax/media/j3d/SoundRetained.java index d0898ff..38a8515 100644 --- a/src/classes/share/javax/media/j3d/SoundRetained.java +++ b/src/classes/share/javax/media/j3d/SoundRetained.java @@ -215,7 +215,7 @@ abstract class SoundRetained extends LeafRetained */ void dispatchAttribChange(int dirtyBit, Object argument) { // Send message including a integer argument - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_SOUND | J3dThread.SOUND_SCHEDULER; createMessage.type = J3dMessage.SOUND_ATTRIB_CHANGED; @@ -238,7 +238,7 @@ abstract class SoundRetained extends LeafRetained */ void dispatchStateChange(int dirtyBit, Object argument) { // Send message including a integer argument - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_SOUND | J3dThread.SOUND_SCHEDULER; createMessage.type = J3dMessage.SOUND_STATE_CHANGED; diff --git a/src/classes/share/javax/media/j3d/SoundScheduler.java b/src/classes/share/javax/media/j3d/SoundScheduler.java index b9ef720..59bc12a 100644 --- a/src/classes/share/javax/media/j3d/SoundScheduler.java +++ b/src/classes/share/javax/media/j3d/SoundScheduler.java @@ -270,6 +270,12 @@ class SoundScheduler extends J3dStructure { "during Sound rendering:"); e.printStackTrace(); } + catch (Error e) { + // Issue 264 - catch Error + System.err.println("Error occurred " + + "during Sound rendering:"); + e.printStackTrace(); + } // what if the user/app makes no change to scenegraph? // must still re-render after retest for sound complete @@ -789,6 +795,12 @@ class SoundScheduler extends J3dStructure { "during sound deactivation:"); e.printStackTrace(); } + catch (Error e) { + // Issue 264 - catch Error + System.err.println("Error occurred " + + "during sound deactivation:"); + e.printStackTrace(); + } updateThread.active = false; } } diff --git a/src/classes/share/javax/media/j3d/SoundscapeRetained.java b/src/classes/share/javax/media/j3d/SoundscapeRetained.java index 72ba4b5..53d8471 100644 --- a/src/classes/share/javax/media/j3d/SoundscapeRetained.java +++ b/src/classes/share/javax/media/j3d/SoundscapeRetained.java @@ -56,7 +56,7 @@ class SoundscapeRetained extends LeafRetained void dispatchMessage(int dirtyBit, Object argument) { // Send message including a integer argument - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.type = J3dMessage.SOUNDSCAPE_CHANGED; createMessage.universe = universe; diff --git a/src/classes/share/javax/media/j3d/SpotLightRetained.java b/src/classes/share/javax/media/j3d/SpotLightRetained.java index 6609fc0..20f41e3 100644 --- a/src/classes/share/javax/media/j3d/SpotLightRetained.java +++ b/src/classes/share/javax/media/j3d/SpotLightRetained.java @@ -183,22 +183,16 @@ class SpotLightRetained extends PointLightRetained { * transformed position, spread angle, concentration, * and its transformed position. */ - native void updateLight(long ctx, - int lightSlot, float red, float green, - float blue, float ax, float ay, float az, - float px, float py, float pz, float spreadAngle, - float concentration, float dx, float dy, - float dz); - - void update(long ctx, int lightSlot, double scale) { + void update(Context ctx, int lightSlot, double scale) { validateAttenuationInEc(scale); - updateLight(ctx, lightSlot, color.x, color.y, color.z, - attenuation.x, linearAttenuationInEc, - quadraticAttenuationInEc, - xformPosition.x, xformPosition.y, - xformPosition.z, spreadAngle, concentration, - xformDirection.x, xformDirection.y, - xformDirection.z); + Pipeline.getPipeline().updateSpotLight(ctx, + lightSlot, color.x, color.y, color.z, + attenuation.x, linearAttenuationInEc, + quadraticAttenuationInEc, + xformPosition.x, xformPosition.y, + xformPosition.z, spreadAngle, concentration, + xformDirection.x, xformDirection.y, + xformDirection.z); } @@ -264,40 +258,6 @@ class SpotLightRetained extends PointLightRetained { } - /* - // This update function, and its native counterpart, - // updates a spot light. This includes its color, attenuation, - // transformed position, spread angle, concentration, - // and its transformed position. - native void updateLight(int lightSlot, float red, float green, - float blue, float ax, float ay, float az, - float px, float py, float pz, float spreadAngle, - float concentration, float dx, float dy, - float dz); - void update(int lightSlot, double scale) { - updateLight(lightSlot, color.x, color.y, color.z, - attenuation.x, linearAttenuationInEc, - quadraticAttenuationInEc, - xformPosition.x, xformPosition.y, - xformPosition.z, spreadAngle, concentration, - xformDirection.x, xformDirection.y, - xformDirection.z); - } - - synchronized void update(LightRetained l, boolean clear) { - SpotLightRetained sl = (SpotLightRetained)l; - super.update(sl, clear); - - l.sgLight.getLocalToVworld(trans, l.key); - trans.transform(direction, sl.xformDirection); - sl.xformDirection.normalize(); - trans.transform(position, sl.xformPosition); - sl.spreadAngle = spreadAngle; - sl.concentration = concentration; - } - */ - - // Clones only the retained side, internal use only protected Object clone() { SpotLightRetained sr = (SpotLightRetained)super.clone(); @@ -318,7 +278,7 @@ class SpotLightRetained extends PointLightRetained { } final void sendMessage(int attrMask, Object attr) { - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = targetThreads; createMessage.universe = universe; createMessage.type = J3dMessage.LIGHT_CHANGED; diff --git a/src/classes/share/javax/media/j3d/SwitchRetained.java b/src/classes/share/javax/media/j3d/SwitchRetained.java index 21b0640..cc3ad37 100644 --- a/src/classes/share/javax/media/j3d/SwitchRetained.java +++ b/src/classes/share/javax/media/j3d/SwitchRetained.java @@ -194,7 +194,7 @@ class SwitchRetained extends GroupRetained implements TargetsInterface if (threads > 0) { - m = VirtualUniverse.mc.getMessage(); + m = new J3dMessage(); m.type = J3dMessage.SWITCH_CHANGED; m.universe = universe; m.threads = threads; diff --git a/src/classes/share/javax/media/j3d/TexCoordGenerationRetained.java b/src/classes/share/javax/media/j3d/TexCoordGenerationRetained.java index 408c30f..3a5089d 100644 --- a/src/classes/share/javax/media/j3d/TexCoordGenerationRetained.java +++ b/src/classes/share/javax/media/j3d/TexCoordGenerationRetained.java @@ -255,20 +255,6 @@ class TexCoordGenerationRetained extends NodeComponentRetained { } } - /** - * These two methods update the native context, - * trans contains eyeTovworld transform in d3d - * trans contains vworldToEye transform in ogl - */ - native void updateNative(long ctx, - boolean enable, int genMode, int format, - float planeSx, float planeSy, float planeSz, float planeSw, - float planeTx, float planeTy, float planeTz, float planeTw, - float planeRx, float planeRy, float planeRz, float planeRw, - float planeQx, float planeQy, float planeQz, float planeQw, - double[] trans); - - void updateNative(Canvas3D cv) { int gMode = genMode; Transform3D trans = null; @@ -282,22 +268,17 @@ class TexCoordGenerationRetained extends NodeComponentRetained { if (VirtualUniverse.mc.isD3D() && (gMode == TexCoordGeneration.EYE_LINEAR)) { - trans = VirtualUniverse.mc.getTransform3D(cv.vworldToEc); + trans = new Transform3D(cv.vworldToEc); trans.invert(); m = trans; } - updateNative(cv.ctx, + Pipeline.getPipeline().updateTexCoordGeneration(cv.ctx, enable, gMode, format, planeS.x, planeS.y, planeS.z, planeS.w, planeT.x, planeT.y, planeT.z, planeT.w, planeR.x, planeR.y, planeR.z, planeR.w, planeQ.x, planeQ.y, planeQ.z, planeQ.w, m.mat); - - if (trans != null) { - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - trans); - } } /** @@ -379,7 +360,7 @@ class TexCoordGenerationRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.TEXCOORDGENERATION_CHANGED; createMessage.universe = null; @@ -392,7 +373,7 @@ class TexCoordGenerationRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.TEXCOORDGENERATION_CHANGED; diff --git a/src/classes/share/javax/media/j3d/Text3DRenderMethod.java b/src/classes/share/javax/media/j3d/Text3DRenderMethod.java index 2416f32..c4d304d 100644 --- a/src/classes/share/javax/media/j3d/Text3DRenderMethod.java +++ b/src/classes/share/javax/media/j3d/Text3DRenderMethod.java @@ -22,8 +22,9 @@ class Text3DRenderMethod implements RenderMethod { /** * The actual rendering code for this RenderMethod */ - public boolean render(RenderMolecule rm, Canvas3D cv, int pass, + public boolean render(RenderMolecule rm, Canvas3D cv, RenderAtomListInfo ra, int dirtyBits) { + boolean isNonUniformScale; Transform3D trans = null; @@ -33,7 +34,7 @@ class Text3DRenderMethod implements RenderMethod { rm.textureBin.attributeBin.ignoreVertexColors, cv.ctx); if (rm.doInfinite) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); while (ra != null) { trans = ra.infLocalToVworld; isNonUniformScale = !trans.isCongruent(); @@ -42,10 +43,8 @@ class Text3DRenderMethod implements RenderMethod { ra.geometry().execute(cv, ra.renderAtom, isNonUniformScale, (rm.useAlpha && ra.geometry().noAlpha), rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, - rm.textureBin.attributeBin.ignoreVertexColors, - pass); + rm.textureBin.attributeBin.ignoreVertexColors); ra = ra.next; } return true; @@ -55,7 +54,7 @@ class Text3DRenderMethod implements RenderMethod { while (ra != null) { if (cv.ra == ra.renderAtom) { if (cv.raIsVisible) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); trans = ra.localToVworld; isNonUniformScale = !trans.isCongruent(); @@ -63,18 +62,16 @@ class Text3DRenderMethod implements RenderMethod { ra.geometry().execute(cv, ra.renderAtom, isNonUniformScale, (rm.useAlpha && ra.geometry().noAlpha), rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, rm.textureBin.attributeBin. - ignoreVertexColors, - pass); + ignoreVertexColors); isVisible = true; } } else { if (!VirtualUniverse.mc.viewFrustumCulling || ra.renderAtom.localeVwcBounds.intersect(cv.viewFrustum)) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.raIsVisible = true; trans = ra.localToVworld; isNonUniformScale = !trans.isCongruent(); @@ -83,11 +80,9 @@ class Text3DRenderMethod implements RenderMethod { ra.geometry().execute(cv, ra.renderAtom, isNonUniformScale, (rm.useAlpha && ra.geometry().noAlpha), rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, rm.textureBin.attributeBin. - ignoreVertexColors, - pass); + ignoreVertexColors); isVisible = true; } else { diff --git a/src/classes/share/javax/media/j3d/Text3DRetained.java b/src/classes/share/javax/media/j3d/Text3DRetained.java index 56483ac..36ad3c0 100644 --- a/src/classes/share/javax/media/j3d/Text3DRetained.java +++ b/src/classes/share/javax/media/j3d/Text3DRetained.java @@ -458,7 +458,7 @@ class Text3DRetained extends GeometryRetained { numMessages = universeList.size(); m = new J3dMessage[numMessages]; for (i=0; i<numMessages; i++) { - m[i] = VirtualUniverse.mc.getMessage(); + m[i] = new J3dMessage(); m[i].type = J3dMessage.TEXT3D_DATA_CHANGED; m[i].threads = targetThreads; shapeList = (ArrayList)userLists.get(i); @@ -637,7 +637,7 @@ class Text3DRetained extends GeometryRetained { numMessages = universeList.size(); m = new J3dMessage[numMessages]; for (i=0; i<numMessages; i++) { - m[i] = VirtualUniverse.mc.getMessage(); + m[i] = new J3dMessage(); m[i].type = J3dMessage.TEXT3D_TRANSFORM_CHANGED; m[i].threads = targetThreads; shapeList = (ArrayList)userLists.get(i); @@ -709,7 +709,7 @@ class Text3DRetained extends GeometryRetained { charTransforms = new Transform3D[numChars]; for (i=0; i<numChars; i++) { - charTransforms[i] = VirtualUniverse.mc.getTransform3D(null); + charTransforms[i] = new Transform3D(); } if (numChars != 0) { @@ -880,7 +880,7 @@ class Text3DRetained extends GeometryRetained { } boolean intersect(Point3d[] pnts) { - Transform3D tempT3D = VirtualUniverse.mc.getTransform3D(null); + Transform3D tempT3D = new Transform3D(); GeometryArrayRetained ga; boolean isIntersect = false; Point3d transPnts[] = new Point3d[pnts.length]; @@ -901,7 +901,6 @@ class Text3DRetained extends GeometryRetained { } } } - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, tempT3D); return isIntersect; } @@ -940,21 +939,19 @@ class Text3DRetained extends GeometryRetained { void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, - boolean updateAlpha, float alpha, boolean multiScreen, + boolean updateAlpha, float alpha, int screen, - boolean ignoreVertexColors, int pass) { + boolean ignoreVertexColors) { - Transform3D trans = VirtualUniverse.mc.getTransform3D(null); + Transform3D trans = new Transform3D(); for (int i = 0; i < geometryList.length; i++) { trans.set(drawTransform); trans.mul(charTransforms[i]); cv.setModelViewMatrix(cv.ctx, vpcToEc.mat, trans); geometryList[i].execute(cv, ra, isNonUniformScale, updateAlpha, alpha, - multiScreen, screen, ignoreVertexColors, - pass); + screen, ignoreVertexColors); } - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, trans); } int getClassType() { diff --git a/src/classes/share/javax/media/j3d/Texture.java b/src/classes/share/javax/media/j3d/Texture.java index 52e6cd5..2ac1fce 100644 --- a/src/classes/share/javax/media/j3d/Texture.java +++ b/src/classes/share/javax/media/j3d/Texture.java @@ -28,10 +28,11 @@ import java.util.Hashtable; * boundary color is used when the boundaryModeS and boundaryModeT * parameters are set to CLAMP or CLAMP_TO_BOUNDARY and if the texture * boundary is not specified. </LI><P> - * <LI>Boundary Width - the texture boundary width. If the texture boundary - * width is > 0, then all images for all mipmap levels will include boundary - * texels. The actual texture image for level 0, for example, will be of - * dimension (width + 2*boundaryWidth) * (height + 2*boundaryWidth). + * <LI>Boundary Width - the texture boundary width, which must be 0 or 1. + * If the texture boundary + * width is 1, then all images for all mipmap levels will include a border. + * The actual texture image for level 0, for example, will be of + * dimension (width + 2*boundaryWidth) * (height + 2*boundaryWidth). * The boundary texels will be used when linear filtering is to be applied. * </LI><p> * <LI>Boundary ModeS and Boundary ModeT - the boundary mode for the @@ -549,7 +550,7 @@ public abstract class Texture extends NodeComponent { ALLOW_SHARPEN_TEXTURE_READ, ALLOW_SIZE_READ }; - + /** * Constructs a Texture object with default parameters. * The default values are as follows: @@ -610,6 +611,9 @@ public abstract class Texture extends NodeComponent { int width, int height) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + if ((mipMapMode != BASE_LEVEL) && (mipMapMode != MULTI_LEVEL_MIPMAP)) throw new IllegalArgumentException(J3dI18N.getString("Texture0")); @@ -619,19 +623,32 @@ public abstract class Texture extends NodeComponent { throw new IllegalArgumentException(J3dI18N.getString("Texture1")); } - // set default read capabilities - setDefaultReadCapabilities(readCapabilities); + if (width < 1) { + throw new IllegalArgumentException(J3dI18N.getString("Texture46")); + } - int widPower = getPowerOf2(width); - if (widPower == -1) - throw new IllegalArgumentException(J3dI18N.getString("Texture2")); + if (height < 1) { + throw new IllegalArgumentException(J3dI18N.getString("Texture47")); + } - int heiPower = getPowerOf2(height); - if (heiPower == -1) - throw new IllegalArgumentException(J3dI18N.getString("Texture3")); + int widthLevels; + int heightLevels; - ((TextureRetained)this.retained).initialize(format, width, widPower, - height, heiPower, mipMapMode, 0); + if (VirtualUniverse.mc.enforcePowerOfTwo) { + widthLevels = getPowerOf2(width); + if (widthLevels == -1) + throw new IllegalArgumentException(J3dI18N.getString("Texture2")); + + heightLevels = getPowerOf2(height); + if (heightLevels == -1) + throw new IllegalArgumentException(J3dI18N.getString("Texture3")); + } else { + widthLevels = getLevelsNPOT(width); + heightLevels = getLevelsNPOT(height); + } + + ((TextureRetained)this.retained).initialize(format, width, widthLevels, + height, heightLevels, mipMapMode, 0); } /** @@ -653,10 +670,10 @@ public abstract class Texture extends NodeComponent { * does not include the width of the boundary. * @param height height of image at level 0. Must be power of 2. This * does not include the width of the boundary. - * @param boundaryWidth width of the boundary. + * @param boundaryWidth width of the boundary, which must be 0 or 1. * @exception IllegalArgumentException if width or height are not a * power of 2, if an invalid format or mipMapMode is specified, or - * if the boundaryWidth < 0 + * if the boundaryWidth is < 0 or > 1 * * @since Java 3D 1.3 */ @@ -666,6 +683,9 @@ public abstract class Texture extends NodeComponent { int height, int boundaryWidth) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + if ((mipMapMode != BASE_LEVEL) && (mipMapMode != MULTI_LEVEL_MIPMAP)) throw new IllegalArgumentException(J3dI18N.getString("Texture0")); @@ -675,22 +695,35 @@ public abstract class Texture extends NodeComponent { throw new IllegalArgumentException(J3dI18N.getString("Texture1")); } - // set default read capabilities - setDefaultReadCapabilities(readCapabilities); + if (width < 1) { + throw new IllegalArgumentException(J3dI18N.getString("Texture46")); + } + + if (height < 1) { + throw new IllegalArgumentException(J3dI18N.getString("Texture47")); + } - int widPower = getPowerOf2(width); - if (widPower == -1) - throw new IllegalArgumentException(J3dI18N.getString("Texture2")); + int widthLevels; + int heightLevels; - int heiPower = getPowerOf2(height); - if (heiPower == -1) - throw new IllegalArgumentException(J3dI18N.getString("Texture3")); + if (VirtualUniverse.mc.enforcePowerOfTwo) { + widthLevels = getPowerOf2(width); + if (widthLevels == -1) + throw new IllegalArgumentException(J3dI18N.getString("Texture2")); - if (boundaryWidth < 0) + heightLevels = getPowerOf2(height); + if (heightLevels == -1) + throw new IllegalArgumentException(J3dI18N.getString("Texture3")); + } else { + widthLevels = getLevelsNPOT(width); + heightLevels = getLevelsNPOT(height); + } + + if (boundaryWidth < 0 || boundaryWidth > 1) throw new IllegalArgumentException(J3dI18N.getString("Texture30")); - ((TextureRetained)this.retained).initialize(format, width, widPower, - height, heiPower, mipMapMode, boundaryWidth); + ((TextureRetained)this.retained).initialize(format, width, widthLevels, + height, heightLevels, mipMapMode, boundaryWidth); } /** @@ -869,26 +902,45 @@ public abstract class Texture extends NodeComponent { } /** - * Sets the image for a specified mipmap level. + * Sets the image for a specified mipmap level. Note that the image size + * must be the correct size for the specified mipmap level. The image size + * of the base level image, that is level 0, must be the same size + * in each dimension (width, height, depth) as this + * texture, excluding the border, if any. + * Each successive mipmap level must be 1/2 the size of the previous level, + * such that <code>size[n] = floor(size[n-1]/2)</code>, exluding + * the border. + * * @param level mipmap level to set: 0 is the base level * @param image ImageComponent object containing the texture image * for the specified mipmap level + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @exception IllegalArgumentException if an ImageComponent3D is - * used in a Texture2D object; if an ImageComponent2D is used in a - * Texture3D object; or if this object is part of a live - * scene graph and the image being set at this level is not the - * same size (width, height, depth) as the old image at this - * level. + * used in a Texture2D object or if an ImageComponent2D is used in a + * Texture3D object. + * + * @exception IllegalArgumentException if the image being set at this + * level is not the correct size for this level. + * + * @exception IllegalSharingException if this Texture is live and + * the specified image is being used by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this Texture is + * being used by an immediate mode context and + * the specified image is being used by a Canvas3D as an off-screen buffer. */ public void setImage(int level, ImageComponent image) { if (isLiveOrCompiled()) { if(!this.getCapability(ALLOW_IMAGE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("Texture15")); } - + + // Do illegal sharing check + validateImageIllegalSharing(image); + if (isLive()) ((TextureRetained)this.retained).setImage(level, image); else @@ -913,20 +965,38 @@ public abstract class Texture extends NodeComponent { } /** - * Sets the array of images for all mipmap levels. + * Sets the array of images for all mipmap levels. Note that the image size + * of the base level image, <code>images[0]</code>, must be the same size + * in each dimension (width, height, depth) as this + * texture, excluding the border, if any. + * Each successive mipmap level must be 1/2 the size of the previous level, + * such that <code>size[n] = floor(size[n-1]/2)</code>, exluding + * the border. + * * @param images array of ImageComponent objects * containing the texture images for all mipmap levels * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @exception IllegalArgumentException if an ImageComponent3D is - * used in a Texture2D object; if an ImageComponent2D is used in a - * Texture3D object; if <code>images.length</code> is not equal to - * the total number of mipmap levels; or if this object is part of - * a live scene graph and the size of each dimension (width, - * height, depth) of the image at a given level in the - * <code>images</code> array is not half the dimension of the - * previous level. + * used in a Texture2D object or if an ImageComponent2D is used in a + * Texture3D object. + * + * @exception IllegalArgumentException if <code>images.length</code> is + * not equal to the total number of mipmap levels. + * + * @exception IllegalArgumentException if the size of each dimension + * of the image at a given level in the + * <code>images</code> array is not the correct size. + * + * @exception IllegalSharingException if this Texture is live and + * any of the specified images are being used by a Canvas3D as an + * off-screen buffer. + * + * @exception IllegalSharingException if this Texture is + * being used by an immediate mode context and + * any of the specified images are being used by a Canvas3D as an + * off-screen buffer. * * @since Java 3D 1.2 */ @@ -936,6 +1006,11 @@ public abstract class Texture extends NodeComponent { throw new CapabilityNotSetException(J3dI18N.getString("Texture15")); } + // Do illegal sharing check + for(int i=0; i<images.length; i++) { + validateImageIllegalSharing(images[i]); + } + if (images == null) throw new IllegalArgumentException(J3dI18N.getString("Texture20")); @@ -1132,6 +1207,18 @@ public abstract class Texture extends NodeComponent { //Can't reach here because we have already checked for 0 return -1; } + + // returns number of levels using NPOT rules for mipmap generation + // which say that each level should be floor(size/2) of previous level + static int getLevelsNPOT(int num) { + int tmp, levels = 0; + tmp = num; + while (tmp > 1) { + tmp = tmp / 2; + levels++; + } + return levels; + } /** * Sets the texture boundary color for this texture object. The @@ -1771,4 +1858,5 @@ public abstract class Texture extends NodeComponent { } return false; } + } diff --git a/src/classes/share/javax/media/j3d/Texture2D.java b/src/classes/share/javax/media/j3d/Texture2D.java index 766a396..ca20be6 100644 --- a/src/classes/share/javax/media/j3d/Texture2D.java +++ b/src/classes/share/javax/media/j3d/Texture2D.java @@ -11,68 +11,20 @@ */ package javax.media.j3d; -import javax.vecmath.*; +import javax.vecmath.*; /** * Texture2D is a subclass of Texture class. It extends Texture * class by adding a constructor and a mutator method for * setting a 2D texture image. - * <P> - * Each Texture2D object has the following properties:<P> - * <UL> - * <LI>Magnification filter - the magnification filter function. - * Used when the pixel being rendered maps to an area less than or - * equal to one texel. In addition to the magnification filter functions - * defined in the base Texture class, the following values are - * supported:</LI><P> - * <UL> - * <LI>LINEAR_DETAIL - performs linear sampling in both the base level - * texture image and the detail texture image, and combines the two - * texture values according to the detail texture mode.</LI><P> - * <LI>LINEAR_DETAIL_RGB - performs linear detail for the rgb - * components only. The alpha component is computed using BASE_LEVEL_LINEAR - * filter.</LI><P> - * <LI>LINEAR_DETAIL_ALPHA - performs linear detail for the alpha - * component only. The rgb components are computed using BASE_LEVEL_LINEAR - * filter.</LI><P> - * </UL> - * <LI>Detail Texture Image - Detail texture image to be used when the texture - * magnification filter mode specifies LINEAR_DETAIL, LINEAR_DETAIL_ALPHA, or - * LINEAR_DETAIL_RGB; if the detail texture images is null, then - * the texture magnification filter mode will fall back to BASE_LEVEL_LINEAR. - * </LI><P> - * <LI>Detail Texture Mode - specifies how the texture image is combined - * with the detail image. The detail texture modes are as follows: </LI><P> - * <UL> - * <LI>DETAIL_ADD</LI><P> - * <UL> - * T' = T<sub>texture</sub> + DetailFunc(LOD) * (2 * T<sub>detail</sub> - 1)<P> - * </UL> - * <LI>DETAIL_MODULATE</LI><P> - * <UL> - * T' = T<sub>texture</sub> * (1 + DetailFunc(LOD) * (2 * T<sub>detail</sub> - 1))<P> - * </UL> - * </UL> - * where T<sub>texture</sub> is the texture value computed from the base level - * texture image, and T<sub>detail</sub> is the texture value computed from the - * detail texture image.<P> - * <LI>Detail Texture Function - specifies the function of level-of-detail - * used in combining the detail texture with the base level texture of this object.</LI><P> - * <LI>Detail Texture Level - specifies the number of levels that - * separate the base level image of this texture object and the detail - * texture image. This value is used in the linear filter - * calculation of the detail texture image. Note, detail texture will only - * be applied to the level 0 of the texture image. Hence, for detail texture - * to work, base level has to be set to 0.</LI><P> - * </UL> - * - * @see Canvas3D#queryProperties */ public class Texture2D extends Texture { /** + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * Specifies that this Texture object allows reading its detail * texture information (e.g., detail texture image, detail texture mode, * detail texture function, detail texture function points count, @@ -84,6 +36,8 @@ public class Texture2D extends Texture { ALLOW_DETAIL_TEXTURE_READ = CapabilityBits.TEXTURE2D_ALLOW_DETAIL_TEXTURE_READ; /** + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * Performs linear sampling in both the base level * texture image and the detail texture image, and combines the two * texture values according to the detail texture mode. @@ -94,6 +48,8 @@ public class Texture2D extends Texture { public static final int LINEAR_DETAIL = 6; /** + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * Performs linear detail for the rgb * components only. The alpha component is computed using * BASE_LEVEL_LINEAR filter. @@ -104,6 +60,8 @@ public class Texture2D extends Texture { public static final int LINEAR_DETAIL_RGB = 7; /** + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * Performs linear detail for the alpha * component only. The rgb components are computed using * BASE_LEVEL_LINEAR filter. @@ -114,6 +72,8 @@ public class Texture2D extends Texture { public static final int LINEAR_DETAIL_ALPHA = 8; /** + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * Adds the detail texture image to the level 0 image of this texture * object * @@ -123,6 +83,8 @@ public class Texture2D extends Texture { public static final int DETAIL_ADD = 0; /** + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * Modulates the detail texture image with the level 0 image of this * texture object * @@ -167,10 +129,10 @@ public class Texture2D extends Texture { * BASE_LEVEL, MULTI_LEVEL_MIPMAP. * @param format data format of Textures saved in this object. * One of INTENSITY, LUMINANCE, ALPHA, LUMINANCE_ALPHA, RGB, RGBA. - * @param width width of image at level 0. Must be power of 2. - * @param height height of image at level 0. Must be power of 2. + * @param width width of image at level 0. Must be greater than 0 + * @param height height of image at level 0. Must be greater than 0 * @exception IllegalArgumentException if width or height are NOT - * power of 2 OR invalid format/mipmapMode is specified. + * greater than 0 OR invalid format/mipmapMode is specified. */ public Texture2D( int mipMapMode, @@ -200,14 +162,14 @@ public class Texture2D extends Texture { * BASE_LEVEL, MULTI_LEVEL_MIPMAP * @param format data format of Textures saved in this object. * One of INTENSITY, LUMINANCE, ALPHA, LUMINANCE_ALPHA, RGB, RGBA - * @param width width of image at level 0. Must be power of 2. This + * @param width width of image at level 0. Must be greater than 0. This * does not include the width of the boundary. - * @param height height of image at level 0. Must be power of 2. This + * @param height height of image at level 0. Must be greater than 0. This * does not include the width of the boundary. - * @param boundaryWidth width of the boundary. - * @exception IllegalArgumentException if width or height are not a - * power of 2, if an invalid format or mipMapMode is specified, or - * if the boundaryWidth < 0 + * @param boundaryWidth width of the boundary, which must be 0 or 1. + * @exception IllegalArgumentException if width or height are not greater + * than 0, if an invalid format or mipMapMode is specified, or + * if the boundaryWidth is < 0 or > 1 * * @since Java 3D 1.3 */ @@ -271,7 +233,9 @@ public class Texture2D extends Texture { } /** - * Sets the detail texture image for this texture object. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. + * * @param detailTexture ImageComponent2D object containing the * detail texture image. * @exception RestrictedAccessException if the method is called @@ -286,7 +250,9 @@ public class Texture2D extends Texture { } /** - * Retrieves the detail texture image for this texture object. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. + * * @return ImageComponent2D object containing the detail texture image. * * @exception CapabilityNotSetException if appropriate capability is @@ -305,7 +271,9 @@ public class Texture2D extends Texture { } /** - * Sets the detail texture mode for this texture object. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. + * * @param mode detail texture mode. One of: DETAIL_ADD or DETAIL_MODULATE * * @exception IllegalArgumentException if @@ -327,7 +295,9 @@ public class Texture2D extends Texture { } /** - * Retrieves the detail texture mode for this texture object. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. + * * @return the detail texture mode. * * @exception CapabilityNotSetException if appropriate capability is @@ -346,7 +316,9 @@ public class Texture2D extends Texture { } /** - * Sets the detail texture level for this texture object. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. + * * @param level the detail texture level. * * @exception IllegalArgumentException if <code>level</code> < 0 @@ -366,7 +338,9 @@ public class Texture2D extends Texture { } /** - * Retrieves the detail texture level for this texture object. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. + * * @return the detail texture level. * * @exception CapabilityNotSetException if appropriate capability is @@ -385,7 +359,9 @@ public class Texture2D extends Texture { } /** - * sets the detail texture LOD function for this texture object. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. + * * @param lod array containing the level-of-detail values. * @param pts array containing the function values for the corresponding * level-of-detail values. @@ -409,9 +385,8 @@ public class Texture2D extends Texture { } /** - * sets the detail texture LOD function for this texture object. - * The Point2f x,y values are defined as follows: x is the lod value, - * y is the corresponding function value. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * * @param pts array of Point2f containing the lod as well as the * corresponding function value. @@ -428,8 +403,8 @@ public class Texture2D extends Texture { } /** - * Gets the number of points in the detail texture LOD function for this - * texture object. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * * @return the number of points in the detail texture LOD function. * @@ -449,9 +424,8 @@ public class Texture2D extends Texture { } /** - * Copies the array of detail texture LOD function points into the - * specified arrays. The arrays must be large enough to hold all the - * points. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * * @param lod the array to receive the level-of-detail values. * @param pts the array to receive the function values for the @@ -473,10 +447,8 @@ public class Texture2D extends Texture { } /** - * Copies the array of detail texture LOD function points including - * the lod values and the corresponding function values into the - * specified array. The array must be large enough to hold all the points. - * The individual array elements must be allocated by the caller as well. + * @deprecated As of Java 3D 1.5 the optional detail texture feature is no + * longer supported. * * @param pts the array to receive the detail texture LOD function points * diff --git a/src/classes/share/javax/media/j3d/Texture2DRetained.java b/src/classes/share/javax/media/j3d/Texture2DRetained.java index 991c6ee..4957680 100644 --- a/src/classes/share/javax/media/j3d/Texture2DRetained.java +++ b/src/classes/share/javax/media/j3d/Texture2DRetained.java @@ -22,17 +22,18 @@ import javax.vecmath.*; */ class Texture2DRetained extends TextureRetained { + // Note : There is hardly any HW vendor supports detail Image. + // Detail Image operation is simply no-op in 1.5. + // currently detail image is only applicable to 2D texture - // detail texture info - - int detailTextureId = -1; - ImageComponent2DRetained detailImage = null; - DetailTextureImage detailTexture = null; - int detailTextureMode = Texture2D.DETAIL_MODULATE; - int detailTextureLevel = 2; - int numDetailTextureFuncPts = 0; - float detailTextureFuncPts[] = null; // array of pairs of floats + + // These members are unused except for public set and get methods. + private ImageComponent2DRetained detailImage = null; + private int detailTextureMode = Texture2D.DETAIL_MODULATE; + private int detailTextureLevel = 2; + private int numDetailTextureFuncPts = 0; + private float detailTextureFuncPts[] = null; // array of pairs of floats // first value for LOD // second value for the fcn value @@ -44,7 +45,6 @@ class Texture2DRetained extends TextureRetained { detailImage = null; } else { detailImage = (ImageComponent2DRetained)image.retained; - detailImage.setTextureRef(); } } @@ -184,174 +184,6 @@ class Texture2DRetained extends TextureRetained { return detailTextureFuncPts; } - synchronized void initMirrorObject() { - - super.initMirrorObject(); - - Texture2DRetained mirrorTexture = (Texture2DRetained)mirror; - - // detail texture info - mirrorTexture.detailImage = detailImage; - mirrorTexture.detailTextureMode = detailTextureMode; - mirrorTexture.detailTextureLevel = detailTextureLevel; - mirrorTexture.detailTexture = null; - mirrorTexture.numDetailTextureFuncPts = numDetailTextureFuncPts; - - if (detailTextureFuncPts == null) { - mirrorTexture.detailTextureFuncPts = null; - } else { - if ((mirrorTexture.detailTextureFuncPts == null) || - (mirrorTexture.detailTextureFuncPts.length != - detailTextureFuncPts.length)) { - mirrorTexture.detailTextureFuncPts = - new float[detailTextureFuncPts.length]; - } - for (int i = 0; i < detailTextureFuncPts.length; i++) { - mirrorTexture.detailTextureFuncPts[i] = - detailTextureFuncPts[i]; - } - - // add detail texture to the user list of the image - // only if detail texture is to be used - if ((mirrorTexture.detailImage != null) && - (mirrorTexture.magFilter >= Texture2D.LINEAR_DETAIL) && - (mirrorTexture.magFilter <= Texture2D.LINEAR_DETAIL_ALPHA)) { - mirrorTexture.detailImage.addUser(mirrorTexture); - } - } - } - - void clearLive(int refCount) { - super.clearLive(refCount); - - // remove detail texture from the user list of the image - if ((detailImage != null) && - (magFilter >= Texture2D.LINEAR_DETAIL) && - (magFilter <= Texture2D.LINEAR_DETAIL_ALPHA)) { - detailImage.removeUser(mirror); - } - } - - // overload the incTextureBinRefCount method to take care - // of detail texture ref as well - // This method is called from RenderBin when a new TextureBin - // is created. And all the referenced textures in that TextureBin - // will be notified to increment the TextureBin reference count. - - void incTextureBinRefCount(TextureBin tb) { - super.incTextureBinRefCount(tb); - - // increment detail texture ref count - - if ((detailImage != null) && - (magFilter >= Texture2D.LINEAR_DETAIL) && - (magFilter <= Texture2D.LINEAR_DETAIL_ALPHA)) { - if (detailTexture == null) { - detailTexture = detailImage.getDetailTexture(); - } - - detailTexture.incTextureBinRefCount(format, tb); - } - } - - // This method is called from AttributeBin when a TextureBin - // is to be removed. And all the referenced textures in that TextureBin - // will be notified to decrement the TextureBin reference count. - // And if detail texture exists, we need to decrement the - // TextureBin reference count of the detail texture as well. - - void decTextureBinRefCount(TextureBin tb) { - super.decTextureBinRefCount(tb); - - // decrement detail texture ref count - - if (detailTexture != null) { - detailTexture.decTextureBinRefCount(format, tb); - } - } - - - native void bindDetailTexture(long ctx, int objectId); - - native void updateTextureImage(long ctx, - int numLevels, - int level, - int internalFormat, int format, - int width, int height, - int boundaryWidth, byte[] imageYup); - - native void updateTextureSubImage(long ctx, - int level, int xoffset, int yoffset, - int internalFormat,int format, - int imgXOffset, int imgYOffset, - int tilew, - int width, int height, - byte[] image); - - native void updateDetailTextureParameters(long ctx, - int detailTextureMode, - int detailTextureLevel, - int nPts, float[] pts); - // wrapper to the native call - - void updateTextureImage(Canvas3D cv, int face, - int numLevels, int level, - int format, int storedFormat, - int width, int height, - int boundaryWidth, - byte[] data) { - - updateTextureImage(cv.ctx, numLevels, level, format, - storedFormat, width, height, - boundaryWidth, data); - } - - - - // wrapper to the native call - - void updateTextureSubImage(Canvas3D cv, int face, int level, - int xoffset, int yoffset, int format, - int storedFormat, int imgXOffset, - int imgYOffset, int tileWidth, - int width, int height, byte[] data) { - - updateTextureSubImage(cv.ctx, level, xoffset, yoffset, format, - storedFormat, imgXOffset, imgYOffset, - tileWidth, width, height, data); - } - - - void updateNative(Canvas3D cv) { - - // update mipmap texture - - super.updateNative(cv); - - - // update detail texture if exists - - if (detailTexture != null) { - detailTexture.updateNative(cv, format); - } - } - - - // update texture parameters - - void updateTextureFields(Canvas3D cv) { - - super.updateTextureFields(cv); - - // update detail texture parameters if applicable - - if (detailTexture != null) { - - updateDetailTextureParameters(cv.ctx, detailTextureMode, - detailTextureLevel, numDetailTextureFuncPts, - detailTextureFuncPts); - } - } } diff --git a/src/classes/share/javax/media/j3d/Texture3D.java b/src/classes/share/javax/media/j3d/Texture3D.java index 69f007d..024a2d8 100644 --- a/src/classes/share/javax/media/j3d/Texture3D.java +++ b/src/classes/share/javax/media/j3d/Texture3D.java @@ -24,6 +24,8 @@ package javax.media.j3d; public class Texture3D extends Texture { + // TODO KCR : NPOT + /** * Constructs a Texture3D object with default parameters. * The default values are as follows: @@ -62,10 +64,20 @@ public class Texture3D extends Texture { int depth) { super(mipmapMode, format, width, height); - int depthPower = getPowerOf2(depth); - if (depthPower == -1) - throw new IllegalArgumentException(J3dI18N.getString("Texture3D1")); + int depthLevels = -1; + if (VirtualUniverse.mc.enforcePowerOfTwo) { + depthLevels = getPowerOf2(depth); + if (depthLevels == -1) + throw new IllegalArgumentException(J3dI18N.getString("Texture3D1")); + + } else { + depthLevels = getLevelsNPOT(depth); + } + + // TODO : Need to verify whether this is a bug. Why depthLevels isn't + // use to determine maxMipMapLevels ? See also Texture.java + ((Texture3DRetained)this.retained).setDepth(depth); } @@ -83,10 +95,10 @@ public class Texture3D extends Texture { * @param width width of image at level 0. Must be power of 2. * @param height height of image at level 0. Must be power of 2. * @param depth depth of image at level 0. Must be power of 2. - * @param boundaryWidth width of the boundary. + * @param boundaryWidth width of the boundary, which must be 0 or 1. * @exception IllegalArgumentException if width or height are NOT * power of 2 OR invalid format/mipmapMode is specified, or - * if the boundaryWidth < 0 + * if the boundaryWidth is < 0 or > 1 * * @since Java 3D 1.3 */ @@ -98,10 +110,22 @@ public class Texture3D extends Texture { int boundaryWidth) { super(mipmapMode, format, width, height, boundaryWidth); - int depthPower = getPowerOf2(depth); - if (depthPower == -1) - throw new IllegalArgumentException(J3dI18N.getString("Texture3D1")); - + int depthLevels = -1; + + if (VirtualUniverse.mc.enforcePowerOfTwo) { + depthLevels = getPowerOf2(depth); + + if (depthLevels == -1) + throw new IllegalArgumentException(J3dI18N.getString("Texture3D1")); + } + else { + depthLevels = getLevelsNPOT(depth); + + } + + // TODO : Need to verify whether this is a bug. Why depthLevels isn't + // use to determine maxMipMapLevels ? See also Texture.java + ((Texture3DRetained)this.retained).setDepth(depth); } diff --git a/src/classes/share/javax/media/j3d/Texture3DRetained.java b/src/classes/share/javax/media/j3d/Texture3DRetained.java index 6128325..5e4f667 100644 --- a/src/classes/share/javax/media/j3d/Texture3DRetained.java +++ b/src/classes/share/javax/media/j3d/Texture3DRetained.java @@ -57,42 +57,84 @@ class Texture3DRetained extends TextureRetained { /** * This method updates the native context. */ - native void bindTexture(long ctx, int objectId, boolean enable); + void bindTexture(Context ctx, int objectId, boolean enable) { + Pipeline.getPipeline().bindTexture3D(ctx, objectId, enable); + } - native void updateTextureBoundary(long ctx, - int boundaryModeS, int boundaryModeT, - int boundaryModeR, float boundaryRed, - float boundaryGreen, float boundaryBlue, - float boundaryAlpha); - - native void updateTextureFilterModes(long ctx, - int minFilter, int magFilter); + void updateTextureBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + int boundaryModeR, float boundaryRed, + float boundaryGreen, float boundaryBlue, + float boundaryAlpha) { - native void updateTextureSharpenFunc(long ctx, - int numSharpenTextureFuncPts, - float[] sharpenTextureFuncPts); + Pipeline.getPipeline().updateTexture3DBoundary(ctx, + boundaryModeS, boundaryModeT, boundaryModeR, + boundaryRed, boundaryGreen, + boundaryBlue, boundaryAlpha); + } - native void updateTextureFilter4Func(long ctx, - int numFilter4FuncPts, - float[] filter4FuncPts); + void updateTextureFilterModes(Context ctx, + int minFilter, int magFilter) { - native void updateTextureAnisotropicFilter(long ctx, float degree); + Pipeline.getPipeline().updateTexture3DFilterModes(ctx, + minFilter, magFilter); + } + void updateTextureSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { + + Pipeline.getPipeline().updateTexture3DSharpenFunc(ctx, + numSharpenTextureFuncPts, sharpenTextureFuncPts); + } - native void updateTextureImage(long ctx, int numLevels, int level, - int format, int internalFormat, int width, - int height, int depth, - int boundaryWidth, byte[] imageYup); + void updateTextureFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + + Pipeline.getPipeline().updateTexture3DFilter4Func(ctx, + numFilter4FuncPts, filter4FuncPts); + } + + void updateTextureAnisotropicFilter(Context ctx, float degree) { + Pipeline.getPipeline().updateTexture3DAnisotropicFilter(ctx, degree); + } - native void updateTextureSubImage(long ctx, int level, - int xoffset, int yoffset, int zoffset, - int internalFormat, int format, - int imgXoffset, int imgYoffset, int imgZoffset, - int tilew, int tileh, - int width, int height, int depth, - byte[] imageYup); + // Wrapper around the native call for 3D textures + void updateTextureImage(Canvas3D cv, + int face, int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, int depth, + int boundaryWidth, int imageDataType, + Object imageData) { + + Pipeline.getPipeline().updateTexture3DImage(cv.ctx, + numLevels, level, + textureFormat, imageFormat, + width, height, depth, + boundaryWidth, imageDataType, imageData); + } + + // Wrapper around the native call for 3D textures + void updateTextureSubImage(Canvas3D cv, + int face, int level, + int xoffset, int yoffset, int zoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, int imgZOffset, + int tilew, int tileh, int width, int height, int depth, + int imageDataType, Object imageData) { + + Pipeline.getPipeline().updateTexture3DSubImage(cv.ctx, + level, xoffset, yoffset, zoffset, + textureFormat, imageFormat, + imgXOffset, imgYOffset, imgZOffset, + tilew, tileh, width, height, depth, + imageDataType, imageData); + } + + // get an ID for Texture3D int getTextureId() { @@ -116,18 +158,36 @@ class Texture3DRetained extends TextureRetained { // mipmapping when level 0 is not the base level void updateTextureDimensions(Canvas3D cv) { - updateTextureImage(cv.ctx, maxLevels, 0, - format, ImageComponentRetained.BYTE_RGBA, - width, height, depth, boundaryWidth, null); + if(images[0][0] != null) { + updateTextureImage(cv, maxLevels, 0, 0, + format, images[0][0].getImageFormatTypeIntValue(false), + width, height, depth, boundaryWidth, + images[0][0].getImageDataTypeIntValue(), null); + } } void updateTextureBoundary(Canvas3D cv) { - updateTextureBoundary(cv.ctx, - boundaryModeS, boundaryModeT, boundaryModeR, - boundaryColor.x, boundaryColor.y, - boundaryColor.z, boundaryColor.w); - + updateTextureBoundary(cv.ctx, + boundaryModeS, boundaryModeT, boundaryModeR, + boundaryColor.x, boundaryColor.y, + boundaryColor.z, boundaryColor.w); + } + + void updateTextureLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + + Pipeline.getPipeline().updateTexture3DLodRange(ctx, baseLevel, maximumLevel, + minimumLod, maximumLod); + } + + void updateTextureLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + + Pipeline.getPipeline().updateTexture3DLodOffset(ctx, + lodOffsetX, lodOffsetY, lodOffsetZ); } void reloadTextureImage(Canvas3D cv, int face, int level, @@ -139,13 +199,16 @@ class Texture3DRetained extends TextureRetained { " h= " + image.height + " d= " + depth + " numLevels= " + numLevels); */ - - - updateTextureImage(cv.ctx, numLevels, level, format, - image.storedYupFormat, - image.width, image.height, depth, - boundaryWidth, image.imageYup); - + + // Texture3D does not need to support Raster + ImageComponentRetained.ImageData imageData = image.getImageData(false); + + updateTextureImage(cv, + 0, numLevels, level, format, + image.getImageFormatTypeIntValue(false), + image.width, image.height, depth, + boundaryWidth, image.getImageDataTypeIntValue(), + imageData.get()); } void reloadTextureSubImage(Canvas3D cv, int level, int face, @@ -157,43 +220,18 @@ class Texture3DRetained extends TextureRetained { width = info.width, height = info.height; - int xoffset = x - image.minX; - int yoffset = y - image.minY; - - updateTextureSubImage(cv.ctx, level, xoffset, yoffset, z, - format, image.storedYupFormat, - xoffset, yoffset, z, - image.width, image.height, - width, height, 1, image.imageYup); - } - - - - protected void finalize() { - - if (objectId > 0) { - // memory not yet free - // send a message to the request renderer - synchronized (VirtualUniverse.mc.contextCreationLock) { - boolean found = false; - - for (Enumeration e = Screen3D.deviceRendererMap.elements(); - e.hasMoreElements(); ) { - Renderer rdr = (Renderer) e.nextElement(); - J3dMessage renderMessage = VirtualUniverse.mc.getMessage(); - renderMessage.threads = J3dThread.RENDER_THREAD; - renderMessage.type = J3dMessage.RENDER_IMMEDIATE; - renderMessage.universe = null; - renderMessage.view = null; - renderMessage.args[0] = null; - renderMessage.args[1] = new Integer(objectId); - renderMessage.args[2] = "3D"; - rdr.rendererStructure.addMessage(renderMessage); - } - objectId = -1; - } - VirtualUniverse.mc.setWorkForRequestRenderer(); - } + int xoffset = x; + int yoffset = y; + // Texture3D does not need to support Raster + ImageComponentRetained.ImageData imageData = image.getImageData(false); + + updateTextureSubImage(cv, + 0, level, xoffset, yoffset, z, + format, image.getImageFormatTypeIntValue(false), + xoffset, yoffset, z, + image.width, image.height, + width, height, 1, image.getImageDataTypeIntValue(), + imageData.get()); } } diff --git a/src/classes/share/javax/media/j3d/TextureAttributesRetained.java b/src/classes/share/javax/media/j3d/TextureAttributesRetained.java index 3b58d95..aaba553 100644 --- a/src/classes/share/javax/media/j3d/TextureAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/TextureAttributesRetained.java @@ -220,8 +220,7 @@ class TextureAttributesRetained extends NodeComponentRetained { */ final void setTextureTransform(Transform3D transform) { this.transform.set(transform); - sendMessage(TRANSFORM_CHANGED, - VirtualUniverse.mc.getTransform3D(transform), null); + sendMessage(TRANSFORM_CHANGED, new Transform3D(transform), null); } @@ -498,39 +497,6 @@ class TextureAttributesRetained extends NodeComponentRetained { return combineAlphaScale; } - // These methods update the native context. - native void updateNative(long ctx, - double[] transform, boolean isIdentity, int textureMode, - int perspCorrectionMode, float red, - float green, float blue, float alpha, - int textureFormat); - - native void updateNativeRegisterCombiners(long ctx, - double[] transform, boolean isIdentity, int textureMode, - int perspCorrectionMode, float red, - float green, float blue, float alpha, - int textureFormat, - int combineRgbMode, int combineAlphaMode, - int[] combineRgbSrc, int[] combineAlphaSrc, - int[] combineRgbFcn, int[] combineAlphaFcn, - int combineRgbScale, int combineAlphaScale); - - native void updateTextureColorTableNative(long ctx, int numComponents, - int colorTableSize, - int[] colorTable); - - native void updateCombinerNative(long ctx, - int combineRgbMode, int combineAlphaMode, - int[] combineRgbSrc, int[] combineAlphaSrc, - int[] combineRgbFcn, int[] combineAlphaFcn, - int combineRgbScale, int combineAlphaScale); - - // NOTE: the following native methods are not used any more, since - // we no longer do simulated multi-pass by default - // (and with shaders, this won't work anyway) -// native void restoreBlend1Pass(long ctx); -// native void updateBlend2Pass(long ctx); - void updateNative(Canvas3D cv, boolean simulate, int textureFormat) { //System.out.println("TextureAttributes/updateNative: simulate= " + simulate + " " + this); @@ -548,14 +514,14 @@ class TextureAttributesRetained extends NodeComponentRetained { if (VirtualUniverse.mc.useCombiners && (cv.textureExtendedFeatures & Canvas3D.TEXTURE_REGISTER_COMBINERS) != 0) { - updateNativeRegisterCombiners(cv.ctx, - transform.mat, isIdentity, textureMode, perspCorrectionMode, - textureBlendColor.x, textureBlendColor.y, - textureBlendColor.z, textureBlendColor.w, - textureFormat, combineRgbMode, combineAlphaMode, - combineRgbSrc, combineAlphaSrc, - combineRgbFcn, combineAlphaFcn, - combineRgbScale, combineAlphaScale); + Pipeline.getPipeline().updateRegisterCombiners(cv.ctx, + transform.mat, isIdentity, textureMode, perspCorrectionMode, + textureBlendColor.x, textureBlendColor.y, + textureBlendColor.z, textureBlendColor.w, + textureFormat, combineRgbMode, combineAlphaMode, + combineRgbSrc, combineAlphaSrc, + combineRgbFcn, combineAlphaFcn, + combineRgbScale, combineAlphaScale); } else { if (textureMode == TextureAttributes.COMBINE) { @@ -567,11 +533,12 @@ class TextureAttributesRetained extends NodeComponentRetained { int _combineRgbMode = combineRgbMode; int _combineAlphaMode = combineAlphaMode; - updateNative(cv.ctx, transform.mat, isIdentity, textureMode, - perspCorrectionMode, - textureBlendColor.x, textureBlendColor.y, - textureBlendColor.z, textureBlendColor.w, - textureFormat); + Pipeline.getPipeline().updateTextureAttributes(cv.ctx, + transform.mat, isIdentity, textureMode, + perspCorrectionMode, + textureBlendColor.x, textureBlendColor.y, + textureBlendColor.z, textureBlendColor.w, + textureFormat); if (((combineRgbMode == TextureAttributes.COMBINE_DOT3) && @@ -600,30 +567,32 @@ class TextureAttributesRetained extends NodeComponentRetained { _combineAlphaMode = TextureAttributes.COMBINE_REPLACE; } - updateCombinerNative(cv.ctx, - _combineRgbMode, _combineAlphaMode, - combineRgbSrc, combineAlphaSrc, - combineRgbFcn, combineAlphaFcn, - combineRgbScale, combineAlphaScale); + Pipeline.getPipeline().updateCombiner(cv.ctx, + _combineRgbMode, _combineAlphaMode, + combineRgbSrc, combineAlphaSrc, + combineRgbFcn, combineAlphaFcn, + combineRgbScale, combineAlphaScale); } else { // Texture COMBINE is not supported by the underlying // layer, fallback to REPLACE - updateNative(cv.ctx, transform.mat, isIdentity, - TextureAttributes.REPLACE, - perspCorrectionMode, - textureBlendColor.x, textureBlendColor.y, - textureBlendColor.z, textureBlendColor.w, - textureFormat); + Pipeline.getPipeline().updateTextureAttributes(cv.ctx, + transform.mat, isIdentity, + TextureAttributes.REPLACE, + perspCorrectionMode, + textureBlendColor.x, textureBlendColor.y, + textureBlendColor.z, textureBlendColor.w, + textureFormat); } } else { - updateNative(cv.ctx, transform.mat, isIdentity, textureMode, - perspCorrectionMode, - textureBlendColor.x, textureBlendColor.y, - textureBlendColor.z, textureBlendColor.w, - textureFormat); + Pipeline.getPipeline().updateTextureAttributes(cv.ctx, + transform.mat, isIdentity, textureMode, + perspCorrectionMode, + textureBlendColor.x, textureBlendColor.y, + textureBlendColor.z, textureBlendColor.w, + textureFormat); } } @@ -631,7 +600,7 @@ class TextureAttributesRetained extends NodeComponentRetained { if (((cv.textureExtendedFeatures & Canvas3D.TEXTURE_COLOR_TABLE) != 0) && textureColorTable != null) { - updateTextureColorTableNative(cv.ctx, + Pipeline.getPipeline().updateTextureColorTable(cv.ctx, numTextureColorTableComponents, textureColorTableSize, textureColorTable); } @@ -639,15 +608,16 @@ class TextureAttributesRetained extends NodeComponentRetained { // we are in the multi-pass mode, // in this case, set the texture Mode to replace and use // blending to simulate the original textureMode - updateNative(cv.ctx, transform.mat, isIdentity, TextureAttributes.REPLACE, - perspCorrectionMode, - textureBlendColor.x, textureBlendColor.y, - textureBlendColor.z, textureBlendColor.w, textureFormat); + Pipeline.getPipeline().updateTextureAttributes(cv.ctx, + transform.mat, isIdentity, TextureAttributes.REPLACE, + perspCorrectionMode, + textureBlendColor.x, textureBlendColor.y, + textureBlendColor.z, textureBlendColor.w, textureFormat); if (((cv.textureExtendedFeatures & Canvas3D.TEXTURE_COLOR_TABLE) != 0) && textureColorTable != null) { - updateTextureColorTableNative(cv.ctx, numTextureColorTableComponents, + Pipeline.getPipeline().updateTextureColorTable(cv.ctx, numTextureColorTableComponents, textureColorTableSize, textureColorTable); } @@ -727,8 +697,6 @@ class TextureAttributesRetained extends NodeComponentRetained { if ((component & TRANSFORM_CHANGED) != 0) { mirrorTa.transform.set((Transform3D)value); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - (Transform3D)value); } else if ((component & MODE_CHANGED) != 0) { mirrorTa.textureMode = ((Integer)value).intValue(); @@ -969,7 +937,7 @@ class TextureAttributesRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.TEXTUREATTRIBUTES_CHANGED; createMessage.universe = null; @@ -983,7 +951,7 @@ class TextureAttributesRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.TEXTUREATTRIBUTES_CHANGED; diff --git a/src/classes/share/javax/media/j3d/TextureBin.java b/src/classes/share/javax/media/j3d/TextureBin.java index 9a004bc..75c5229 100644 --- a/src/classes/share/javax/media/j3d/TextureBin.java +++ b/src/classes/share/javax/media/j3d/TextureBin.java @@ -152,21 +152,27 @@ class TextureBin extends Object implements ObjectUpdate { transparentRMList = null; numEditingRenderMolecules = 0; + // Issue 249 - check for sole user only if property is set // determine if this appearance is a sole user of this // TextureBin - if ((app != null) && - (app.changedFrequent & - (AppearanceRetained.TEXTURE | - AppearanceRetained.TEXCOORD_GEN | - AppearanceRetained.TEXTURE_ATTR | - AppearanceRetained.TEXTURE_UNIT_STATE)) != 0) { - tbFlag |= TextureBin.SOLE_USER; - this.app = app; + tbFlag &= ~TextureBin.SOLE_USER; + if (VirtualUniverse.mc.allowSoleUser) { + if ((app != null) && + (app.changedFrequent & + (AppearanceRetained.TEXTURE | + AppearanceRetained.TEXCOORD_GEN | + AppearanceRetained.TEXTURE_ATTR | + AppearanceRetained.TEXTURE_UNIT_STATE)) != 0) { + tbFlag |= TextureBin.SOLE_USER; - } else { - tbFlag &= ~TextureBin.SOLE_USER; - this.app = null; + } } + + if ((tbFlag & TextureBin.SOLE_USER) != 0) { + this.app = app; + } else { + this.app = null; + } resetTextureState(state); @@ -1015,7 +1021,6 @@ class TextureBin extends Object implements ObjectUpdate { r.prev = null; r.next = null; - renderBin.renderMoleculeFreelist.add(r); found = true; } } @@ -1082,14 +1087,14 @@ class TextureBin extends Object implements ObjectUpdate { texUnitState = null; } } - + /** * This method is called to update the state for this * TextureBin. This is only applicable in the single-pass case. * Multi-pass render will have to take care of its own * state update. */ - void updateAttributes(Canvas3D cv, int pass) { + void updateAttributes(Canvas3D cv) { boolean dirty = ((cv.canvasDirty & (Canvas3D.TEXTUREBIN_DIRTY| Canvas3D.TEXTUREATTRIBUTES_DIRTY)) != 0); @@ -1112,11 +1117,11 @@ class TextureBin extends Object implements ObjectUpdate { useShaders ? cv.maxTextureImageUnits : cv.maxTextureUnits; // If the number of active texture units is greater than the number of - // supported units, and we don't allow simulated multi-texture, then we + // supported units, then we // need to set a flag indicating that the texture units are invalid. boolean disableTexture = false; - if (pass < 0 && numActiveTexUnit > availableTextureUnits) { + if (numActiveTexUnit > availableTextureUnits) { disableTexture = true; // System.err.println("*** TextureBin : number of texture units exceeded"); } @@ -1148,7 +1153,7 @@ class TextureBin extends Object implements ObjectUpdate { } cv.setLastActiveTexUnit(-1); } - } else if (pass < 0) { + } else { int j = 0; @@ -1194,28 +1199,10 @@ class TextureBin extends Object implements ObjectUpdate { } cv.setLastActiveTexUnit(lastActiveTexUnitIdx); - // tell the underlying library the texture unit mapping - - if ((pass == USE_DISPLAYLIST) && - (cv.numActiveTexUnit > 0)) { - cv.updateTexUnitStateMap(); - } // set the active texture unit back to 0 cv.activeTextureUnit(cv.ctx, 0); - } else { - // update the last active texture unit state - if (dirty || cv.texUnitState[0].mirror == null || - cv.texUnitState[0].mirror != - texUnitState[lastActiveTexUnitIndex].mirror) { - texUnitState[lastActiveTexUnitIndex].updateNative( - -1, cv, false, false); - cv.texUnitState[0].mirror = - texUnitState[lastActiveTexUnitIndex].mirror; - - cv.setLastActiveTexUnit(0); - } } cv.canvasDirty &= ~Canvas3D.TEXTUREBIN_DIRTY; } @@ -1256,20 +1243,7 @@ class TextureBin extends Object implements ObjectUpdate { } } - // If shaders are not being used, and if allowSimulatedMultiTexture - // property is set, then we will use simulated (multi-pass) - // multi-texture when the requested number of texture units exceeds - // the available number of texture units - boolean useShaders = (shaderBin.shaderProgram != null); - int availableTextureUnits = - useShaders ? cv.maxTextureImageUnits : cv.maxTextureUnits; - - if (!useShaders && (numActiveTexUnit > availableTextureUnits) && - VirtualUniverse.mc.allowSimulatedMultiTexture) { - multiPassRender(cv, rlist); - } else { - renderList(cv, USE_DISPLAYLIST, rlist); - } + renderList(cv, USE_DISPLAYLIST, rlist); } @@ -1277,6 +1251,7 @@ class TextureBin extends Object implements ObjectUpdate { * render a render list */ void renderList(Canvas3D cv, int pass, Object rlist) { + assert pass < 0; if (rlist instanceof RenderMolecule) { renderList(cv, pass, (RenderMolecule) rlist); @@ -1290,6 +1265,7 @@ class TextureBin extends Object implements ObjectUpdate { * render list of RenderMolecule */ void renderList(Canvas3D cv, int pass, RenderMolecule rlist) { + assert pass < 0; // bit mask of all attr fields that are equivalent across // renderMolecules thro. ORing of invisible RMs. @@ -1323,6 +1299,7 @@ class TextureBin extends Object implements ObjectUpdate { * render sorted transparent list */ void renderList(Canvas3D cv, int pass, TransparentRenderingInfo tinfo) { + assert pass < 0; RenderMolecule rm = tinfo.rm; if (rm.isSwitchOn()) { @@ -1331,87 +1308,6 @@ class TextureBin extends Object implements ObjectUpdate { } - - /** - * multi rendering pass to simulate multiple texture units - */ - private void multiPassRender(Canvas3D cv, Object rlist) { - - assert VirtualUniverse.mc.allowSimulatedMultiTexture; - - boolean startToSimulate = false; - boolean isFogEnabled = false; - - // No lazy download of texture for multi-pass, - // update the texture states here now - - // update the environment state - - // no need to update the texture state in updateAttributes(), the state - // will be explicitly updated in the multi-pass - cv.setStateIsUpdated(Canvas3D.TEXTUREBIN_BIT); - cv.textureBin = this; - cv.canvasDirty &= ~Canvas3D.TEXTUREBIN_DIRTY; - cv.updateEnvState(); - - - // first reset those texture units that are currently enabled - - if (cv.multiTexAccelerated) { - int activeTexUnit = cv.getNumActiveTexUnit(); - for (int i = 0; i < activeTexUnit; i++) { - cv.resetTexture(cv.ctx, i); - } - // set the active texture unit back to 0 - cv.activeTextureUnit(cv.ctx, 0); - } - - // only texture unit 0 will be used in multi-pass case - cv.setNumActiveTexUnit(1); - cv.setLastActiveTexUnit(0); - - // first check if there is fog in the path - // if there is, then turn off fog now and turn it back on - // for the last pass only - isFogEnabled = (environmentSet.fog != null); - - TextureUnitStateRetained tus; - - for (int i = 0; i < texUnitState.length; i++) { - tus = texUnitState[i]; - - if (tus != null && tus.isTextureEnabled()) { - - - // update the canvas texture unit state cache - cv.texUnitState[0].mirror = tus.mirror; - - tus.updateNative(-1, cv, false, startToSimulate); - - if (!startToSimulate) { - startToSimulate = true; - if (isFogEnabled) { - cv.setFogEnableFlag(cv.ctx, false); - } - } - - // turn on fog again in the last pass - - if (i == lastActiveTexUnitIndex && isFogEnabled) { - cv.setFogEnableFlag(cv.ctx, true); - } - renderList(cv, i, rlist); - } - } - - // adjust the depth test back to what it was - // and adjust the blend func to what it was - if (startToSimulate) { - cv.setStateToUpdate(Canvas3D.TRANSPARENCY_BIT); - } - } - - void changeLists(RenderMolecule r) { RenderMolecule renderMoleculeList, rmlist = null, head; HashMap allMap = null; @@ -1680,5 +1576,3 @@ class TextureBin extends Object implements ObjectUpdate { numEditingRenderMolecules++; } } - - diff --git a/src/classes/share/javax/media/j3d/TextureCubeMap.java b/src/classes/share/javax/media/j3d/TextureCubeMap.java index 9c6f608..f3facec 100644 --- a/src/classes/share/javax/media/j3d/TextureCubeMap.java +++ b/src/classes/share/javax/media/j3d/TextureCubeMap.java @@ -44,6 +44,8 @@ import javax.vecmath.*; */ public class TextureCubeMap extends Texture { + // TODO KCR : NPOT + /** * Specifies the face of the cube that is pierced by the positive x axis */ @@ -123,7 +125,7 @@ public class TextureCubeMap extends Texture { * @param format data format of Textures saved in this object. * One of INTENSITY, LUMINANCE, ALPHA, LUMINANCE_ALPHA, RGB, RGBA. * @param width width of image at level 0. Must be power of 2. - * @param boundaryWidth width of the boundary. + * @param boundaryWidth width of the boundary, which must be 0 or 1. * * @exception IllegalArgumentException if width is NOT * power of 2 OR invalid format/mipmapMode is specified. @@ -157,6 +159,12 @@ public class TextureCubeMap extends Texture { * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalSharingException if this TextureCubeMap is live and + * the specified image is being used by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this TextureCubeMap is + * being used by an immediate mode context and + * the specified image is being used by a Canvas3D as an off-screen buffer. */ public void setImage(int level, int face, ImageComponent2D image) { if (isLiveOrCompiled()) { @@ -164,7 +172,9 @@ public class TextureCubeMap extends Texture { throw new CapabilityNotSetException( J3dI18N.getString("TextureCubeMap1")); } - + + validateImageIllegalSharing(image); + if (isLive()) ((TextureCubeMapRetained)this.retained).setImage(level, face, image); else @@ -190,6 +200,14 @@ public class TextureCubeMap extends Texture { * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * + * @exception IllegalSharingException if this TextureCubeMap is live and + * any of the specified images are being used by a Canvas3D as an + * off-screen buffer. + * + * @exception IllegalSharingException if this TextureCubeMap is + * being used by an immediate mode context and + * any of the specified images are being used by a Canvas3D as an + * off-screen buffer. */ public void setImages(int face, ImageComponent2D[] images) { if (isLiveOrCompiled()) { @@ -198,6 +216,11 @@ public class TextureCubeMap extends Texture { J3dI18N.getString("TextureCubeMap1")); } + // Do illegal sharing check + for(int i=0; i<images.length; i++) { + validateImageIllegalSharing(images[i]); + } + if (isLive()) ((TextureCubeMapRetained)this.retained).setImages(face, images); else diff --git a/src/classes/share/javax/media/j3d/TextureCubeMapRetained.java b/src/classes/share/javax/media/j3d/TextureCubeMapRetained.java index b79f5a0..f5e683c 100644 --- a/src/classes/share/javax/media/j3d/TextureCubeMapRetained.java +++ b/src/classes/share/javax/media/j3d/TextureCubeMapRetained.java @@ -41,6 +41,10 @@ class TextureCubeMapRetained extends TextureRetained { * Sets a specified mipmap level for a particular face of the cubemap. */ void initImage(int level, int face, ImageComponent image) { + + // Issue 172 : call checkImageSize even for non-live setImage calls + checkImageSize(level, image); + if (this.images == null) { throw new IllegalArgumentException( J3dI18N.getString("TextureRetained0")); @@ -70,8 +74,10 @@ class TextureCubeMapRetained extends TextureRetained { } } - ((ImageComponent2DRetained)image.retained).setTextureRef(); - + /* Don't think this is needed. --- Chien. + ((ImageComponent2DRetained)image.retained).setTextureRef(); + */ + if (image != null) { this.images[face][level] = (ImageComponentRetained)image.retained; } else { @@ -81,8 +87,6 @@ class TextureCubeMapRetained extends TextureRetained { final void setImage(int level, int face, ImageComponent image) { - checkImageSize(level, image); - initImage(level, face, image); Object arg[] = new Object[3]; @@ -98,12 +102,12 @@ class TextureCubeMapRetained extends TextureRetained { if (image != null && level < maxLevels) { ImageComponentRetained img= (ImageComponentRetained)image.retained; if (img.isByReference()) { - if (img.bImage[0] == null) { + if (img.getRefImage(0) == null) { enable = false; } } else { - if (img.imageYup == null) { + if (img.getImageData(isUseAsRaster()).get() == null) { enable = false; } } @@ -126,14 +130,8 @@ class TextureCubeMapRetained extends TextureRetained { final void setImages(int face, ImageComponent[] images) { int i; - ImageComponentRetained[] imagesRet = - new ImageComponentRetained[images.length]; - for (i = 0; i < images.length; i++) { - imagesRet[i] = (ImageComponentRetained)images[i].retained; - } - checkSizes(imagesRet); - initImages(face, images); + initImages(face, images); ImageComponent [] imgs = new ImageComponent[images.length]; for (i = 0; i < images.length; i++) { @@ -154,12 +152,12 @@ class TextureCubeMapRetained extends TextureRetained { if (images[i] != null) { ImageComponentRetained img= (ImageComponentRetained)images[i].retained; if (img.isByReference()) { - if (img.bImage[0] == null) { + if (img.getRefImage(0) == null) { enable = false; } } else { - if (img.imageYup == null) { + if (img.getImageData(isUseAsRaster()).get() == null) { enable = false; } } @@ -221,42 +219,64 @@ class TextureCubeMapRetained extends TextureRetained { } - native void bindTexture(long ctx, int objectId, boolean enable); + void bindTexture(Context ctx, int objectId, boolean enable) { + Pipeline.getPipeline().bindTextureCubeMap(ctx, objectId, enable); + } - native void updateTextureFilterModes(long ctx, int minFilter, - int magFilter); + void updateTextureBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha) { - native void updateTextureBoundary(long ctx, - int boundaryModeS, int boundaryModeT, - float boundaryRed, float boundaryGreen, - float boundaryBlue, float boundaryAlpha); + Pipeline.getPipeline().updateTextureCubeMapBoundary(ctx, + boundaryModeS, boundaryModeT, + boundaryRed, boundaryGreen, + boundaryBlue, boundaryAlpha); + } - native void updateTextureSharpenFunc(long ctx, - int numSharpenTextureFuncPts, - float[] sharpenTextureFuncPts); + void updateTextureFilterModes(Context ctx, + int minFilter, int magFilter) { - native void updateTextureFilter4Func(long ctx, - int numFilter4FuncPts, - float[] filter4FuncPts); + Pipeline.getPipeline().updateTextureCubeMapFilterModes(ctx, + minFilter, magFilter); + } - native void updateTextureAnisotropicFilter(long ctx, float degree); + void updateTextureSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { - native void updateTextureImage(long ctx, - int face, - int numLevels, - int level, - int internalFormat, int format, - int width, int height, - int boundaryWidth, byte[] imageYup); + Pipeline.getPipeline().updateTextureCubeMapSharpenFunc(ctx, + numSharpenTextureFuncPts, sharpenTextureFuncPts); + } - native void updateTextureSubImage(long ctx, int face, - int level, int xoffset, int yoffset, - int internalFormat,int format, - int imgXOffset, int imgYOffset, - int tilew, - int width, int height, - byte[] image); - + void updateTextureFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { + + Pipeline.getPipeline().updateTextureCubeMapFilter4Func(ctx, + numFilter4FuncPts, filter4FuncPts); + } + + void updateTextureAnisotropicFilter(Context ctx, float degree) { + Pipeline.getPipeline().updateTextureCubeMapAnisotropicFilter(ctx, degree); + } + + + void updateTextureLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + + Pipeline.getPipeline().updateTextureCubeMapLodRange(ctx, baseLevel, maximumLevel, + minimumLod, maximumLod); + } + + void updateTextureLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + + Pipeline.getPipeline().updateTextureCubeMapLodOffset(ctx, + lodOffsetX, lodOffsetY, lodOffsetZ); + } /** @@ -264,38 +284,52 @@ class TextureCubeMapRetained extends TextureRetained { * mipmapping when level 0 is not the base level */ void updateTextureDimensions(Canvas3D cv) { - for (int i = 0; i < 6; i++) { - updateTextureImage(cv.ctx, i, maxLevels, 0, - format, ImageComponentRetained.BYTE_RGBA, - width, height, boundaryWidth, null); - } + if(images[0][0] != null) { + // All faces should have the same image format and type. + int imageFormat = images[0][0].getImageFormatTypeIntValue(false); + int imageType = images[0][0].getImageDataTypeIntValue(); + + for (int i = 0; i < 6; i++) { + updateTextureImage(cv, i, maxLevels, 0, + format, imageFormat, + width, height, boundaryWidth, + imageType, null); + } + } } // This is just a wrapper of the native method. - - void updateTextureImage(Canvas3D cv, int face, int numLevels, int level, - int format, int storedFormat, - int width, int height, - int boundaryWidth, byte[] data) { - - updateTextureImage(cv.ctx, face, numLevels, level, format, - storedFormat, width, height, - boundaryWidth, data); + void updateTextureImage(Canvas3D cv, + int face, int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, int imageDataType, + Object imageData) { + + Pipeline.getPipeline().updateTextureCubeMapImage(cv.ctx, + face, numLevels, level, + textureFormat, imageFormat, + width, height, + boundaryWidth, imageDataType, imageData); } - // This is just a wrapper of the native method. + void updateTextureSubImage(Canvas3D cv, + int face, int level, + int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object imageData) { + + Pipeline.getPipeline().updateTextureCubeMapSubImage(cv.ctx, + face, level, xoffset, yoffset, + textureFormat, imageFormat, + imgXOffset, imgYOffset, + tilew, width, height, + imageDataType, imageData); - void updateTextureSubImage(Canvas3D cv, int face, int level, - int xoffset, int yoffset, int format, - int storedFormat, int imgXOffset, - int imgYOffset, int tileWidth, - int width, int height, byte[] data) { - - updateTextureSubImage(cv.ctx, face, level, xoffset, yoffset, format, - storedFormat, imgXOffset, imgYOffset, - tileWidth, width, height, data); } } diff --git a/src/classes/share/javax/media/j3d/TextureRetained.java b/src/classes/share/javax/media/j3d/TextureRetained.java index bfeef5a..ec4de75 100644 --- a/src/classes/share/javax/media/j3d/TextureRetained.java +++ b/src/classes/share/javax/media/j3d/TextureRetained.java @@ -12,10 +12,10 @@ package javax.media.j3d; -import java.awt.image.BufferedImage; import java.util.*; import javax.vecmath.*; import java.awt.image.DataBufferByte; +import java.awt.image.RenderedImage; /** * The Texture object is a component object of an Appearance object @@ -85,6 +85,7 @@ abstract class TextureRetained extends NodeComponentRetained { float maximumLod = 1000.0f; Point3f lodOffset = null; + private boolean useAsRaster = false; // true if used by Raster or Background. // Texture mapping enable switch // This enable is derived from the user specified enable @@ -163,8 +164,8 @@ abstract class TextureRetained extends NodeComponentRetained { Object resourceLock = new Object(); - void initialize(int format, int width, int widPower, - int height, int heiPower, int mipmapMode, + void initialize(int format, int width, int widLevels, + int height, int heiLevels, int mipmapMode, int boundaryWidth) { this.mipmapMode = mipmapMode; @@ -176,10 +177,10 @@ abstract class TextureRetained extends NodeComponentRetained { // determine the maximum number of mipmap levels that can be // defined from the specified dimension - if (widPower > heiPower) { - maxMipMapLevels = widPower + 1; + if (widLevels > heiLevels) { + maxMipMapLevels = widLevels + 1; } else { - maxMipMapLevels = heiPower + 1; + maxMipMapLevels = heiLevels + 1; } @@ -331,6 +332,10 @@ abstract class TextureRetained extends NodeComponentRetained { * power of 2 OR invalid format/mipmapMode is specified. */ void initImage(int level, ImageComponent image) { + + // Issue 172 : call checkImageSize even for non-live setImage calls + checkImageSize(level, image); + if (this.images == null) { throw new IllegalArgumentException(J3dI18N.getString("TextureRetained0")); } @@ -359,12 +364,6 @@ abstract class TextureRetained extends NodeComponentRetained { } } - if (this instanceof Texture2DRetained) { - ((ImageComponent2DRetained)image.retained).setTextureRef(); - } else { - ((ImageComponent3DRetained)image.retained).setTextureRef(); - } - if (image != null) { this.images[0][level] = (ImageComponentRetained)image.retained; @@ -375,17 +374,21 @@ abstract class TextureRetained extends NodeComponentRetained { final void checkImageSize(int level, ImageComponent image) { if (image != null) { - int imgHeight = ((ImageComponentRetained)image.retained).height; int imgWidth = ((ImageComponentRetained)image.retained).width; - int i, tmp = 1; - // calculate tmp = 2**level - for (i=0; i < level; i++,tmp *= 2); + int imgHeight = ((ImageComponentRetained)image.retained).height; + + int wdh = width; + int hgt = height; + for (int i = 0; i < level; i++) { + wdh >>= 1; + hgt >>= 1; + } - int hgt = height/tmp, wdh = width / tmp; - if (hgt < 1) hgt = 1; if (wdh < 1) wdh = 1; + if (hgt < 1) hgt = 1; - if ((hgt != imgHeight) || (wdh != imgWidth)) { + if ((wdh != (imgWidth - 2*boundaryWidth)) || + (hgt != (imgHeight - 2*boundaryWidth))) { throw new IllegalArgumentException( J3dI18N.getString("TextureRetained1")); } @@ -393,36 +396,31 @@ abstract class TextureRetained extends NodeComponentRetained { } final void checkSizes(ImageComponentRetained images[]) { - // check that the image at each level is w/2 h/2 of the image at the - // previous level + // Issue 172 : this method is now redundant + + // Assertion check that the image at each level is the correct size + // This shouldn't be needed since we already should have checked the + // size at each level, and verified that all levels are set. if (images != null) { - - // only need to check if there is more than 1 level - if (images.length > 1) { - int compareW = images[0].width/2; - int compareH = images[0].height/2; - int w, h; - for (int i = 1; i < images.length; i++) { - w = images[i].width; - h = images[i].height; - if (compareW < 1) compareW = 1; - if (compareH < 1) compareH = 1; - if ((w != compareW) && (h != compareH)) { - throw new IllegalArgumentException( - J3dI18N.getString("TextureRetained1")); - } - compareW = w/2; - compareH = h/2; - } - } - } + int hgt = height; + int wdh = width; + for (int level = 0; level < images.length; level++) { + int imgWidth = images[level].width; + int imgHeight = images[level].height; + + assert (wdh == (imgWidth - 2*boundaryWidth)) && + (hgt == (imgHeight - 2*boundaryWidth)); + + wdh /= 2; + hgt /= 2; + if (wdh < 1) wdh = 1; + if (hgt < 1) hgt = 1; + } + } } final void setImage(int level, ImageComponent image) { - - checkImageSize(level, image); - - initImage(level, image); + initImage(level, image); Object arg[] = new Object[3]; arg[0] = new Integer(level); @@ -438,12 +436,12 @@ abstract class TextureRetained extends NodeComponentRetained { if (image != null && level >= baseLevel && level <= maximumLevel) { ImageComponentRetained img= (ImageComponentRetained)image.retained; if (img.isByReference()) { - if (img.bImage[0] == null) { + if (img.getRefImage(0) == null) { enable = false; } } else { - if (img.imageYup == null) { + if (img.getImageData(isUseAsRaster()).get() == null) { enable = false; } } @@ -466,14 +464,8 @@ abstract class TextureRetained extends NodeComponentRetained { final void setImages(ImageComponent[] images) { int i; - ImageComponentRetained[] imagesRet = - new ImageComponentRetained[images.length]; - for (i = 0; i < images.length; i++) { - imagesRet[i] = (ImageComponentRetained)images[i].retained; - } - checkSizes(imagesRet); - initImages(images); + initImages(images); ImageComponent [] imgs = new ImageComponent[images.length]; for (i = 0; i < images.length; i++) { @@ -496,12 +488,12 @@ abstract class TextureRetained extends NodeComponentRetained { ImageComponentRetained img= (ImageComponentRetained)images[i].retained; if (img.isByReference()) { - if (img.bImage[0] == null) { + if (img.getRefImage(0) == null) { enable = false; } } else { - if (img.imageYup == null) { + if (img.getImageData(isUseAsRaster()).get() == null) { enable = false; } } @@ -629,11 +621,11 @@ abstract class TextureRetained extends NodeComponentRetained { for (int j = 0; j < numFaces && enable; j++) { for (int i = baseLevel; i <= maximumLevel && enable; i++) { if (images[j][i].isByReference()) { - if (images[j][i].bImage[0] == null) { + if (images[j][i].getRefImage(0) == null) { enable = false; } } else { - if (images[j][i].imageYup == null) { + if (images[j][i].getImageData(isUseAsRaster()).get() == null) { enable = false; } } @@ -936,13 +928,6 @@ abstract class TextureRetained extends NodeComponentRetained { void setLive(boolean backgroundGroup, int refCount) { - // check the sizes of the images - if (images != null) { - for (int j = 0; j < numFaces; j++) { - checkSizes(images[j]); - } - } - // This line should be assigned before calling doSetLive, so that // the mirror object's enable is assigned correctly! enable = userSpecifiedEnable; @@ -967,8 +952,16 @@ abstract class TextureRetained extends NodeComponentRetained { } } + // Issue 172 : assertion check the sizes of the images after we have + // checked for all mipmap levels being set + if (images != null) { + for (int j = 0; j < numFaces; j++) { + checkSizes(images[j]); + } + } + // Send a message to Rendering Attr stucture to update the resourceMask - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.TEXTURE_CHANGED; createMessage.args[0] = this; @@ -984,11 +977,11 @@ abstract class TextureRetained extends NodeComponentRetained { for (int j = 0; j < numFaces && enable; j++) { for (int i = baseLevel; i <= maximumLevel && enable; i++){ if (images[j][i].isByReference()) { - if (images[j][i].bImage[0] == null) { + if (images[j][i].getRefImage(0) == null) { enable = false; } } else { - if (images[j][i].imageYup == null) { + if (images[j][i].getImageData(isUseAsRaster()).get() == null) { enable = false; } } @@ -1017,52 +1010,69 @@ abstract class TextureRetained extends NodeComponentRetained { } } - // Simply pass along to the NodeComponents - /** - * This method updates the native context. The implementation for 2D - * texture mapping happens here. Texture3D implements its own version - * of this. + /* + * The following methods update the native context. + * The implementation for Texture2D happens here. + * Texture3D and TextureCubeMap implement their own versions. */ - native void bindTexture(long ctx, int objectId, boolean enable); - native void updateTextureFilterModes(long ctx, - int minFilter, int magFilter); + void bindTexture(Context ctx, int objectId, boolean enable) { + Pipeline.getPipeline().bindTexture2D(ctx, objectId, enable); + } - native void updateTextureLodRange(long ctx, - int baseLevel, int maximumLevel, - float minimumLod, float maximumLod); + void updateTextureBoundary(Context ctx, + int boundaryModeS, int boundaryModeT, + float boundaryRed, float boundaryGreen, + float boundaryBlue, float boundaryAlpha) { - native void updateTextureLodOffset(long ctx, - float lodOffsetX, float lodOffsetY, - float lodOffsetZ); + Pipeline.getPipeline().updateTexture2DBoundary(ctx, + boundaryModeS, boundaryModeT, + boundaryRed, boundaryGreen, + boundaryBlue, boundaryAlpha); + } + void updateTextureFilterModes(Context ctx, + int minFilter, int magFilter) { - native void updateTextureBoundary(long ctx, - int boundaryModeS, int boundaryModeT, - float boundaryRed, float boundaryGreen, - float boundaryBlue, float boundaryAlpha); + Pipeline.getPipeline().updateTexture2DFilterModes(ctx, + minFilter, magFilter); + } - native void updateTextureSharpenFunc(long ctx, - int numSharpenTextureFuncPts, - float[] sharpenTextureFuncPts); + void updateTextureSharpenFunc(Context ctx, + int numSharpenTextureFuncPts, + float[] sharpenTextureFuncPts) { - native void updateTextureFilter4Func(long ctx, - int numFilter4FuncPts, - float[] filter4FuncPts); + Pipeline.getPipeline().updateTexture2DSharpenFunc(ctx, + numSharpenTextureFuncPts, sharpenTextureFuncPts); + } - native void updateTextureAnisotropicFilter(long ctx, float degree); + void updateTextureFilter4Func(Context ctx, + int numFilter4FuncPts, + float[] filter4FuncPts) { - native void updateTextureImage(long ctx, - int numLevels, int level, - int format, int storedFormat, - int width, int height, - int boundaryWidth, byte[] data); + Pipeline.getPipeline().updateTexture2DFilter4Func(ctx, + numFilter4FuncPts, filter4FuncPts); + } - native void updateTextureSubImage(long ctx, int level, - int xoffset, int yoffset, int format, - int storedFormat, int imgXOffset, - int imgYOffset, int tileWidth, - int width, int height, byte[] data); + void updateTextureAnisotropicFilter(Context ctx, float degree) { + Pipeline.getPipeline().updateTexture2DAnisotropicFilter(ctx, degree); + } + + void updateTextureLodRange(Context ctx, + int baseLevel, int maximumLevel, + float minimumLod, float maximumLod) { + + Pipeline.getPipeline().updateTexture2DLodRange(ctx, baseLevel, maximumLevel, + minimumLod, maximumLod); + } + + void updateTextureLodOffset(Context ctx, + float lodOffsetX, float lodOffsetY, + float lodOffsetZ) { + + Pipeline.getPipeline().updateTexture2DLodOffset(ctx, + lodOffsetX, lodOffsetY, lodOffsetZ); + } // get an ID for Texture 2D @@ -1100,23 +1110,26 @@ abstract class TextureRetained extends NodeComponentRetained { * mipmapping when level 0 is not the base level */ void updateTextureDimensions(Canvas3D cv) { - updateTextureImage(cv.ctx, maxLevels, 0, - format, ImageComponentRetained.BYTE_RGBA, - width, height, boundaryWidth, null); + if(images[0][0] != null) { + updateTextureImage(cv, 0, maxLevels, 0, + format, images[0][0].getImageFormatTypeIntValue(false), + width, height, boundaryWidth, + images[0][0].getImageDataTypeIntValue(), null); + } } - + void updateTextureLOD(Canvas3D cv) { if ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_LOD_RANGE) != 0 ) { - updateTextureLodRange(cv.ctx, baseLevel, maximumLevel, - minimumLod, maximumLod); + updateTextureLodRange(cv.ctx, baseLevel, maximumLevel, + minimumLod, maximumLod); } - if ((lodOffset != null) && - ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_LOD_OFFSET) != 0)) { - updateTextureLodOffset(cv.ctx, - lodOffset.x, lodOffset.y, lodOffset.z); + if ((lodOffset != null) && + ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_LOD_OFFSET) != 0)) { + updateTextureLodOffset(cv.ctx, + lodOffset.x, lodOffset.y, lodOffset.z); } } @@ -1218,38 +1231,40 @@ abstract class TextureRetained extends NodeComponentRetained { } - - // wrapper of the native call - - void updateTextureImage(Canvas3D cv, int face, - int numLevels, int level, - int format, int storedFormat, - int width, int height, - int boundaryWidth, byte[] data) { - - updateTextureImage(cv.ctx, maxLevels, level, - format, storedFormat, - width, height, boundaryWidth, data); - } - - - - // wrapper of the native call - - void updateTextureSubImage(Canvas3D cv, int face, int level, - int xoffset, int yoffset, int format, - int storedFormat, int imgXOffset, - int imgYOffset, int tileWidth, - int width, int height, byte[] data) { - - updateTextureSubImage(cv.ctx, level, - xoffset, yoffset, format, - storedFormat, imgXOffset, - imgYOffset, tileWidth, - width, height, data); + // Wrapper around the native call for 2D textures; overridden for + // Texture3D and TextureCureMap + void updateTextureImage(Canvas3D cv, + int face, int numLevels, int level, + int textureFormat, int imageFormat, + int width, int height, + int boundaryWidth, + int imageDataType, Object data) { + + Pipeline.getPipeline().updateTexture2DImage(cv.ctx, + numLevels, level, + textureFormat, imageFormat, + width, height, boundaryWidth, + imageDataType, data); + } + + // Wrapper around the native call for 2D textures; overridden for + // Texture3D and TextureCureMap + void updateTextureSubImage(Canvas3D cv, + int face, int level, + int xoffset, int yoffset, + int textureFormat, int imageFormat, + int imgXOffset, int imgYOffset, + int tilew, int width, int height, + int imageDataType, Object data) { + + Pipeline.getPipeline().updateTexture2DSubImage(cv.ctx, + level, xoffset, yoffset, + textureFormat, imageFormat, + imgXOffset, imgYOffset, + tilew, width, height, + imageDataType, data); } - - + /** * reloadTextureImage is used to load a particular level of image @@ -1257,33 +1272,31 @@ abstract class TextureRetained extends NodeComponentRetained { * BufferedImage */ void reloadTextureImage(Canvas3D cv, int face, int level, - ImageComponentRetained image, int numLevels) { - - //System.out.println("Texture.reloadTextureImage: face= " + face + " level= " + level); - - //System.out.println("...image = "+image+" image.storedFormat = "+image.storedYupFormat+" image.imageYup = "+image.imageYup+" texture - "+this); - - //System.out.println("....imageYupAllocated= " + image.imageYupAllocated); - - updateTextureImage(cv, face, numLevels, level, format, - image.storedYupFormat, - image.width, image.height, - boundaryWidth, image.imageYup); - - // Now take care of the RenderedImage case. Note, if image - // is a RenderedImage, then imageYup will be null - - if (image.imageYupClass == ImageComponentRetained.RENDERED_IMAGE) { - - // System.out.println("==========. subImage"); + ImageComponentRetained image, int numLevels) { + + boolean useAsRaster = isUseAsRaster(); + ImageComponentRetained.ImageData imageData = image.getImageData(useAsRaster); + + updateTextureImage(cv, + face, numLevels, level, + format, image.getImageFormatTypeIntValue(useAsRaster), + imageData.getWidth(), imageData.getHeight(), + boundaryWidth, image.getImageDataTypeIntValue(), + imageData.get()); + + // Now take care of the RenderedImage (byRef and yUp) case. Note, if image + // is a RenderedImage ( byRef and yUp), then imageData will be null + + if (imageData == null) { + // System.out.println("==========. subImage"); // Download all the tiles for this texture int xoffset = 0, yoffset = 0; int tmpw = image.width; int tmph = image.height; - int endXTile = image.minTileX * image.tilew + image.tileGridXOffset+image.tilew; - int endYTile = image.minTileY * image.tileh + image.tileGridYOffset+image.tileh; - int curw = (endXTile - image.minX); - int curh = (endYTile - image.minY); + int endXTile = image.tilew; + int endYTile = image.tileh; + int curw = endXTile; + int curh = endYTile; if (tmpw < curw) { curw = tmpw; @@ -1296,23 +1309,23 @@ abstract class TextureRetained extends NodeComponentRetained { int startw = curw; int imageXOffset = image.tilew - curw; int imageYOffset = image.tileh - curh; - for (int m = image.minTileY; m < image.minTileY+image.numYTiles; m++) { + for (int m = 0; m < image.numYTiles; m++) { xoffset = 0; tmpw = width; curw = startw; imageXOffset = image.tilew - curw; - for (int n = image.minTileX; - n < image.minTileX+image.numXTiles; n++) { + for (int n = 0; n < image.numXTiles; n++) { java.awt.image.Raster ras; - ras = image.bImage[0].getTile(n,m); - byte[] tmpImage = ((DataBufferByte)ras.getDataBuffer()).getData(); - updateTextureSubImage(cv, face, - level, xoffset, yoffset, format, - image.storedYupFormat, - imageXOffset, imageYOffset, - image.tilew, - curw, curh, - tmpImage); + ras = ((RenderedImage)image.getRefImage(0)).getTile(n,m); + byte[] data = ((DataBufferByte)ras.getDataBuffer()).getData(); + updateTextureSubImage(cv, face, + level, xoffset, yoffset, format, + image.getImageFormatTypeIntValue(false), + imageXOffset, imageYOffset, + image.tilew, + curw, curh, + ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY, + (Object) data); xoffset += curw; imageXOffset = 0; tmpw -= curw; @@ -1354,57 +1367,43 @@ abstract class TextureRetained extends NodeComponentRetained { // " width= " + width + " height= " + height + // " format= " + format); - - if (image.imageYupClass == ImageComponentRetained.BUFFERED_IMAGE) { - - int xoffset = x - image.minX; - int yoffset = y - image.minY; - - byte[] imageData; - if (image.imageYupAllocated) { - imageData = image.imageYup; - yoffset = image.height - yoffset - height; - - } else { - // Fix issue 132 - imageData = ((DataBufferByte) - ((BufferedImage)image.bImage[0]).getRaster().getDataBuffer()).getData(); - - // based on the yUp flag in the associated ImageComponent, - // adjust the yoffset - - if (!image.yUp) { - yoffset = image.height - yoffset - height; - } - } - - updateTextureSubImage(cv, face, level, - xoffset, yoffset, - format, image.storedYupFormat, - xoffset, yoffset, - image.width, width, height, imageData); - } else { + ImageComponentRetained.ImageData imageData = image.getImageData(isUseAsRaster()); + if(imageData != null) { + int xoffset = x; + int yoffset = y; + + // TODO Check this logic : If !yUp adjust yoffset --- Chien + if (!image.yUp) { + yoffset = image.height - yoffset - height; + } + + updateTextureSubImage(cv, face, level, + xoffset, yoffset, + format, image.getImageFormatTypeIntValue(false), + xoffset, yoffset, + image.width, width, height, + image.getImageDataTypeIntValue(), + imageData.get()); + + } else { // System.out.println("RenderedImage subImage update"); - // determine the first tile of the image float mt; - int xoff = image.tileGridXOffset; - int yoff = image.tileGridYOffset; int minTileX, minTileY; - int rx = x + image.minX; // x offset in RenderedImage - int ry = y + image.minY; // y offset in RenderedImage + int rx = x; + int ry = y; - mt = (float)(rx - xoff) / (float)image.tilew; + mt = (float)(rx) / (float)image.tilew; if (mt < 0) { minTileX = (int)(mt - 1); } else { minTileX = (int)mt; } - mt = (float)(ry - yoff) / (float)image.tileh; + mt = (float)(ry) / (float)image.tileh; if (mt < 0) { minTileY = (int)(mt - 1); } else { @@ -1413,8 +1412,8 @@ abstract class TextureRetained extends NodeComponentRetained { // determine the pixel offset of the upper-left corner of the // first tile - int startXTile = minTileX * image.tilew + xoff; - int startYTile = minTileY * image.tilew + yoff; + int startXTile = minTileX * image.tilew; + int startYTile = minTileY * image.tilew; // image dimension in the first tile @@ -1466,7 +1465,6 @@ abstract class TextureRetained extends NodeComponentRetained { } java.awt.image.Raster ras; - byte[] imageData; int textureX = x; // x offset in the texture int textureY = y; // y offset in the texture @@ -1480,14 +1478,16 @@ abstract class TextureRetained extends NodeComponentRetained { for (int xTile = minTileX; xTile < minTileX + numXTiles; xTile++) { - ras = image.bImage[0].getTile(xTile, yTile); - imageData = ((DataBufferByte)ras.getDataBuffer()).getData(); - - updateTextureSubImage(cv, face, level, - textureX, textureY, - format, image.storedYupFormat, - imgX, imgY, image.tilew, curw, curh, imageData); + ras = ((RenderedImage)image.getRefImage(0)).getTile(xTile, yTile); + byte[] data = ((DataBufferByte)ras.getDataBuffer()).getData(); + updateTextureSubImage(cv, face, level, + textureX, textureY, + format, image.getImageFormatTypeIntValue(false), + imgX, imgY, + image.tilew, curw, curh, + ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY, + (Object)data); // move to the next tile in x direction @@ -1690,7 +1690,7 @@ abstract class TextureRetained extends NodeComponentRetained { return; } - if (cv.useSharedCtx && cv.screen.renderer.sharedCtx != 0) { + if (cv.useSharedCtx && cv.screen.renderer.sharedCtx != null) { if ((resourceCreationMask & cv.screen.renderer.rendererBit) == 0) { reloadTexture = true; @@ -1845,7 +1845,7 @@ abstract class TextureRetained extends NodeComponentRetained { width, height, boundaryWidth); - mirror = (Texture2DRetained)tex.retained;; + mirror = (Texture2DRetained)tex.retained; } ((TextureRetained)mirror).objectId = -1; @@ -1950,9 +1950,9 @@ abstract class TextureRetained extends NodeComponentRetained { images[j][0].addUser(mirrorTexture); } - for (int i = 1; i < mirrorTexture.maxLevels; i++) { - mirrorTexture.images[j][i] = createNextLevelImage( - (mirrorTexture.images[j][i-1])); + for (int i = 1; i < mirrorTexture.maxLevels; i++) { + mirrorTexture.images[j][i] = + mirrorTexture.images[j][i-1].createNextLevelMipMapImage(); } } } @@ -1995,7 +1995,6 @@ abstract class TextureRetained extends NodeComponentRetained { if (info.updateMask == 0) { // this update info is done, remove it // from the update list - VirtualUniverse.mc.addFreeImageUpdateInfo(info); imageUpdateInfo[k][i].remove(j); } } @@ -2025,8 +2024,7 @@ abstract class TextureRetained extends NodeComponentRetained { imageUpdateInfo[face][level] = new ArrayList(); } - //info = mirrorTa.getFreeImageUpdateInfo(); - info = VirtualUniverse.mc.getFreeImageUpdateInfo(); + info = new ImageComponentUpdateInfo(); if (arg == null) { @@ -2045,8 +2043,6 @@ abstract class TextureRetained extends NodeComponentRetained { if (info.entireImage) { // the entire image update supercedes all the subimage update; // hence, remove all the existing updates from the list - VirtualUniverse.mc.addFreeImageUpdateInfo( - imageUpdateInfo[face][level]); imageUpdateInfo[face][level].clear(); // reset the update prune mask for this level @@ -2308,8 +2304,6 @@ abstract class TextureRetained extends NodeComponentRetained { for (int face = 0; face < numFaces; face++) { for (int level = 0; level < maxLevels; level++) { if (imageUpdateInfo[face][level] != null) { - VirtualUniverse.mc.addFreeImageUpdateInfo( - imageUpdateInfo[face][level]); imageUpdateInfo[face][level].clear(); } } @@ -2358,110 +2352,6 @@ abstract class TextureRetained extends NodeComponentRetained { resourceCreationMask = 0x0; } - final ImageComponentRetained createNextLevelImage( - ImageComponentRetained oImage) { - - int xScale, yScale, nWidth, nHeight; - ImageComponentRetained nImage = null; - - if (oImage.width > 1) { - nWidth = oImage.width >> 1; - xScale = 2; - } else { - nWidth = 1; - xScale = 1; - } - if (oImage.height > 1) { - nHeight = oImage.height >> 1; - yScale = 2; - } else { - nHeight = 1; - yScale = 1; - } - - int bytesPerPixel = oImage.bytesPerYupPixelStored; - - if (oImage instanceof ImageComponent2DRetained) { - - nImage = new ImageComponent2DRetained(); - nImage.processParams(oImage.format, nWidth, nHeight, 1); - nImage.imageYup = new byte[nWidth * nHeight * bytesPerPixel]; - nImage.storedYupFormat = nImage.internalFormat; - nImage.bytesPerYupPixelStored = bytesPerPixel; - scaleImage(nWidth, nHeight, xScale, yScale, oImage.width, 0, 0, - bytesPerPixel, nImage.imageYup, oImage.imageYup); - - } else { //oImage instanceof ImageComponent3DRetained - - int depth = ((ImageComponent3DRetained)oImage).depth; - nImage = new ImageComponent3DRetained(); - nImage.processParams(oImage.format, nWidth, nHeight, depth); - nImage.imageYup = new byte[nWidth * nHeight * bytesPerPixel]; - nImage.storedYupFormat = nImage.internalFormat; - nImage.bytesPerYupPixelStored = bytesPerPixel; - - for (int i = 0; i < depth; i++) { - scaleImage(nWidth, nHeight, xScale, yScale, oImage.width, - i * nWidth * nHeight * bytesPerPixel, - i * oImage.width * oImage.height * bytesPerPixel, - bytesPerPixel, nImage.imageYup, oImage.imageYup); - } - } - return nImage; - } - - final void scaleImage(int nWidth, int nHeight, int xScale, int yScale, - int oWidth, int nStart, int oStart, int bytesPerPixel, - byte[] nData, byte[] oData) { - - int nOffset = 0; - int oOffset = 0; - int oLineIncr = bytesPerPixel * oWidth; - int oPixelIncr = bytesPerPixel << 1; - - if (yScale == 1) { - for (int x = 0; x < nWidth; x++) { - for (int k = 0; k < bytesPerPixel; k++) { - nData[nStart + nOffset + k] = (byte) - (((int)(oData[oStart + oOffset + k] & 0xff) + - (int)(oData[oStart + oOffset + k - + bytesPerPixel] & 0xff) + 1) >> 1); - } - nOffset += bytesPerPixel; - oOffset += oPixelIncr; - } - } else if (xScale == 1) { - for (int y = 0; y < nHeight; y++) { - for (int k = 0; k < bytesPerPixel; k++) { - nData[nStart + nOffset + k] = (byte) - (((int)(oData[oStart + oOffset + k] & 0xff) + - (int)(oData[oStart + oOffset + k - + oLineIncr] & 0xff) + 1) >> 1); - } - nOffset += bytesPerPixel; - oOffset += oLineIncr; - } - } else { - for (int y = 0; y < nHeight; y++) { - for (int x = 0; x < nWidth; x++) { - for (int k = 0; k < bytesPerPixel; k++) { - nData[nStart + nOffset + k] = (byte) - (((int)(oData[oStart + oOffset + k] & 0xff) + - (int)(oData[oStart + oOffset + k - + bytesPerPixel] & 0xff) + - (int)(oData[oStart + oOffset + k - + oLineIncr] & 0xff) + - (int)(oData[oStart + oOffset + k + oLineIncr + - + bytesPerPixel] & 0xff) + 2) >> 2); - } - nOffset += bytesPerPixel; - oOffset += oPixelIncr; - } - oOffset += oLineIncr; - } - } - } - void incTextureBinRefCount(TextureBin tb) { ImageComponentRetained image; @@ -2523,7 +2413,7 @@ abstract class TextureRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.TEXTURE_CHANGED; createMessage.universe = null; @@ -2535,7 +2425,7 @@ abstract class TextureRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.TEXTURE_CHANGED; @@ -2554,35 +2444,6 @@ abstract class TextureRetained extends NodeComponentRetained { } - protected void finalize() { - - if (objectId > 0) { - // memory not yet free - // send a message to the request renderer - synchronized (VirtualUniverse.mc.contextCreationLock) { - boolean found = false; - - for (Enumeration e = Screen3D.deviceRendererMap.elements(); - e.hasMoreElements(); ) { - Renderer rdr = (Renderer) e.nextElement(); - J3dMessage renderMessage = VirtualUniverse.mc.getMessage(); - renderMessage.threads = J3dThread.RENDER_THREAD; - renderMessage.type = J3dMessage.RENDER_IMMEDIATE; - renderMessage.universe = null; - renderMessage.view = null; - renderMessage.args[0] = null; - renderMessage.args[1] = new Integer(objectId); - renderMessage.args[2] = "2D"; - rdr.rendererStructure.addMessage(renderMessage); - } - objectId = -1; - } - - VirtualUniverse.mc.setWorkForRequestRenderer(); - } - - } - void handleFrequencyChange(int bit) { switch (bit) { case Texture.ALLOW_ENABLE_WRITE: @@ -2594,5 +2455,13 @@ abstract class TextureRetained extends NodeComponentRetained { break; } } -} + + void setUseAsRaster(boolean useAsRaster) { + this.useAsRaster = useAsRaster; + } + + boolean isUseAsRaster() { + return this.useAsRaster; + } +} diff --git a/src/classes/share/javax/media/j3d/TextureUnitState.java b/src/classes/share/javax/media/j3d/TextureUnitState.java index ced1e88..162a301 100644 --- a/src/classes/share/javax/media/j3d/TextureUnitState.java +++ b/src/classes/share/javax/media/j3d/TextureUnitState.java @@ -126,6 +126,15 @@ public class TextureUnitState extends NodeComponent { * texture attributes * @param texCoordGeneration object that specifies the texture coordinate * generation parameters + * + * @exception IllegalSharingException if this TextureUnitState is live and + * the specified texture refers to an ImageComponent2D that is being used + * by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this TextureUnitState is + * being used by an immediate mode context and + * the specified texture refers to an ImageComponent2D that is being used + * by a Canvas3D as an off-screen buffer. */ public void set(Texture texture, TextureAttributes textureAttributes, @@ -135,6 +144,17 @@ public class TextureUnitState extends NodeComponent { if (!this.getCapability(ALLOW_STATE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState0")); + // Do illegal sharing check + if(texture != null) { + TextureRetained texRetained = (TextureRetained)texture.retained; + ImageComponent[] images = texRetained.getImages(); + if(images != null) { + for(int i=0; i<images.length; i++) { + validateImageIllegalSharing(images[i]); + } + } + } + ((TextureUnitStateRetained)this.retained).setTextureUnitState( texture, textureAttributes, texCoordGeneration); } @@ -143,16 +163,38 @@ public class TextureUnitState extends NodeComponent { * Sets the texture object to the specified object. * Setting it to null disables texture mapping for the * texture unit corresponding to this TextureUnitState object. + * * @param texture object that specifies the desired texture * map and texture parameters + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * + * @exception IllegalSharingException if this TextureUnitState is live and + * the specified texture refers to an ImageComponent2D that is being used + * by a Canvas3D as an off-screen buffer. + * + * @exception IllegalSharingException if this TextureUnitState is + * being used by an immediate mode context and + * the specified texture refers to an ImageComponent2D that is being used + * by a Canvas3D as an off-screen buffer. */ public void setTexture(Texture texture) { if (isLiveOrCompiled()) if (!this.getCapability(ALLOW_STATE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState0")); + // Do illegal sharing check + if(texture != null) { + TextureRetained texRetained = (TextureRetained)texture.retained; + ImageComponent[] images = texRetained.getImages(); + if(images != null) { + for(int i=0; i<images.length; i++) { + validateImageIllegalSharing(images[i]); + } + } + } + ((TextureUnitStateRetained)this.retained).setTexture(texture); } diff --git a/src/classes/share/javax/media/j3d/TextureUnitStateRetained.java b/src/classes/share/javax/media/j3d/TextureUnitStateRetained.java index ffadb2a..ccc87c8 100644 --- a/src/classes/share/javax/media/j3d/TextureUnitStateRetained.java +++ b/src/classes/share/javax/media/j3d/TextureUnitStateRetained.java @@ -142,8 +142,6 @@ class TextureUnitStateRetained extends NodeComponentRetained { return (texGen == null ? null : (TexCoordGeneration)texGen.source); } - native void updateTextureUnitState(long ctx, int unitIndex, boolean enableFlag); - void updateNative(int unitIndex, Canvas3D cv, boolean reload, boolean simulate) { @@ -176,7 +174,7 @@ class TextureUnitStateRetained extends NodeComponentRetained { return; } else { - updateTextureUnitState(cv.ctx, unitIndex, true); + Pipeline.getPipeline().updateTextureUnitState(cv.ctx, unitIndex, true); } // reload is needed in a multi-texture case to bind the @@ -499,9 +497,8 @@ class TextureUnitStateRetained extends NodeComponentRetained { ((texGen == null) || (texGen.isStatic()))); } - /* + // Issue 209 - enable this method (was previously commented out) // Simply pass along to the NodeComponent - void compile (CompileState compState) { setCompiled(); @@ -512,7 +509,6 @@ class TextureUnitStateRetained extends NodeComponentRetained { if (texGen != null) texGen.compile(compState); } - */ boolean equals(TextureUnitStateRetained ts) { return ((ts == this) || @@ -557,7 +553,7 @@ class TextureUnitStateRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.TEXTURE_UNIT_STATE_CHANGED; createMessage.universe = null; @@ -569,7 +565,7 @@ class TextureUnitStateRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.TEXTURE_UNIT_STATE_CHANGED; diff --git a/src/classes/share/javax/media/j3d/TimerThread.java b/src/classes/share/javax/media/j3d/TimerThread.java index c3dd474..657e900 100644 --- a/src/classes/share/javax/media/j3d/TimerThread.java +++ b/src/classes/share/javax/media/j3d/TimerThread.java @@ -38,8 +38,9 @@ class TimerThread extends Thread { private WakeupOnElapsedTime soundSchedCond = new WakeupOnElapsedTime(120000); // every 2 minutes - private boolean running = true; - private volatile boolean waiting = false; + private volatile boolean running = true; + private boolean waiting = false; + private boolean ready = false; TimerThread(ThreadGroup t) { super(t, "J3D-TimerThread"); @@ -119,20 +120,27 @@ class TimerThread extends Thread { synchronized void runMonitor(int action, long waitTime) { switch (action) { case WAIT: - try { - if (running) { - waiting = true; - if (waitTime < 0) { - wait(); - } else { - wait(waitTime); - } - } - } catch (InterruptedException e) {} - waiting = false; - break; + // Issue 308 - wait unless ready flag already set + // Note that we can't loop since we need to be able to timeout + // after "waitTime" msec + if (running && !ready) { + waiting = true; + try { + if (waitTime < 0) { + wait(); + } else { + wait(waitTime); + } + } catch (InterruptedException e) {} + waiting = false; + } + ready = false; + break; case NOTIFY: - notify(); + ready = true; + if (waiting) { + notify(); + } break; case STOP: running = false; diff --git a/src/classes/share/javax/media/j3d/Transform3D.java b/src/classes/share/javax/media/j3d/Transform3D.java index 386c03d..e36672a 100644 --- a/src/classes/share/javax/media/j3d/Transform3D.java +++ b/src/classes/share/javax/media/j3d/Transform3D.java @@ -117,6 +117,8 @@ public class Transform3D { private static final int ROTSCALESVD_DIRTY = SCALE_BIT | ROTATION_BIT | SVD_BIT; + private static final int ALL_DIRTY = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + private int dirtyBits; boolean autoNormalize = false; // Don't auto normalize by default @@ -541,6 +543,27 @@ public class Transform3D { return this.autoNormalize; } + /** + * Transforms the point parameter with this transform and + * places the result into pointOut. The fourth element of the + * point input paramter is assumed to be one. + * @param point the input point to be transformed + * @param pointOut the transformed point + */ + void transform(Point3d point, Point4d pointOut) { + + pointOut.x = mat[0]*point.x + mat[1]*point.y + + mat[2]*point.z + mat[3]; + pointOut.y = mat[4]*point.x + mat[5]*point.y + + mat[6]*point.z + mat[7]; + pointOut.z = mat[8]*point.x + mat[9]*point.y + + mat[10]*point.z + mat[11]; + pointOut.w = mat[12]*point.x + mat[13]*point.y + + mat[14]*point.z + mat[15]; + } + + + private static final boolean almostZero(double a) { return ((a < EPSILON_ABSOLUTE) && (a > -EPSILON_ABSOLUTE)); } @@ -576,17 +599,6 @@ public class Transform3D { } } - // Fix for Issue 167 -- don't classify matrices with Infinity or NaN values - // as affine - private final boolean isInfOrNaN() { - for (int i = 0; i < 16; i++) { - if (Double.isNaN(mat[i]) || Double.isInfinite(mat[i])) { - return true; - } - } - return false; - } - private final void classifyAffine() { if (!isInfOrNaN() && almostZero(mat[12]) && @@ -774,7 +786,7 @@ public class Transform3D { mat[i] += t1.mat[i]; } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -792,7 +804,7 @@ public class Transform3D { mat[i] = t1.mat[i] + t2.mat[i]; } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -810,7 +822,7 @@ public class Transform3D { mat[i] -= t1.mat[i]; } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -829,7 +841,7 @@ public class Transform3D { mat[i] = t1.mat[i] - t2.mat[i]; } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -868,7 +880,7 @@ public class Transform3D { mat[14] = mat[11]; mat[11] = temp; - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -900,7 +912,7 @@ public class Transform3D { mat[14] = t1.mat[11]; mat[15] = t1.mat[15]; - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -940,6 +952,11 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(q1)) { + dirtyBits = ALL_DIRTY; + return; + } dirtyBits = CLASSIFY_BIT | SCALE_BIT | ROTATION_BIT; type = RIGID | CONGRUENT | AFFINE | ORTHO; @@ -974,6 +991,12 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(q1)) { + dirtyBits = ALL_DIRTY; + return; + } + dirtyBits = CLASSIFY_BIT | SCALE_BIT | ROTATION_BIT; type = RIGID | CONGRUENT | AFFINE | ORTHO; } @@ -1002,11 +1025,8 @@ public class Transform3D { mat[9] = m1.m21*scales[1]; mat[10]= m1.m22*scales[2]; - // only affine bit is preserved - // SCALE_BIT is clear in the above computeScales() so - // there is no need to set it dirty again. - dirtyBits |= (RIGID_BIT | CONGRUENT_BIT| ORTHO_BIT| - CLASSIFY_BIT | ROTSCALESVD_DIRTY); + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; if (autoNormalize) { // the matrix pass in may not normalize @@ -1038,8 +1058,8 @@ public class Transform3D { mat[9] = m1.m21*scales[1]; mat[10]= m1.m22*scales[2]; - dirtyBits |= (RIGID_BIT | CONGRUENT_BIT| ORTHO_BIT| - CLASSIFY_BIT | ROTSCALESVD_DIRTY); + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -1072,7 +1092,13 @@ public class Transform3D { mat[6] = (2.0*(q1.y*q1.z - q1.w*q1.x))*scales[2]; mat[10] = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y)*scales[2]; - dirtyBits |= CLASSIFY_BIT | ROTATION_BIT; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(q1)) { + dirtyBits = ALL_DIRTY; + return; + } + + dirtyBits |= CLASSIFY_BIT | ROTATION_BIT; dirtyBits &= ~ORTHO_BIT; type |= ORTHO; type &= ~(ORTHOGONAL|IDENTITY|SCALE|TRANSLATION|SCALE|ZERO); @@ -1104,10 +1130,16 @@ public class Transform3D { mat[6] = (2.0*(q1.y*q1.z - q1.w*q1.x))*scales[2]; mat[10] = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y)*scales[2]; - dirtyBits |= CLASSIFY_BIT | ROTATION_BIT; - dirtyBits &= ~ORTHO_BIT; - type |= ORTHO; - type &= ~(ORTHOGONAL|IDENTITY|SCALE|TRANSLATION|SCALE|ZERO); + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(q1)) { + dirtyBits = ALL_DIRTY; + return; + } + + dirtyBits |= CLASSIFY_BIT | ROTATION_BIT; + dirtyBits &= ~ORTHO_BIT; + type |= ORTHO; + type &= ~(ORTHOGONAL|IDENTITY|SCALE|TRANSLATION|SCALE|ZERO); } @@ -1157,7 +1189,13 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; - type = CONGRUENT | AFFINE | RIGID | ORTHO; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(a1)) { + dirtyBits = ALL_DIRTY; + return; + } + + type = CONGRUENT | AFFINE | RIGID | ORTHO; dirtyBits = CLASSIFY_BIT | ROTATION_BIT | SCALE_BIT; } } @@ -1209,6 +1247,12 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(a1)) { + dirtyBits = ALL_DIRTY; + return; + } + type = CONGRUENT | AFFINE | RIGID | ORTHO; dirtyBits = CLASSIFY_BIT | ROTATION_BIT | SCALE_BIT; } @@ -1267,6 +1311,11 @@ public class Transform3D { mat[10] = (t * az * az + cosTheta)*scales[2]; } + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(a1)) { + dirtyBits = ALL_DIRTY; + return; + } // Rigid remain rigid, congruent remain congruent after // set rotation @@ -1329,6 +1378,11 @@ public class Transform3D { mat[10] = (t * az * az + cosTheta)*scales[2]; } + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(a1)) { + dirtyBits = ALL_DIRTY; + return; + } // Rigid remain rigid, congruent remain congruent after // set rotation @@ -1369,6 +1423,12 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(angle)) { + dirtyBits = ALL_DIRTY; + return; + } + type = CONGRUENT | AFFINE | RIGID | ORTHO; dirtyBits = CLASSIFY_BIT | ROTATION_BIT | SCALE_BIT; } @@ -1403,6 +1463,12 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(angle)) { + dirtyBits = ALL_DIRTY; + return; + } + type = CONGRUENT | AFFINE | RIGID | ORTHO; dirtyBits = CLASSIFY_BIT | ROTATION_BIT | SCALE_BIT; } @@ -1438,6 +1504,12 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(angle)) { + dirtyBits = ALL_DIRTY; + return; + } + type = CONGRUENT | AFFINE | RIGID | ORTHO; dirtyBits = CLASSIFY_BIT | ROTATION_BIT | SCALE_BIT; } @@ -1455,6 +1527,12 @@ public class Transform3D { mat[8] = 0.0; mat[9] = 0.0; mat[10] = 1.0; mat[11] = trans.z; mat[12] = 0.0; mat[13] = 0.0; mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(trans)) { + dirtyBits = ALL_DIRTY; + return; + } + type = CONGRUENT | AFFINE | RIGID | ORTHO; dirtyBits = CLASSIFY_BIT | ROTATION_BIT | SCALE_BIT; } @@ -1471,6 +1549,11 @@ public class Transform3D { mat[8] = 0.0; mat[9] = 0.0; mat[10] = 1.0; mat[11] = trans.z; mat[12] = 0.0; mat[13] = 0.0; mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(trans)) { + dirtyBits = ALL_DIRTY; + return; + } type = CONGRUENT | AFFINE | RIGID | ORTHO; dirtyBits = CLASSIFY_BIT | ROTATION_BIT | SCALE_BIT; @@ -1498,6 +1581,12 @@ public class Transform3D { mat[9] = rot[7]*scale; mat[10] = rot[8]*scale; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(scale)) { + dirtyBits = ALL_DIRTY; + return; + } + dirtyBits |= (CLASSIFY_BIT | RIGID_BIT | CONGRUENT_BIT | SVD_BIT); dirtyBits &= ~SCALE_BIT; } @@ -1528,6 +1617,13 @@ public class Transform3D { mat[8] = rot[6]*scale.x; mat[9] = rot[7]*scale.y; mat[10] = rot[8]*scale.z; + + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(scale)) { + dirtyBits = ALL_DIRTY; + return; + } + dirtyBits |= (CLASSIFY_BIT | RIGID_BIT | CONGRUENT_BIT | SVD_BIT); dirtyBits &= ~SCALE_BIT; } @@ -1568,9 +1664,8 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; - type = AFFINE | ORTHO; - dirtyBits = CLASSIFY_BIT | CONGRUENT_BIT | RIGID_BIT | - ROTATION_BIT; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; } /** @@ -1583,6 +1678,13 @@ public class Transform3D { mat[3] = trans.x; mat[7] = trans.y; mat[11] = trans.z; + + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(trans)) { + dirtyBits = ALL_DIRTY; + return; + } + // Only preserve CONGRUENT, RIGID, ORTHO type &= ~(ORTHOGONAL|IDENTITY|SCALE|TRANSLATION|SCALE|ZERO); dirtyBits |= CLASSIFY_BIT; @@ -1599,6 +1701,13 @@ public class Transform3D { mat[3] = trans.x; mat[7] = trans.y; mat[11] = trans.z; + + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(trans)) { + dirtyBits = ALL_DIRTY; + return; + } + type &= ~(ORTHOGONAL|IDENTITY|SCALE|TRANSLATION|SCALE|ZERO); dirtyBits |= CLASSIFY_BIT; } @@ -1636,8 +1745,9 @@ public class Transform3D { mat[13] = 0.0; mat[14] = 0.0; mat[15] = 1.0; - type = CONGRUENT | AFFINE | ORTHO; - dirtyBits = CLASSIFY_BIT | ROTATION_BIT | RIGID_BIT; + + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; } /** @@ -1673,8 +1783,8 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; - type = CONGRUENT | AFFINE | ORTHO; - dirtyBits = CLASSIFY_BIT | ROTATION_BIT| RIGID_BIT; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; } /** @@ -1710,8 +1820,8 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; - type = CONGRUENT | AFFINE | ORTHO; - dirtyBits = CLASSIFY_BIT | ROTATION_BIT | RIGID_BIT; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; } /** @@ -1742,9 +1852,8 @@ public class Transform3D { mat[14]=0.0; mat[15]=1.0; - type = AFFINE; - dirtyBits = ORTHO_BIT | CONGRUENT_BIT | RIGID_BIT | - CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; if (autoNormalize) { // input matrix may not normalize @@ -1780,9 +1889,8 @@ public class Transform3D { mat[14]=0.0; mat[15]=1.0; - type = AFFINE; - dirtyBits = ORTHO_BIT | CONGRUENT_BIT | RIGID_BIT | - CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -1817,9 +1925,8 @@ public class Transform3D { mat[14]=0.0; mat[15]=1.0; - type = AFFINE; - dirtyBits = ORTHO_BIT | CONGRUENT_BIT | RIGID_BIT | - CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -1849,7 +1956,7 @@ public class Transform3D { } } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -1920,7 +2027,7 @@ public class Transform3D { mat[14] = matrix[14]; mat[15] = matrix[15]; - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -1952,7 +2059,7 @@ public class Transform3D { mat[14] = matrix[14]; mat[15] = matrix[15]; - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -1984,7 +2091,7 @@ public class Transform3D { mat[14] = m1.m32; mat[15] = m1.m33; - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -2016,7 +2123,7 @@ public class Transform3D { mat[14] = m1.m32; mat[15] = m1.m33; - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -2049,9 +2156,8 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; - type = AFFINE; - dirtyBits = ORTHO_BIT | CONGRUENT_BIT | RIGID_BIT | - CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -2084,9 +2190,8 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; - type = AFFINE; - dirtyBits = ORTHO_BIT | CONGRUENT_BIT | RIGID_BIT | - CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -2139,6 +2244,12 @@ public class Transform3D { mat[14] = 0.0; mat[15] = 1.0; + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(euler)) { + dirtyBits = ALL_DIRTY; + return; + } + type = AFFINE | CONGRUENT | RIGID | ORTHO; dirtyBits = CLASSIFY_BIT | SCALE_BIT | ROTATION_BIT; } @@ -2968,7 +3079,7 @@ public class Transform3D { luBacksubstitution(tmp, row_perm, this.mat); type = 0; - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; } @@ -3314,6 +3425,12 @@ public class Transform3D { scales = new double[3]; scales[0] = scales[1] = scales[2] = scale; + + // Issue 253: set all dirty bits if input is infinity or NaN + if (isInfOrNaN(x) || isInfOrNaN(y) || isInfOrNaN(z) || isInfOrNaN(scale)) { + dirtyBits = ALL_DIRTY; + return; + } type = AFFINE | CONGRUENT | ORTHO; dirtyBits = CLASSIFY_BIT | ROTATION_BIT | RIGID_BIT; @@ -3329,7 +3446,7 @@ public class Transform3D { for (int i=0 ; i<16 ; i++) { mat[i] *= scalar; } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; } /** @@ -3342,7 +3459,7 @@ public class Transform3D { for (int i=0 ; i<16 ; i++) { mat[i] = t1.mat[i] * scalar; } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -3465,7 +3582,7 @@ public class Transform3D { dirtyBits = ORTHO_BIT | CONGRUENT_BIT | RIGID_BIT | CLASSIFY_BIT | ROTSCALESVD_DIRTY; } else { - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; } } @@ -3668,7 +3785,7 @@ public class Transform3D { dirtyBits = ORTHO_BIT | CONGRUENT_BIT | RIGID_BIT | CLASSIFY_BIT | ROTSCALESVD_DIRTY; } else { - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; } } @@ -3683,11 +3800,10 @@ public class Transform3D { * @param t1 the matrix whose inverse is computed. */ public final void mulInverse(Transform3D t1) { - Transform3D t2 = VirtualUniverse.mc.getTransform3D(null); + Transform3D t2 = new Transform3D(); t2.autoNormalize = false; t2.invert(t1); this.mul(t2); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t2); } @@ -3698,11 +3814,10 @@ public class Transform3D { * @param t2 the transform whose inverse is computed. */ public final void mulInverse(Transform3D t1, Transform3D t2) { - Transform3D t3 = VirtualUniverse.mc.getTransform3D(null); + Transform3D t3 = new Transform3D(); t3.autoNormalize = false; t3.invert(t2); this.mul(t1,t3); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t3); } /** @@ -3712,11 +3827,10 @@ public class Transform3D { * @param t2 the transform whose transpose is computed */ public final void mulTransposeRight(Transform3D t1, Transform3D t2) { - Transform3D t3 = VirtualUniverse.mc.getTransform3D(null); + Transform3D t3 = new Transform3D(); t3.autoNormalize = false; t3.transpose(t2); mul(t1, t3); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t3); } @@ -3727,11 +3841,10 @@ public class Transform3D { * @param t2 the transform on the right hand side of the multiplication */ public final void mulTransposeLeft(Transform3D t1, Transform3D t2){ - Transform3D t3 = VirtualUniverse.mc.getTransform3D(null); + Transform3D t3 = new Transform3D(); t3.autoNormalize = false; t3.transpose(t1); mul(t3, t2); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t3); } @@ -3743,15 +3856,13 @@ public class Transform3D { * @param t2 the transform on the right hand side of the multiplication */ public final void mulTransposeBoth(Transform3D t1, Transform3D t2) { - Transform3D t3 = VirtualUniverse.mc.getTransform3D(null); - Transform3D t4 = VirtualUniverse.mc.getTransform3D(null); + Transform3D t3 = new Transform3D(); + Transform3D t4 = new Transform3D(); t3.autoNormalize = false; t4.autoNormalize = false; t3.transpose(t1); t4.transpose(t2); mul(t3, t4); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t3); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t4); } @@ -3765,6 +3876,10 @@ public class Transform3D { * Note that the scale of the matrix is not altered by this method. */ public final void normalize() { + // Issue 253: Unable to normalize matrices with infinity or NaN + if (!isAffine() && isInfOrNaN()) { + return; + } if ((dirtyBits & (ROTATION_BIT|SVD_BIT)) != 0) { computeScaleRotation(true); @@ -3813,6 +3928,11 @@ public class Transform3D { * Note that the scale of the matrix is not altered by this method. */ public final void normalizeCP() { + // Issue 253: Unable to normalize matrices with infinity or NaN + if (!isAffine() && isInfOrNaN()) { + return; + } + if ((dirtyBits & SCALE_BIT) != 0) { computeScales(false); } @@ -4189,9 +4309,9 @@ public class Transform3D { mat[4] = m1.m10; mat[5] = m1.m11; mat[6] = m1.m12; mat[8] = m1.m20; mat[9] = m1.m21; mat[10] = m1.m22; - // keep affine bit - dirtyBits |= (RIGID_BIT | CONGRUENT_BIT | ORTHO_BIT | - CLASSIFY_BIT | ROTSCALESVD_DIRTY); + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; + if (autoNormalize) { normalize(); } @@ -4208,9 +4328,10 @@ public class Transform3D { mat[4] = m1.m10; mat[5] = m1.m11; mat[6] = m1.m12; mat[8] = m1.m20; mat[9] = m1.m21; mat[10] = m1.m22; - dirtyBits |= (RIGID_BIT | CONGRUENT_BIT | ORTHO_BIT | - CLASSIFY_BIT | ROTSCALESVD_DIRTY); - if (autoNormalize) { + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; + + if (autoNormalize) { normalize(); } } @@ -4227,7 +4348,7 @@ public class Transform3D { mat[i] = s*t1.mat[i] + t2.mat[i]; } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -4246,7 +4367,7 @@ public class Transform3D { mat[i] = s*mat[i] + t1.mat[i]; } - dirtyBits = CLASSIFY_ALL_DIRTY | ROTSCALESVD_DIRTY; + dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); @@ -4354,8 +4475,8 @@ public class Transform3D { mat[12] = mat[13] = mat[14] = 0; mat[15] = 1; - type = AFFINE | CONGRUENT | RIGID | ORTHO; - dirtyBits = CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; } @@ -4407,7 +4528,8 @@ public class Transform3D { // Matrix is a projection transform type = 0; - dirtyBits = CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; } @@ -4454,7 +4576,8 @@ public class Transform3D { // Matrix is a projection transform type = 0; - dirtyBits = CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; } @@ -4497,10 +4620,9 @@ public class Transform3D { mat[1] = mat[2] = mat[4] = mat[6] = mat[8] = mat[9] = mat[12] = mat[13] = mat[14] = 0; mat[15] = 1; - // Matrix is a projection transform - type = AFFINE; - dirtyBits = CLASSIFY_BIT | ROTSCALESVD_DIRTY | CONGRUENT_BIT | - RIGID_BIT | ORTHO_BIT; + + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; } /** @@ -5641,18 +5763,72 @@ public class Transform3D { t.mat[9] = rot[7]; t.mat[10] = rot[8]; - t.type = ORTHOGONAL | RIGID | CONGRUENT| AFFINE | ORTHO; - if ((dirtyBits & SVD_BIT) != 0) { - t.dirtyBits = CLASSIFY_BIT | ROTSCALESVD_DIRTY; - } else { - t.dirtyBits = CLASSIFY_BIT | ROTATION_BIT | SCALE_BIT; - } + // Issue 253: set all dirty bits + t.dirtyBits = ALL_DIRTY; } // somehow CanvasViewCache will directly modify mat[] // instead of calling ortho(). So we need to reset dirty bit final void setOrthoDirtyBit() { - dirtyBits = CLASSIFY_BIT | ROTSCALESVD_DIRTY; + // Issue 253: set all dirty bits + dirtyBits = ALL_DIRTY; type = 0; } + + // Fix for Issue 167 -- don't classify matrices with Infinity or NaN values + // as affine + private final boolean isInfOrNaN() { + for (int i = 0; i < 16; i++) { + if (Double.isNaN(mat[i]) || Double.isInfinite(mat[i])) { + return true; + } + } + return false; + } + + // Fix for Issue 253 + // Methods to check input parameters for Infinity or NaN values + private final boolean isInfOrNaN(Quat4f q) { + return (Float.isNaN(q.x) || Float.isInfinite(q.x) || + Float.isNaN(q.y) || Float.isInfinite(q.y) || + Float.isNaN(q.z) || Float.isInfinite(q.z) || + Float.isNaN(q.w) || Float.isInfinite(q.w)); + } + + private boolean isInfOrNaN(Quat4d q) { + return (Double.isNaN(q.x) || Double.isInfinite(q.x) || + Double.isNaN(q.y) || Double.isInfinite(q.y) || + Double.isNaN(q.z) || Double.isInfinite(q.z) || + Double.isNaN(q.w) || Double.isInfinite(q.w)); + } + + private boolean isInfOrNaN(AxisAngle4f a) { + return (Float.isNaN(a.x) || Float.isInfinite(a.x) || + Float.isNaN(a.y) || Float.isInfinite(a.y) || + Float.isNaN(a.z) || Float.isInfinite(a.z) || + Float.isNaN(a.angle) || Float.isInfinite(a.angle)); + } + + private boolean isInfOrNaN(AxisAngle4d a) { + return (Double.isNaN(a.x) || Double.isInfinite(a.x) || + Double.isNaN(a.y) || Double.isInfinite(a.y) || + Double.isNaN(a.z) || Double.isInfinite(a.z) || + Double.isNaN(a.angle) || Double.isInfinite(a.angle)); + } + + private boolean isInfOrNaN(double val) { + return Double.isNaN(val) || Double.isInfinite(val); + } + + private boolean isInfOrNaN(Vector3f v) { + return (Float.isNaN(v.x) || Float.isInfinite(v.x) || + Float.isNaN(v.y) || Float.isInfinite(v.y) || + Float.isNaN(v.z) || Float.isInfinite(v.z)); + } + + private boolean isInfOrNaN(Vector3d v) { + return (Double.isNaN(v.x) || Double.isInfinite(v.x) || + Double.isNaN(v.y) || Double.isInfinite(v.y) || + Double.isNaN(v.z) || Double.isInfinite(v.z)); + } } diff --git a/src/classes/share/javax/media/j3d/TransformGroup.java b/src/classes/share/javax/media/j3d/TransformGroup.java index 9290c03..6bf078c 100644 --- a/src/classes/share/javax/media/j3d/TransformGroup.java +++ b/src/classes/share/javax/media/j3d/TransformGroup.java @@ -182,9 +182,8 @@ public class TransformGroup extends Group { void duplicateAttributes(Node originalNode, boolean forceDuplicate) { super.duplicateAttributes(originalNode, forceDuplicate); - Transform3D t = VirtualUniverse.mc.getTransform3D(null); + Transform3D t = new Transform3D(); ((TransformGroupRetained) originalNode.retained).getTransform(t); ((TransformGroupRetained) retained).setTransform(t); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t); } } diff --git a/src/classes/share/javax/media/j3d/TransformGroupRetained.java b/src/classes/share/javax/media/j3d/TransformGroupRetained.java index 7ede29f..bca8aa4 100644 --- a/src/classes/share/javax/media/j3d/TransformGroupRetained.java +++ b/src/classes/share/javax/media/j3d/TransformGroupRetained.java @@ -117,13 +117,13 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface // this writeable transformGroup has a static transform // merged into this node - trans = VirtualUniverse.mc.getTransform3D(staticTransform.transform); + trans = new Transform3D(staticTransform.transform); trans.mul(t1); transform.setWithLock(trans); } else { - trans = VirtualUniverse.mc.getTransform3D(t1); + trans = new Transform3D(t1); transform.setWithLock(t1); } @@ -137,7 +137,7 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface throw new BadTransformException(J3dI18N.getString("ViewPlatformRetained0")); } - tchangeMessage = VirtualUniverse.mc.getMessage(); + tchangeMessage = new J3dMessage(); tchangeMessage.type = J3dMessage.TRANSFORM_CHANGED; tchangeMessage.threads = targetThreads; tchangeMessage.args[1] = this; @@ -534,7 +534,7 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface // This is needed b/c super.setlive is called after inSharedGroup check. inSharedGroup = s.inSharedGroup; - trans = VirtualUniverse.mc.getTransform3D(null); + trans = new Transform3D(); transform.getWithLock(trans); currentTransform.set(trans); diff --git a/src/classes/share/javax/media/j3d/TransformStructure.java b/src/classes/share/javax/media/j3d/TransformStructure.java index 5c16942..8320a6c 100644 --- a/src/classes/share/javax/media/j3d/TransformStructure.java +++ b/src/classes/share/javax/media/j3d/TransformStructure.java @@ -216,8 +216,6 @@ class TransformStructure extends J3dStructure implements ObjectUpdate { for (i=0; i<tSize; i++) { tg = tgs[i]; tg.currentTransform.set(t3ds[i]); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - t3ds[i]); synchronized(tg) { // synchronized with tg.set/clearLive if(tg.perPathData != null) { diff --git a/src/classes/share/javax/media/j3d/TransparencyAttributesRetained.java b/src/classes/share/javax/media/j3d/TransparencyAttributesRetained.java index beb2ad7..8c4b6fd 100644 --- a/src/classes/share/javax/media/j3d/TransparencyAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/TransparencyAttributesRetained.java @@ -215,22 +215,11 @@ class TransparencyAttributesRetained extends NodeComponentRetained { } } - /** - * These two native methods update the native context. - */ - native void updateNative(long ctx, - float alpha, int geometryType, - int polygonMode, - boolean lineAA, boolean pointAA, - int transparencyMode, - int srcBlendFunction, - int dstBlendFunction); - - void updateNative(long ctx, + void updateNative(Context ctx, float alpha, int geometryType, int polygonMode, boolean lineAA, boolean pointAA) { - updateNative(ctx, alpha, geometryType, polygonMode, + Pipeline.getPipeline().updateTransparencyAttributes(ctx, alpha, geometryType, polygonMode, lineAA, pointAA, transparencyMode, srcBlendFunction, dstBlendFunction); } @@ -292,7 +281,7 @@ class TransparencyAttributesRetained extends NodeComponentRetained { // Send to rendering attribute structure, regardless of // whether there are users or not (alternate appearance case ..) - J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + J3dMessage createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; createMessage.type = J3dMessage.TRANSPARENCYATTRIBUTES_CHANGED; createMessage.universe = null; @@ -305,7 +294,7 @@ class TransparencyAttributesRetained extends NodeComponentRetained { // System.out.println("univList.size is " + univList.size()); for(int i=0; i<univList.size(); i++) { - createMessage = VirtualUniverse.mc.getMessage(); + createMessage = new J3dMessage(); createMessage.threads = J3dThread.UPDATE_RENDER; createMessage.type = J3dMessage.TRANSPARENCYATTRIBUTES_CHANGED; diff --git a/src/classes/share/javax/media/j3d/TriangleArrayRetained.java b/src/classes/share/javax/media/j3d/TriangleArrayRetained.java index 9969788..d64221d 100644 --- a/src/classes/share/javax/media/j3d/TriangleArrayRetained.java +++ b/src/classes/share/javax/media/j3d/TriangleArrayRetained.java @@ -414,12 +414,12 @@ class TriangleArrayRetained extends GeometryArrayRetained { int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); - Point3d pnt0 = getPoint3d(); - Point3d pnt1 = getPoint3d(); - Point3d pnt2 = getPoint3d(); - Vector3d vec = getVector3d(); - Vector3d normal = getVector3d(); - Vector3d tmpvec = getVector3d(); + Point3d pnt0 = new Point3d(); + Point3d pnt1 = new Point3d(); + Point3d pnt2 = new Point3d(); + Vector3d vec = new Vector3d(); + Vector3d normal = new Vector3d(); + Vector3d tmpvec = new Vector3d(); double area; double totalarea = 0; @@ -463,12 +463,6 @@ class TriangleArrayRetained extends GeometryArrayRetained { centroid.y *= area; centroid.z *= area; } - freeVector3d(tmpvec); - freeVector3d(vec); - freeVector3d(normal); - freePoint3d(pnt0); - freePoint3d(pnt1); - freePoint3d(pnt2); } int getClassType() { diff --git a/src/classes/share/javax/media/j3d/TriangleFanArrayRetained.java b/src/classes/share/javax/media/j3d/TriangleFanArrayRetained.java index e7035a6..7e24f77 100644 --- a/src/classes/share/javax/media/j3d/TriangleFanArrayRetained.java +++ b/src/classes/share/javax/media/j3d/TriangleFanArrayRetained.java @@ -509,12 +509,12 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { // From Graphics Gems IV (pg5) and Graphics Gems II, Pg170 void computeCentroid() { - Vector3d vec = getVector3d(); - Vector3d normal = getVector3d(); - Vector3d tmpvec = getVector3d(); - Point3d pnt0 = getPoint3d(); - Point3d pnt1 = getPoint3d(); - Point3d pnt2 = getPoint3d(); + Vector3d vec = new Vector3d(); + Vector3d normal = new Vector3d(); + Vector3d tmpvec = new Vector3d(); + Point3d pnt0 = new Point3d(); + Point3d pnt1 = new Point3d(); + Point3d pnt2 = new Point3d(); double area, totalarea = 0; int end, replaceIndex, j, i = 0; centroid.x = 0; @@ -569,12 +569,6 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { centroid.y *= area; centroid.z *= area; } - freeVector3d(tmpvec); - freeVector3d(vec); - freeVector3d(normal); - freePoint3d(pnt0); - freePoint3d(pnt1); - freePoint3d(pnt2); } int getClassType() { diff --git a/src/classes/share/javax/media/j3d/TriangleStripArrayRetained.java b/src/classes/share/javax/media/j3d/TriangleStripArrayRetained.java index 8d06972..54347df 100644 --- a/src/classes/share/javax/media/j3d/TriangleStripArrayRetained.java +++ b/src/classes/share/javax/media/j3d/TriangleStripArrayRetained.java @@ -527,12 +527,12 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { // From Graphics Gems IV (pg5) and Graphics Gems II, Pg170 void computeCentroid() { - Point3d pnt0 = getPoint3d(); - Point3d pnt1 = getPoint3d(); - Point3d pnt2 = getPoint3d(); - Vector3d vec = getVector3d(); - Vector3d normal = getVector3d(); - Vector3d tmpvec = getVector3d(); + Point3d pnt0 = new Point3d(); + Point3d pnt1 = new Point3d(); + Point3d pnt2 = new Point3d(); + Vector3d vec = new Vector3d(); + Vector3d normal = new Vector3d(); + Vector3d tmpvec = new Vector3d(); double area, totalarea = 0; int end, replaceIndex, j, i = 0; @@ -594,13 +594,6 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { centroid.y *= area; centroid.z *= area; } - - freeVector3d(tmpvec); - freeVector3d(vec); - freeVector3d(normal); - freePoint3d(pnt0); - freePoint3d(pnt1); - freePoint3d(pnt2); } diff --git a/src/classes/share/javax/media/j3d/VertexArrayRenderMethod.java b/src/classes/share/javax/media/j3d/VertexArrayRenderMethod.java index c5ac846..a7c0bb0 100644 --- a/src/classes/share/javax/media/j3d/VertexArrayRenderMethod.java +++ b/src/classes/share/javax/media/j3d/VertexArrayRenderMethod.java @@ -20,18 +20,18 @@ package javax.media.j3d; class VertexArrayRenderMethod implements RenderMethod { - public boolean render(RenderMolecule rm, Canvas3D cv, int pass, + public boolean render(RenderMolecule rm, Canvas3D cv, RenderAtomListInfo ra, int dirtyBits) { - + GeometryArrayRetained geo = (GeometryArrayRetained)ra.geometry(); geo.setVertexFormat((rm.useAlpha && ((geo.vertexFormat & GeometryArray.COLOR) != 0)), rm.textureBin.attributeBin.ignoreVertexColors, cv.ctx); if (rm.doInfinite) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); while (ra != null) { - renderGeo(ra, rm, pass, cv); + renderGeo(ra, rm, cv); ra = ra.next; } return true; @@ -41,17 +41,17 @@ class VertexArrayRenderMethod implements RenderMethod { while (ra != null) { if (cv.ra == ra.renderAtom) { if (cv.raIsVisible) { - cv.updateState(pass, dirtyBits); - renderGeo(ra, rm, pass, cv); + cv.updateState(dirtyBits); + renderGeo(ra, rm, cv); isVisible = true; } } else { if (!VirtualUniverse.mc.viewFrustumCulling || ra.renderAtom.localeVwcBounds.intersect(cv.viewFrustum)) { - cv.updateState(pass, dirtyBits); + cv.updateState(dirtyBits); cv.raIsVisible = true; - renderGeo(ra, rm, pass, cv); + renderGeo(ra, rm, cv); isVisible = true; } else { @@ -69,7 +69,7 @@ class VertexArrayRenderMethod implements RenderMethod { return isVisible; } - void renderGeo(RenderAtomListInfo ra, RenderMolecule rm, int pass, Canvas3D cv) { + void renderGeo(RenderAtomListInfo ra, RenderMolecule rm, Canvas3D cv) { GeometryArrayRetained geo; boolean useAlpha; @@ -81,9 +81,7 @@ class VertexArrayRenderMethod implements RenderMethod { geo.execute(cv, ra.renderAtom, rm.isNonUniformScale, (useAlpha && ((geo.vertexFormat & GeometryArray.COLOR) != 0)) , rm.alpha, - rm.renderBin.multiScreen, cv.screen.screen, - rm.textureBin.attributeBin.ignoreVertexColors, - pass); + rm.textureBin.attributeBin.ignoreVertexColors); } } diff --git a/src/classes/share/javax/media/j3d/View.java b/src/classes/share/javax/media/j3d/View.java index 9cc2300..a447cf2 100644 --- a/src/classes/share/javax/media/j3d/View.java +++ b/src/classes/share/javax/media/j3d/View.java @@ -13,15 +13,13 @@ package javax.media.j3d; import javax.vecmath.*; -import java.lang.Math; import java.util.Vector; import java.util.ArrayList; import java.util.LinkedList; import java.util.Iterator; import java.util.Enumeration; import java.awt.*; -import java.awt.event.*; -import com.sun.j3d.utils.universe.*; // Needed for Support of DVR. +import com.sun.j3d.utils.universe.Viewer; // Needed for Support of DVR. /** * The View object contains all parameters needed in rendering a @@ -166,12 +164,13 @@ import com.sun.j3d.utils.universe.*; // Needed for Support of DVR. * <LI>VIRTUAL_EYE - specifies that the associated distance is from * the eye and in units of virtual distance.</LI><P> * <LI>PHYSICAL_EYE - specifies that the associated distance is from - * the eye and in units of physical distance (in meters).</LI><P> + * the eye and in units of physical distance (in meters). + * This is the default policy for both front and back clipping.</LI><P> * <LI>VIRTUAL_SCREEN - specifies that the associated distance is * from the screen and in units of virtual distance. </LI><P> * <LI>PHYSICAL_SCREEN - specifies that the associated distance is * from the screen and in units of physical distance (in meters). - * This is the default policy for both front and back clipping.</LI><P> + * </LI><P> * </UL> * <LI>Visibility policy - specifies how visible and invisible objects * are drawn. There are three visibility policies:</LI><P> @@ -491,6 +490,7 @@ public class View extends Object { * from the eye in meters. * Policy for interpreting clip plane distances. * Used in specifying the policy in frontClipPolicy and backClipPolicy. + * This is the default policy for both front and back clipping. * @see #setFrontClipPolicy * @see #setBackClipPolicy */ @@ -722,8 +722,8 @@ public class View extends Object { // Support dynamic video resize -- DVR. Viewer viewer = null; // Cached the associate viewer of this view. boolean firstTime = true; - float dvrFactor = 1.0f; - boolean dvrResizeCompensation = true; +// float dvrFactor = 1.0f; +// boolean dvrResizeCompensation = true; // User adjustable minimum frame cycle time long minFrameCycleTime; @@ -982,7 +982,6 @@ public class View extends Object { private Canvas3D[][] cachedCanvasList; private Canvas3D[] cachedCanvases; - private Canvas3D[] cachedOffScreenCanvases; private Screen3D[] cachedScreens; private int longestScreenList = 0; private boolean canvasesDirty = true; @@ -1912,7 +1911,7 @@ public class View extends Object { if (activeStatus && isRunning) { - J3dMessage vpMessage = VirtualUniverse.mc.getMessage(); + J3dMessage vpMessage = new J3dMessage(); vpMessage.universe = universe; vpMessage.view = this; vpMessage.type = J3dMessage.UPDATE_VIEW; @@ -1973,7 +1972,7 @@ public class View extends Object { transparencySortingPolicy = policy; if (activeStatus && isRunning) { - J3dMessage vpMessage = VirtualUniverse.mc.getMessage(); + J3dMessage vpMessage = new J3dMessage(); vpMessage.universe = universe; vpMessage.view = this; vpMessage.type = J3dMessage.UPDATE_VIEW; @@ -2416,22 +2415,14 @@ public class View extends Object { synchronized (canvasList) { ArrayList cv; int len = canvases.size(); - int numOffScreenCanvases = 0; Canvas3D newCachedCanvases[] = new Canvas3D[len]; for (int i=0; i < len; i++) { newCachedCanvases[i] = (Canvas3D) canvases.get(i); - if (newCachedCanvases[i].offScreen) - numOffScreenCanvases++; } // Do this in one instruction so there is no need to // synchronized getCanvases() - if (numOffScreenCanvases > 0) { - cachedOffScreenCanvases = new Canvas3D[numOffScreenCanvases]; - numOffScreenCanvases = 0; - } - cachedCanvases = newCachedCanvases; len = 0; longestScreenList = 0; @@ -2444,13 +2435,6 @@ public class View extends Object { cachedCanvasList[i][j] = (Canvas3D) cv.get(j); } - if (cachedCanvasList[i][0].offScreen) { - for (int j = 0; j < len; j++) { - cachedOffScreenCanvases[numOffScreenCanvases++]= - cachedCanvasList[i][j]; - } - } - if (len > longestScreenList) { longestScreenList = len; } @@ -2491,10 +2475,6 @@ public class View extends Object { return cachedCanvases; } - Canvas3D[] getOffScreenCanvases() { - return cachedOffScreenCanvases; - } - // assume getCanvasList is called before Screen3D[] getScreens() { return cachedScreens; @@ -3089,7 +3069,10 @@ public class View extends Object { final void updateViewCache() { - // DVR support + // TODO KCR : remove obsolete DVR code (but make sure we don't end + // up with a leak in the Viewer Map object). + + // DVR support // This is a back door in j3d to provide DVR support. // A better place to put this code segment is in // ViewCache.snapshot(). Since it consists of some @@ -3104,24 +3087,24 @@ public class View extends Object { firstTime = false; } - if(viewer != null) { - if(viewer.isDvrEnabled()) { - dvrFactor = viewer.getDvrFactor(); - dvrResizeCompensation = - viewer.getDvrResizeCompensationEnable(); - /* - System.out.println("View : dvrFactor is " + dvrFactor); - System.out.println("View : dvrResizeCompensation is " + - dvrResizeCompensation); - */ - } - else { - // Reset back to default. - dvrFactor = 1.0f; - dvrResizeCompensation = true; - - } - } +// if(viewer != null) { +// if(viewer.isDvrEnabled()) { +// dvrFactor = viewer.getDvrFactor(); +// dvrResizeCompensation = +// viewer.getDvrResizeCompensationEnable(); +// /* +// System.out.println("View : dvrFactor is " + dvrFactor); +// System.out.println("View : dvrResizeCompensation is " + +// dvrResizeCompensation); +// */ +// } +// else { +// // Reset back to default. +// dvrFactor = 1.0f; +// dvrResizeCompensation = true; +// +// } +// } // End of back door -- DVR. synchronized(this) { @@ -3286,7 +3269,7 @@ public class View extends Object { soundScheduler.reset(); } - J3dMessage vpMessage = VirtualUniverse.mc.getMessage(); + J3dMessage vpMessage = new J3dMessage(); vpMessage.universe = universe; vpMessage.view = this; vpMessage.type = J3dMessage.UPDATE_VIEW; @@ -3325,7 +3308,7 @@ public class View extends Object { } - J3dMessage vpMessage = VirtualUniverse.mc.getMessage(); + J3dMessage vpMessage = new J3dMessage(); vpMessage.universe = universe; vpMessage.view = this; vpMessage.type = J3dMessage.UPDATE_VIEW; diff --git a/src/classes/share/javax/media/j3d/ViewPlatformRetained.java b/src/classes/share/javax/media/j3d/ViewPlatformRetained.java index d80341b..b9756e4 100644 --- a/src/classes/share/javax/media/j3d/ViewPlatformRetained.java +++ b/src/classes/share/javax/media/j3d/ViewPlatformRetained.java @@ -141,7 +141,7 @@ class ViewPlatformRetained extends LeafRetained { } // Notify behavior scheduler & RenderBin if (source.isLive()) { - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.UPDATE_VIEWPLATFORM; message.threads = J3dThread.UPDATE_RENDER|J3dThread.UPDATE_BEHAVIOR; message.universe = universe; @@ -184,7 +184,7 @@ class ViewPlatformRetained extends LeafRetained { Transform3D getVworldToVpc() { if (vworldToVpc == null) - vworldToVpc = VirtualUniverse.mc.getTransform3D(null); + vworldToVpc = new Transform3D(); vworldToVpc.set(getCurrentLocalToVworld(null)); vworldToVpc.invert(); return vworldToVpc; @@ -197,10 +197,6 @@ class ViewPlatformRetained extends LeafRetained { void evaluateViewPlatformTransform() { - if (vworldToVpc != null) { - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, - vworldToVpc); - } // clear cache so that next time getVworldToVpc() can recompute vworldToVpc = null; } diff --git a/src/classes/share/javax/media/j3d/ViewSpecificGroupRetained.java b/src/classes/share/javax/media/j3d/ViewSpecificGroupRetained.java index 113e4d8..5f6b963 100644 --- a/src/classes/share/javax/media/j3d/ViewSpecificGroupRetained.java +++ b/src/classes/share/javax/media/j3d/ViewSpecificGroupRetained.java @@ -78,7 +78,7 @@ class ViewSpecificGroupRetained extends GroupRetained { objAry[3] = super.processViewSpecificInfo(ADD_VIEW, (HashKey)key, view, addVsgList, addKeyList, addLeafList); - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.VIEWSPECIFICGROUP_CHANGED; message.threads = (J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER | @@ -120,7 +120,7 @@ class ViewSpecificGroupRetained extends GroupRetained { } */ - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.VIEWSPECIFICGROUP_CHANGED; message.threads = (J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER | @@ -184,7 +184,7 @@ class ViewSpecificGroupRetained extends GroupRetained { objAry[3] = super.processViewSpecificInfo(ADD_VIEW, (HashKey)key, view, addVsgList, addKeyList, addLeafList); } - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.VIEWSPECIFICGROUP_CHANGED; message.threads = (J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER | @@ -230,7 +230,7 @@ class ViewSpecificGroupRetained extends GroupRetained { objAry[3] = super.processViewSpecificInfo(ADD_VIEW, (HashKey)tempKey, view, addVsgList, addKeyList, addLeafList); } - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.VIEWSPECIFICGROUP_CHANGED; message.threads = (J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER | @@ -337,7 +337,7 @@ class ViewSpecificGroupRetained extends GroupRetained { objAry[3] = super.processViewSpecificInfo(ADD_VIEW, (HashKey)key, view, addVsgList, addKeyList, addLeafList); - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.VIEWSPECIFICGROUP_CHANGED; message.threads = (J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER | @@ -379,7 +379,7 @@ class ViewSpecificGroupRetained extends GroupRetained { } */ - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.VIEWSPECIFICGROUP_CHANGED; message.threads = (J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER | @@ -427,7 +427,7 @@ class ViewSpecificGroupRetained extends GroupRetained { removeVsgList, removeKeyList, removeLeafList); - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.VIEWSPECIFICGROUP_CHANGED; message.threads = (J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER | @@ -468,7 +468,7 @@ class ViewSpecificGroupRetained extends GroupRetained { System.out.println("n = "+n+" keyValue = "+removeKeyList.get(n)); } */ - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.VIEWSPECIFICGROUP_CHANGED; message.threads = (J3dThread.UPDATE_RENDERING_ENVIRONMENT| J3dThread.UPDATE_RENDER | diff --git a/src/classes/share/javax/media/j3d/VirtualUniverse.java b/src/classes/share/javax/media/j3d/VirtualUniverse.java index a38302c..dcedfcb 100644 --- a/src/classes/share/javax/media/j3d/VirtualUniverse.java +++ b/src/classes/share/javax/media/j3d/VirtualUniverse.java @@ -163,13 +163,20 @@ public class VirtualUniverse extends Object { boolean isSceneGraphLock = false; private Object waitLock = new Object(); - - private HashSet structureChangeListenerSet = null; - private HashSet shaderErrorListenerSet = null; + // Set of scene graph structure change listeners + private HashSet<GraphStructureChangeListener> structureChangeListenerSet = null; + + // Set of shader error listeners + private HashSet<ShaderErrorListener> shaderErrorListenerSet = null; private ShaderErrorListener defaultShaderErrorListener = ShaderProgram.getDefaultErrorListener(); + // Set of rendering error listeners + private static HashSet<RenderingErrorListener> renderingErrorListenerSet = null; + private static RenderingErrorListener defaultRenderingErrorListener = + Renderer.getDefaultErrorListener(); + /** * Constructs a new VirtualUniverse. */ @@ -255,24 +262,8 @@ public class VirtualUniverse extends Object { // Print out debugging information for debug builds if(VersionInfo.isDebug) { System.err.println("Java 3D system initialized"); - System.err.print(" graphics library = "); - switch (mc.getRenderingAPI()) { - case MasterControl.RENDER_OPENGL_SOLARIS: - System.err.println("Solaris OpenGL"); - break; - case MasterControl.RENDER_OPENGL_LINUX: - System.err.println("Linux OpenGL"); - break; - case MasterControl.RENDER_OPENGL_WIN32: - System.err.print("Windows OpenGL"); - break; - case MasterControl.RENDER_DIRECT3D: - System.err.println("Windows Direct3D"); - break; - default: - System.err.println("UNKNOWN"); - break; - } + System.err.println(" rendering pipeline = " + + Pipeline.getPipeline().getPipelineName()); System.err.println(); } } @@ -439,6 +430,10 @@ public class VirtualUniverse extends Object { * <td>String</td> * </tr> * <tr> + * <td><code>j3d.pipeline</code></td> + * <td>String</td> + * </tr> + * <tr> * <td><code>j3d.renderer</code></td> * <td>String</td> * </tr> @@ -514,10 +509,20 @@ public class VirtualUniverse extends Object { * <p> * * <li> + * <code>j3d.pipeline</code> + * <ul> + * String that specifies the Java 3D rendering pipeline. This could + * be one of: "NATIVE_OGL", "NATIVE_D3D", or "JOGL". Others could be + * added in the future. + * </ul> + * </li> + * <p> + * + * <li> * <code>j3d.renderer</code> * <ul> - * String that specifies the Java 3D rendering library. This could - * be one of: "OpenGL" or "DirectX". + * String that specifies the underlying rendering library. This could + * be one of: "OpenGL" or "DirectX". Others could be added in the future. * </ul> * </li> * <p> @@ -549,7 +554,10 @@ public class VirtualUniverse extends Object { values.add(VersionInfo.getSpecificationVendor()); keys.add("j3d.renderer"); - values.add(mc.isD3D() ? "DirectX" : "OpenGL"); + values.add(Pipeline.getPipeline().getRendererName()); + + keys.add("j3d.pipeline"); + values.add(Pipeline.getPipeline().getPipelineName()); // Now Create read-only properties object properties = @@ -1058,9 +1066,9 @@ public class VirtualUniverse extends Object { } synchronized(structureChangeListenerSet) { - Iterator it = structureChangeListenerSet.iterator(); + Iterator<GraphStructureChangeListener> it = structureChangeListenerSet.iterator(); while(it.hasNext()) { - GraphStructureChangeListener listener = (GraphStructureChangeListener)it.next(); + GraphStructureChangeListener listener = it.next(); try { if (add) { listener.branchGroupAdded(parent, child); @@ -1072,6 +1080,11 @@ public class VirtualUniverse extends Object { System.err.println("Exception occurred in GraphStructureChangeListener:"); e.printStackTrace(); } + catch (Error e) { + // Issue 264 - catch Error + System.err.println("Error occurred in GraphStructureChangeListener:"); + e.printStackTrace(); + } } } } @@ -1086,9 +1099,9 @@ public class VirtualUniverse extends Object { } synchronized(structureChangeListenerSet) { - Iterator it = structureChangeListenerSet.iterator(); + Iterator<GraphStructureChangeListener> it = structureChangeListenerSet.iterator(); while(it.hasNext()) { - GraphStructureChangeListener listener = (GraphStructureChangeListener)it.next(); + GraphStructureChangeListener listener = it.next(); try { listener.branchGroupMoved(oldParent, newParent, child); } @@ -1096,6 +1109,11 @@ public class VirtualUniverse extends Object { System.err.println("Exception occurred in GraphStructureChangeListener:"); e.printStackTrace(); } + catch (Error e) { + // Issue 264 - catch Error + System.err.println("Error occurred in GraphStructureChangeListener:"); + e.printStackTrace(); + } } } } @@ -1163,9 +1181,9 @@ public class VirtualUniverse extends Object { // Notify all error listeners in the set if (shaderErrorListenerSet != null) { synchronized(shaderErrorListenerSet) { - Iterator it = shaderErrorListenerSet.iterator(); + Iterator<ShaderErrorListener> it = shaderErrorListenerSet.iterator(); while(it.hasNext()) { - ShaderErrorListener listener = (ShaderErrorListener)it.next(); + ShaderErrorListener listener = it.next(); try { listener.errorOccurred(error); } @@ -1173,15 +1191,108 @@ public class VirtualUniverse extends Object { System.err.println("Exception occurred in ShaderErrorListener:"); e.printStackTrace(); } + catch (Error e) { + // Issue 264 - catch Error + System.err.println("Error occurred in ShaderErrorListener:"); + e.printStackTrace(); + } errorReported = true; } } } - // Notify the default error listener if the set is null or empty - if (!errorReported) { - defaultShaderErrorListener.errorOccurred(error); + // Notify the default error listener if the set is null or empty + if (!errorReported) { + defaultShaderErrorListener.errorOccurred(error); + } + } + + + // Issue 260 : rendering error listeners. + + /** + * Adds the specified RenderingErrorListener to the set of listeners + * that will be notified when a rendering error is detected. + * If the specifed listener is null no action is taken and no exception + * is thrown. + * If a rendering error occurs, the listeners will be called + * asynchronously from a separate notification thread. If the set + * of listeners is empty, a default listener is notified. The + * default listener prints the error information to System.err and + * then calls System.exit(). + * + * @param listener the listener to add to the set. + * + * @since Java 3D 1.5 + */ + public static void addRenderingErrorListener(RenderingErrorListener listener) { + if (listener == null) { + return; + } + + if (renderingErrorListenerSet == null) { + renderingErrorListenerSet = new HashSet(); + } + + synchronized(renderingErrorListenerSet) { + renderingErrorListenerSet.add(listener); + } + } + + /** + * Removes the specified RenderingErrorListener from the set of + * listeners. This method performs no function, nor does it throw + * an exception if the specified listener is not currently in the + * set or is null. + * + * @param listener the listener to remove from the set. + * + * @since Java 3D 1.5 + */ + public static void removeRenderingErrorListener(RenderingErrorListener listener) { + if (renderingErrorListenerSet == null) { + return; } + + synchronized(renderingErrorListenerSet) { + renderingErrorListenerSet.remove(listener); + } + } + + /** + * Notifies all listeners of a rendering error. If no listeners exist, + * a default listener is notified. + */ + static void notifyRenderingErrorListeners(RenderingError error) { + boolean errorReported = false; + + // Notify all error listeners in the set + if (renderingErrorListenerSet != null) { + synchronized(renderingErrorListenerSet) { + Iterator<RenderingErrorListener> it = renderingErrorListenerSet.iterator(); + while(it.hasNext()) { + RenderingErrorListener listener = it.next(); + try { + listener.errorOccurred(error); + } + catch (RuntimeException e) { + System.err.println("Exception occurred in RenderingErrorListener:"); + e.printStackTrace(); + } + catch (Error e) { + // Issue 264 - catch Error + System.err.println("Error occurred in RenderingErrorListener:"); + e.printStackTrace(); + } + errorReported = true; + } + } + } + + // Notify the default error listener if the set is null or empty + if (!errorReported) { + defaultRenderingErrorListener.errorOccurred(error); + } } } diff --git a/src/classes/share/javax/media/j3d/WakeupCondition.java b/src/classes/share/javax/media/j3d/WakeupCondition.java index d0491dd..f419376 100644 --- a/src/classes/share/javax/media/j3d/WakeupCondition.java +++ b/src/classes/share/javax/media/j3d/WakeupCondition.java @@ -91,7 +91,7 @@ public abstract class WakeupCondition extends Object { if (!conditionMet) { conditionMet = true; - J3dMessage message = VirtualUniverse.mc.getMessage(); + J3dMessage message = new J3dMessage(); message.type = J3dMessage.COND_MET; message.threads = J3dThread.UPDATE_BEHAVIOR; message.universe = behav.universe; diff --git a/src/classes/solaris/javax/media/j3d/J3dGraphicsConfig.java b/src/classes/solaris/javax/media/j3d/J3dGraphicsConfig.java deleted file mode 100644 index c242a77..0000000 --- a/src/classes/solaris/javax/media/j3d/J3dGraphicsConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -package javax.media.j3d; - -import sun.awt.*; -import java.awt.*; - -class J3dGraphicsConfig { - - static native boolean isValidVisualID(long display, int vid); - - J3dGraphicsConfig(GraphicsDevice gd, int pixelFormat) { - // a dummy class which this constructor should - // never invoke under Solaris - } - - static boolean isValidPixelFormat(GraphicsConfiguration gc) { - return isValidVisualID(NativeScreenInfo.getStaticDisplay(), - ((X11GraphicsConfig) gc).getVisual()); - } - - static boolean isValidConfig(GraphicsConfiguration gc) { - // Check to see if a valid FBConfig pointer has been cached. - Object fbConfigObject = Canvas3D.fbConfigTable.get(gc); - return ((fbConfigObject != null) && - (fbConfigObject instanceof GraphicsConfigInfo)); - } - - -} diff --git a/src/classes/solaris/javax/media/j3d/NativeWSInfo.java b/src/classes/solaris/javax/media/j3d/NativeWSInfo.java deleted file mode 100644 index 2e0da2a..0000000 --- a/src/classes/solaris/javax/media/j3d/NativeWSInfo.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -package javax.media.j3d; - -import java.awt.*; -import java.awt.event.*; -import sun.awt.*; -import java.lang.reflect.Method; - -class NativeWSInfo { - - //X11DrawingSurface xds; - Object xds; - - void getCanvasWSParameters(Canvas3D canvas) { - try { - Class x11DSclass = Class.forName("sun.awt.X11DrawingSurface"); - Method getDrawable = x11DSclass.getDeclaredMethod("getDrawable", null ); - Method getVisualID = x11DSclass.getDeclaredMethod("getVisualID", null ); - - //canvas.window = xds.getDrawable(); - //canvas.vid = xds.getVisualID(); - - canvas.window = ((Integer)getDrawable.invoke( xds, null )).intValue(); - canvas.vid = ((Integer)getVisualID.invoke( xds, null )).intValue(); - } catch( Exception e ) { - e.printStackTrace(); - } - } - - void getWSDrawingSurface( Object dsi) { - try { - //xds = (X11DrawingSurface)dsi.getSurface(); - Class drawingSurfaceInfoClass = Class.forName("sun.awt.DrawingSurfaceInfo"); - Method getSurface = drawingSurfaceInfoClass.getDeclaredMethod( "getSurface", null); - - //xds = dsi.getSurface(); - xds = getSurface.invoke( dsi, null ); - } catch( Exception e ) { - e.printStackTrace(); - } - } - - int getCanvasVid(GraphicsConfiguration gcfg) { - return (((X11GraphicsConfig)gcfg).getVisual()); - } -} - diff --git a/src/classes/win32/javax/media/j3d/J3dGraphicsConfig.java b/src/classes/win32/javax/media/j3d/J3dGraphicsConfig.java deleted file mode 100644 index 72340e5..0000000 --- a/src/classes/win32/javax/media/j3d/J3dGraphicsConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -package javax.media.j3d; - -import sun.awt.Win32GraphicsConfig; -import java.awt.*; - -class J3dGraphicsConfig extends Win32GraphicsConfig { - - private int pixelFormat; - - J3dGraphicsConfig(GraphicsDevice gd, int pixelFormat) - { - super(gd, pixelFormat); - this.pixelFormat = pixelFormat; - } - - static boolean isValidPixelFormat(GraphicsConfiguration gc) { - return (gc instanceof J3dGraphicsConfig); - } - - static boolean isValidConfig(GraphicsConfiguration gc) { - return isValidPixelFormat(gc); - } - - int getPixelFormat() { - return pixelFormat; - } - - -} diff --git a/src/classes/win32/javax/media/j3d/NativeConfigTemplate3D.java b/src/classes/win32/javax/media/j3d/NativeConfigTemplate3D.java index 7253c5a..c198e31 100644 --- a/src/classes/win32/javax/media/j3d/NativeConfigTemplate3D.java +++ b/src/classes/win32/javax/media/j3d/NativeConfigTemplate3D.java @@ -44,7 +44,7 @@ class NativeConfigTemplate3D { choosePixelFormat(long ctx, int screen, int[] attrList, long[] pFormatInfo); // Native method to free an PixelFormatInfo struct. This is static since it - // may need to be called to clean up the Canvas3D fbConfigTable after the + // may need to be called to clean up the Canvas3D graphicsConfigTable after the // NativeConfigTemplate3D has been disposed of. static native void freePixelFormatInfo(long pFormatInfo); @@ -91,8 +91,8 @@ class NativeConfigTemplate3D { attrList[STENCIL_SIZE] = template.getStencilSize(); // System.out.println("NativeConfigTemplate3D : getStencilSize " + // attrList[STENCIL_SIZE]); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - int screen = nativeScreenInfo.getScreen(); + + int screen = NativeScreenInfo.getScreen(gd); long[] pFormatInfo = new long[1]; @@ -118,17 +118,15 @@ class NativeConfigTemplate3D { // Fix to issue 104 -- // Pass in 0 for pixel format to the AWT. // ATI driver will lockup pixelFormat, if it is passed to AWT. - GraphicsConfiguration gc1 = new J3dGraphicsConfig(gd, 0); - - // We need to cache the offScreen pixelformat that glXChoosePixelFormat() - // returns, since this is not cached with J3dGraphicsConfig and there - // are no public constructors to allow us to extend it. - synchronized (Canvas3D.fbConfigTable) { - if (Canvas3D.fbConfigTable.get(gc1) == null) { - GraphicsConfigInfo gcInfo = new GraphicsConfigInfo(); - gcInfo.setFBConfig(pFormatInfo[0]); - gcInfo.setRequestedStencilSize(attrList[STENCIL_SIZE]); - Canvas3D.fbConfigTable.put(gc1, gcInfo); + GraphicsConfiguration gc1 = Win32GraphicsConfig.getConfig(gd, 0); + + // We need to cache the GraphicsTemplate3D and the private + // pixel format info. + synchronized (Canvas3D.graphicsConfigTable) { + if (Canvas3D.graphicsConfigTable.get(gc1) == null) { + GraphicsConfigInfo gcInfo = new GraphicsConfigInfo(template); + gcInfo.setPrivateData(new Long(pFormatInfo[0])); + Canvas3D.graphicsConfigTable.put(gc1, gcInfo); } else { freePixelFormatInfo(pFormatInfo[0]); } @@ -174,8 +172,7 @@ class NativeConfigTemplate3D { // System.out.println("NativeConfigTemplate3D : getStencilSize " + // attrList[STENCIL_SIZE]); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - int screen = nativeScreenInfo.getScreen(); + int screen = NativeScreenInfo.getScreen(gd); long[] pFormatInfo = new long[1]; @@ -220,8 +217,7 @@ class NativeConfigTemplate3D { Win32GraphicsDevice gd = (Win32GraphicsDevice)((Win32GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - int screen = nativeScreenInfo.getScreen(); + int screen = NativeScreenInfo.getScreen(gd); /* Fix to issue 77 */ return isSceneAntialiasingMultisampleAvailable(c3d.fbConfig, c3d.offScreen, screen); } diff --git a/src/classes/win32/javax/media/j3d/NativeScreenInfo.java b/src/classes/win32/javax/media/j3d/NativeScreenInfo.java index 2156b8f..9652b7a 100644 --- a/src/classes/win32/javax/media/j3d/NativeScreenInfo.java +++ b/src/classes/win32/javax/media/j3d/NativeScreenInfo.java @@ -16,18 +16,20 @@ import java.awt.GraphicsDevice; import sun.awt.Win32GraphicsDevice; class NativeScreenInfo { - private int display = 0; - private int screen = 0; - + private static final long display = 0; // unused for Win32 private static boolean wglARBChecked = false; private static boolean isWglARB; - private native static boolean queryWglARB(); + private static native boolean queryWglARB(); + + private NativeScreenInfo() { + throw new AssertionError("constructor should never be called"); + } // This method will return true if wglGetExtensionsStringARB is supported, // else return false - synchronized static boolean isWglARB() { + static synchronized boolean isWglARB() { if (!wglARBChecked) { // Query for wglGetExtensionsStringARB support. @@ -37,21 +39,14 @@ class NativeScreenInfo { return isWglARB; } - NativeScreenInfo(GraphicsDevice graphicsDevice) { - // Get the screen number - screen = ((sun.awt.Win32GraphicsDevice)graphicsDevice).getScreen(); - display = screen; - } - - int getDisplay() { + static long getDisplay() { return display; } - int getScreen() { - return screen; + static int getScreen(GraphicsDevice graphicsDevice) { + return ((Win32GraphicsDevice)graphicsDevice).getScreen(); } - // Ensure that the native libraries are loaded static { VirtualUniverse.loadLibraries(); diff --git a/src/classes/win32/javax/media/j3d/NativeWSInfo.java b/src/classes/win32/javax/media/j3d/NativeWSInfo.java deleted file mode 100644 index aca9c26..0000000 --- a/src/classes/win32/javax/media/j3d/NativeWSInfo.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -package javax.media.j3d; - -import java.awt.*; -import java.awt.event.*; -import sun.awt.*; -import java.lang.reflect.Method; - -class NativeWSInfo { - - //Win32DrawingSurface wds; - Object wds; - - void getCanvasWSParameters(Canvas3D canvas) { - //canvas.window = wds.getHDC(); - try { - Class win32DSclass = Class.forName("sun.awt.Win32DrawingSurface"); - Method getHDC = win32DSclass.getDeclaredMethod("getHDC", null ); - - canvas.window = ((Integer)getHDC.invoke( wds, null )).intValue(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - void getWSDrawingSurface(Object dsi) { - //wds = (Win32DrawingSurface)dsi.getSurface(); - int hwnd =0; - - try { - Class drawingSurfaceInfoClass = Class.forName("sun.awt.DrawingSurfaceInfo"); - Method getSurface = drawingSurfaceInfoClass.getDeclaredMethod( "getSurface", null); - - wds = getSurface.invoke( dsi, null ); - - Class win32DSclass = Class.forName("sun.awt.Win32DrawingSurface"); - Method getHWnd = win32DSclass.getDeclaredMethod("getHWnd", null ); - hwnd = ((Integer)getHWnd.invoke( wds, null )).intValue(); - } catch( Exception e ) { - e.printStackTrace(); - } - - // note: dsi lock is called from the caller of this method - // Workaround for bug 4169320 - //dsi.lock(); - //subclass(wds.getHWnd()); - subclass(hwnd); - //dsi.unlock(); - } - - // Used in workaround for bug 4169320: Resizing a Java 3D canvas - // on Win95 crashes the application - private native void subclass(int hWnd); - - int getCanvasVid(GraphicsConfiguration gcfg) { - return ((J3dGraphicsConfig) gcfg).getPixelFormat(); - } -} diff --git a/src/classes/solaris/javax/media/j3d/NativeConfigTemplate3D.java b/src/classes/x11/javax/media/j3d/NativeConfigTemplate3D.java index 6f116cf..cbd3713 100644 --- a/src/classes/solaris/javax/media/j3d/NativeConfigTemplate3D.java +++ b/src/classes/x11/javax/media/j3d/NativeConfigTemplate3D.java @@ -44,8 +44,8 @@ class NativeConfigTemplate3D { int[] attrList, long[] fbConfig); // Native method to free an GLXFBConfig struct. This is static since it - // may need to be called to clean up the Canvas3D fbConfigTable after the - // NativeConfigTemplate3D has been disposed of. + // may need to be called to clean up the Canvas3D graphicsConfigTable + // after the NativeConfigTemplate3D has been disposed of. static native void freeFBConfig(long fbConfig); // Native methods to return whether a particular attribute is available @@ -58,9 +58,8 @@ class NativeConfigTemplate3D { /* * Chooses the best FBConfig for Java 3D apps. */ - GraphicsConfiguration - getBestConfiguration(GraphicsConfigTemplate3D template, - GraphicsConfiguration[] gc) { + GraphicsConfiguration getBestConfiguration(GraphicsConfigTemplate3D template, + GraphicsConfiguration[] gc) { X11GraphicsDevice gd = (X11GraphicsDevice)((X11GraphicsConfig)gc[0]).getDevice(); @@ -69,10 +68,8 @@ class NativeConfigTemplate3D { return null; } - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); + long display = NativeScreenInfo.getDisplay(); + int screen = NativeScreenInfo.getScreen(gd); if (debug) { System.out.println(" NativeConfigTemplate3D: using device " + gd); @@ -125,34 +122,42 @@ class NativeConfigTemplate3D { if (visID == 0 || fbConfig[0] == 0) { return null; // no valid visual was found - } + } // search list of graphics configurations for config // with matching visualId - GraphicsConfiguration gc1 = null; - for (int i = 0; i < gc.length; i++) + X11GraphicsConfig gc0 = null; + for (int i = 0; i < gc.length; i++) { if (((X11GraphicsConfig)gc[i]).getVisual() == visID) { - gc1 = gc[i]; + gc0 = (X11GraphicsConfig)gc[i]; break; } - - // To support disabling Solaris OpenGL Xinerama mode, we need to cache - // the pointer to the actual GLXFBConfig that glXChooseFBConfig() - // returns, since this is not cached with X11GraphicsConfig and there - // are no public constructors to allow us to extend it. - synchronized (Canvas3D.fbConfigTable) { - if (Canvas3D.fbConfigTable.get(gc1) == null) { - GraphicsConfigInfo gcInfo = new GraphicsConfigInfo(); - gcInfo.setFBConfig(fbConfig[0]); - gcInfo.setRequestedStencilSize(attrList[STENCIL_SIZE]); - Canvas3D.fbConfigTable.put(gc1, gcInfo); + } + + // Just return if we didn't find a match + if (gc0 == null) { + return null; + } + + // Create a new GraphicsConfig object based on the one we found + X11GraphicsConfig gc1 = + X11GraphicsConfig.getConfig(gd, gc0.getVisual(), + gc0.getDepth(), gc0.getColormap(), false); + + // We need to cache the GraphicsTemplate3D and the private + // fbconfig info. + synchronized (Canvas3D.graphicsConfigTable) { + if (Canvas3D.graphicsConfigTable.get(gc1) == null) { + GraphicsConfigInfo gcInfo = new GraphicsConfigInfo(template); + gcInfo.setPrivateData(new Long(fbConfig[0])); + Canvas3D.graphicsConfigTable.put(gc1, gcInfo); } else { freeFBConfig(fbConfig[0]); } } return gc1; } - + /* * Determine if a given GraphicsConfiguration object can be used * by Java 3D. @@ -167,10 +172,8 @@ class NativeConfigTemplate3D { return false; } - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); + long display = NativeScreenInfo.getDisplay(); + int screen = NativeScreenInfo.getScreen(gd); int[] attrList; // holds the list of attributes to be tramslated // for glxChooseVisual call @@ -206,10 +209,9 @@ class NativeConfigTemplate3D { X11GraphicsDevice gd = (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); + long display = NativeScreenInfo.getDisplay(); + int screen = NativeScreenInfo.getScreen(gd); int vid = ((X11GraphicsConfig)gc).getVisual(); return isStereoAvailable(display, screen, vid); @@ -221,10 +223,9 @@ class NativeConfigTemplate3D { X11GraphicsDevice gd = (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); + long display = NativeScreenInfo.getDisplay(); + int screen = NativeScreenInfo.getScreen(gd); int vid = ((X11GraphicsConfig)gc).getVisual(); return getStencilSize(display, screen, vid); @@ -236,10 +237,9 @@ class NativeConfigTemplate3D { X11GraphicsDevice gd = (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); + long display = NativeScreenInfo.getDisplay(); + int screen = NativeScreenInfo.getScreen(gd); int vid = ((X11GraphicsConfig)gc).getVisual(); return isDoubleBufferAvailable(display, screen, vid); @@ -251,10 +251,9 @@ class NativeConfigTemplate3D { X11GraphicsDevice gd = (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); + long display = NativeScreenInfo.getDisplay(); + int screen = NativeScreenInfo.getScreen(gd); int vid = ((X11GraphicsConfig)gc).getVisual(); return isSceneAntialiasingAccumAvailable(display, screen, vid); @@ -267,10 +266,9 @@ class NativeConfigTemplate3D { X11GraphicsDevice gd = (X11GraphicsDevice)((X11GraphicsConfig)gc).getDevice(); - NativeScreenInfo nativeScreenInfo = new NativeScreenInfo(gd); - long display = nativeScreenInfo.getDisplay(); - int screen = nativeScreenInfo.getScreen(); + long display = NativeScreenInfo.getDisplay(); + int screen = NativeScreenInfo.getScreen(gd); int vid = ((X11GraphicsConfig)gc).getVisual(); return isSceneAntialiasingMultisampleAvailable(display, screen, vid); diff --git a/src/classes/solaris/javax/media/j3d/NativeScreenInfo.java b/src/classes/x11/javax/media/j3d/NativeScreenInfo.java index c84e8fe..85d2d3c 100644 --- a/src/classes/solaris/javax/media/j3d/NativeScreenInfo.java +++ b/src/classes/x11/javax/media/j3d/NativeScreenInfo.java @@ -16,54 +16,50 @@ import java.awt.GraphicsDevice; import sun.awt.X11GraphicsDevice; class NativeScreenInfo { - private int screen; private static long display = 0; private static boolean glxChecked = false; private static boolean isGLX13; - private native static long openDisplay(); - private native static int getDefaultScreen(long display); - private native static boolean queryGLX13(long display); + private static native long openDisplay(); + private static native boolean queryGLX13(long display); + + private NativeScreenInfo() { + throw new AssertionError("constructor should never be called"); + } // Fix for issue 20. // This method will return true if glx version is 1.3 or higher, // else return false. - synchronized static boolean isGLX13() { + static synchronized boolean isGLX13() { if (!glxChecked) { // Open a new static display connection if one is not already opened. getStaticDisplay(); - // Query for glx1.3 support. - isGLX13 = queryGLX13(display); + + // Query for glx1.3 support. + isGLX13 = queryGLX13(getDisplay()); glxChecked = true; } return isGLX13; } - synchronized static long getStaticDisplay() { + private static synchronized long getStaticDisplay() { if (display == 0) { display = openDisplay(); } return display; } - NativeScreenInfo(GraphicsDevice graphicsDevice) { + static long getDisplay() { // Open a new static display connection if one is not already opened - getStaticDisplay(); - - // Get the screen number - screen = ((X11GraphicsDevice)graphicsDevice).getScreen(); + return getStaticDisplay(); } - long getDisplay() { - return display; - } - - int getScreen() { - return screen; + static int getScreen(GraphicsDevice graphicsDevice) { + // Get the screen number + return ((X11GraphicsDevice)graphicsDevice).getScreen(); } - // Ensure that the native libraries are loaded static { VirtualUniverse.loadLibraries(); |