From 54d0ff131097a2cd9a91a0c1dd84deb8b1f7d0ac Mon Sep 17 00:00:00 2001
From: Sven Gothel GL_ARB_half_float_vertex
; GL_NV_half_float
; GL_ARB_half_float_pixel
,
+ earmarked for ES 3.0 (hence kept in GL while fixing Bug 590) */
+ public static final int GL_HALF_FLOAT = 0x140B;
public void glClearDepth( double depth );
diff --git a/make/config/jogl/gl-if-gl-ignores.cfg b/make/config/jogl/gl-if-gl-ignores.cfg
index 220bd74bf..25fbd5a6f 100644
--- a/make/config/jogl/gl-if-gl-ignores.cfg
+++ b/make/config/jogl/gl-if-gl-ignores.cfg
@@ -32,13 +32,19 @@ IgnoreExtension GL_EXT_debug_marker
IgnoreExtension GL_EXT_debug_label
IgnoreExtension GL_EXT_multisampled_render_to_texture
IgnoreExtension GL_EXT_framebuffer_multisample
-
+IgnoreExtension GL_OES_texture_half_float
+IgnoreExtension GL_OES_vertex_half_float
# IgnoreExtension GL_EXT_texture_storage
IgnoreExtension GL_NV_draw_buffers
IgnoreExtension GL_NV_fbo_color_attachments
IgnoreExtension GL_OES_vertex_array_object
IgnoreExtension GL_OES_texture_3D
-# above ext are subsumed, so ignore the aliased ones
+
+# includes GL_STATE_RESTORE, which hasn't the QCOM suffix
+IgnoreExtension GL_QCOM_extended_get
+Ignore GL_STATE_RESTORE
+
+# above ext mightbe subsumed, ignore the aliased ones
Ignore GL_ACTIVE_PROGRAM
Ignore GL_ALPHA16F
Ignore GL_ALPHA32F
@@ -156,10 +162,6 @@ Ignore glPushGroupMarkerEXT
# isn't included in GL2
Ignore GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET
-# includes GL_STATE_RESTORE, which hasn't the QCOM suffix
-IgnoreExtension GL_QCOM_extended_get
-Ignore GL_STATE_RESTORE
-
Ignore GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
Ignore GL_ACTIVE_ATTRIBUTES
Ignore GL_ACTIVE_UNIFORM_MAX_LENGTH
@@ -348,36 +350,6 @@ Ignore GL_NORMAL_ARRAY_TYPE
Ignore GL_NORMALIZE
Ignore GL_NORMAL_MAP_OES
Ignore GL_NUM_SHADER_BINARY_FORMATS
-Ignore GL_OES_blend_equation_separate
-Ignore GL_OES_blend_func_separate
-Ignore GL_OES_blend_subtract
-Ignore GL_OES_byte_coordinates
-Ignore GL_OES_compressed_ETC1_RGB8_texture
-Ignore GL_OES_compressed_paletted_texture
-Ignore GL_OES_depth24
-Ignore GL_OES_depth32
-Ignore GL_OES_draw_texture
-Ignore GL_OES_element_index_uint
-Ignore GL_OES_extended_matrix_palette
-Ignore GL_OES_fbo_render_mipmap
-Ignore GL_OES_fixed_point
-Ignore GL_OES_framebuffer_object
-Ignore GL_OES_matrix_get
-Ignore GL_OES_matrix_palette
-Ignore GL_OES_point_size_array
-Ignore GL_OES_point_sprite
-Ignore GL_OES_query_matrix
-Ignore GL_OES_read_format
-Ignore GL_OES_single_precision
-Ignore GL_OES_stencil1
-Ignore GL_OES_stencil4
-Ignore GL_OES_stencil8
-Ignore GL_OES_stencil_wrap
-Ignore GL_OES_texture_cube_map
-Ignore GL_OES_texture_env_crossbar
-Ignore GL_OES_texture_half_float
-Ignore GL_OES_texture_mirrored_repeat
-Ignore GL_OES_vertex_half_float
Ignore GL_ONE_MINUS_CONSTANT_ALPHA
Ignore GL_ONE_MINUS_CONSTANT_COLOR
Ignore GL_OPERAND0_ALPHA
diff --git a/make/config/jogl/gl-if-gl2_es2.cfg b/make/config/jogl/gl-if-gl2_es2.cfg
index 6a8aef06b..85e799298 100644
--- a/make/config/jogl/gl-if-gl2_es2.cfg
+++ b/make/config/jogl/gl-if-gl2_es2.cfg
@@ -35,6 +35,8 @@ IgnoreExtension GL_EXT_discard_framebuffer
IgnoreExtension GL_OES_compressed_paletted_texture
IgnoreExtension GL_OES_compressed_ETC1_RGB8_texture
IgnoreExtension GL_OES_vertex_array_object
+IgnoreExtension GL_OES_texture_half_float
+IgnoreExtension GL_OES_vertex_half_float
IgnoreExtension GL_OES_EGL_image_external
IgnoreExtension GL_EXT_debug_marker
IgnoreExtension GL_EXT_debug_label
diff --git a/make/scripts/cmpOld2New.sh b/make/scripts/cmpOld2New.sh
index 4394fe7b5..7d68cfc84 100755
--- a/make/scripts/cmpOld2New.sh
+++ b/make/scripts/cmpOld2New.sh
@@ -2,8 +2,8 @@
dirscript=`dirname $0`
-dirold=../build-x86_64-old/jogl/gensrc/classes/javax/media/opengl/
-dirnew=../build-x86_64/jogl/gensrc/classes/javax/media/opengl/
+dirold=../build-old/jogl/gensrc/classes/javax/media/opengl/
+dirnew=../build/jogl/gensrc/classes/javax/media/opengl/
dircmp=cmp-old2new
rm -rf $dircmp
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
index 32391c650..8401b9cd2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
@@ -43,6 +43,7 @@ import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLES2;
import javax.media.opengl.GLException;
import java.nio.*;
@@ -456,6 +457,7 @@ public class GLBuffers extends Buffers {
case GL.GL_SHORT:
case GL.GL_UNSIGNED_SHORT:
case GL.GL_HALF_FLOAT:
+ case GLES2.GL_HALF_FLOAT_OES:
esize = 2;
break;
case GL2ES2.GL_INT:
--
cgit v1.2.3
From 7f341c7bc0d0f5770191bb58f2c0053c3453bc8a Mon Sep 17 00:00:00 2001
From: Sven Gothel
+ jar/jogl-all.jar,
+ jar/jogl-test.jar">
@@ -43,8 +43,8 @@ JOGL NEWT JNLP Applet Runner Special Keys:
pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
archive="jar/applet-launcher.jar,
jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar"
+ jar/jogl-all.jar,
+ jar/jogl-test.jar"
codebase_lookup" value="false"
subapplet.classname="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run"
subapplet.displayname="JOGL GearsES2 Applet"
@@ -75,8 +75,8 @@ The applet above is instantiated with the following code:
<param name="code" value="org.jdesktop.applet.util.JNLPAppletLauncher">
<param name="archive" value="jar/applet-launcher.jar,
jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar">
+ jar/jogl-all.jar,
+ jar/jogl-test.jar">
<param name="codebase_lookup" value="false">
<param name="subapplet.classname" value="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run">
<param name="subapplet.displayname" value="JOGL GearsES2 Applet">
@@ -97,8 +97,8 @@ The applet above is instantiated with the following code:
pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
archive="jar/applet-launcher.jar,
jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar"
+ jar/jogl-all.jar,
+ jar/jogl-test.jar"
codebase_lookup" value="false"
subapplet.classname="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run"
subapplet.displayname="JOGL GearsES2 Applet"
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet.html b/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet.html
index 9db6d8cc2..37473befe 100644
--- a/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet.html
+++ b/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet.html
@@ -20,8 +20,8 @@ JOGL NEWT Applet Runner Special Keys:
width="200" height="200">
+ jar/jogl-all.jar,
+ jar/jogl-test.jar">
@@ -34,8 +34,8 @@ JOGL NEWT Applet Runner Special Keys:
type="application/x-java-applet;version=1.6"
pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
archive="jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar"
+ jar/jogl-all.jar,
+ jar/jogl-test.jar"
java_arguments="-Dsun.java2d.noddraw=true"
gl_event_listener_class="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"
gl_profile="GL2ES2"
@@ -58,8 +58,8 @@ The applet above is instantiated with the following code:
width="200" height="200">
<param name="code" value="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run">
<param name="archive" value="jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar">
+ jar/jogl-all.jar,
+ jar/jogl-test.jar">
<param name="java_arguments" value="-Dsun.java2d.noddraw=true">
<param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2">
<param name="gl_profile" value="GL2ES2">
@@ -72,8 +72,8 @@ The applet above is instantiated with the following code:
type="application/x-java-applet;version=1.6"
pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
archive="jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar"
+ jar/jogl-all.jar,
+ jar/jogl-test.jar"
java_arguments="-Dsun.java2d.noddraw=true"
gl_event_listener_class="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"
gl_profile="GL2ES2"
@@ -90,7 +90,7 @@ The applet above is instantiated with the following code:
-Note that the jogl.test.jar, which contains the test applet class, +Note that the jogl-test.jar, which contains the test applet class, does not need to be signed! JogAmp Community signs jogl.jar and gluegen-rt.jar, which contain JOGL's supporting classes; this is the only diff --git a/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet2.html b/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet2.html index ba2f69ef4..63df4ed60 100644 --- a/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet2.html +++ b/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet2.html @@ -21,8 +21,8 @@ If Applet is out of browser window, it is closeable. width="200" height="200"> + jar/jogl-all.jar, + jar/jogl-test.jar"> @@ -36,8 +36,8 @@ If Applet is out of browser window, it is closeable. type="application/x-java-applet;version=1.6" pluginspage="http://java.sun.com/javase/downloads/ea.jsp" archive="jar/gluegen-rt.jar, - jar/jogl.all.jar, - jar/jogl.test.jar" + jar/jogl-all.jar, + jar/jogl-test.jar" java_arguments="-Dsun.java2d.noddraw=true" gl_event_listener_class="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2" gl_profile="GL2ES2" @@ -61,8 +61,8 @@ The applet above is instantiated with the following code: width="200" height="200"> <param name="code" value="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run"> <param name="archive" value="jar/gluegen-rt.jar, - jar/jogl.all.jar, - jar/jogl.test.jar"> + jar/jogl-all.jar, + jar/jogl-test.jar"> <param name="java_arguments" value="-Dsun.java2d.noddraw=true"> <param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"> <param name="gl_profile" value="GL2ES2"> @@ -76,8 +76,8 @@ The applet above is instantiated with the following code: type="application/x-java-applet;version=1.6" pluginspage="http://java.sun.com/javase/downloads/ea.jsp" archive="jar/gluegen-rt.jar, - jar/jogl.all.jar, - jar/jogl.test.jar" + jar/jogl-all.jar, + jar/jogl-test.jar" java_arguments="-Dsun.java2d.noddraw=true" gl_event_listener_class="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2" gl_profile="GL2ES2" @@ -95,7 +95,7 @@ The applet above is instantiated with the following code:
-Note that the jogl.test.jar, which contains the test applet class,
+Note that the jogl-test.jar, which contains the test applet class,
does not need to be signed! JogAmp Community signs
jogl.jar and gluegen-rt.jar, which contain
JOGL's supporting classes; this is the only
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-normal.html b/jnlp-files/jogl-applet-runner-newt-gears-normal.html
index c8d654dbc..a6dd16a0c 100644
--- a/jnlp-files/jogl-applet-runner-newt-gears-normal.html
+++ b/jnlp-files/jogl-applet-runner-newt-gears-normal.html
@@ -35,8 +35,8 @@ JOGL NEWT JNLP Applet Runner Special Keys:
+ jar/jogl-all.jar,
+ jar/jogl-test.jar">
@@ -58,8 +58,8 @@ JOGL NEWT JNLP Applet Runner Special Keys:
pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
archive="jar/applet-launcher.jar,
jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar"
+ jar/jogl-all.jar,
+ jar/jogl-test.jar"
codebase_lookup" value="false"
subapplet.classname="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run"
subapplet.displayname="JOGL GearsES2 Applet"
@@ -91,8 +91,8 @@ The applet above is instantiated with the following code:
<param name="code" value="org.jdesktop.applet.util.JNLPAppletLauncher">
<param name="archive" value="jar/applet-launcher.jar,
jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar">
+ jar/jogl-all.jar,
+ jar/jogl-test.jar">
<param name="codebase_lookup" value="false">
<param name="subapplet.classname" value="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run">
<param name="subapplet.displayname" value="JOGL GearsES2 Applet">
@@ -114,8 +114,8 @@ The applet above is instantiated with the following code:
pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
archive="jar/applet-launcher.jar,
jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar"
+ jar/jogl-all.jar,
+ jar/jogl-test.jar"
codebase_lookup" value="false"
subapplet.classname="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run"
subapplet.displayname="JOGL GearsES2 Applet"
@@ -154,7 +154,7 @@ Where the referenced JNLP file jogl-applet-runner-newt.jnlp looks as fo
<resources>
<j2se href="http://java.sun.com/products/autodl/j2se" version="1.4+"/>
<property name="sun.java2d.noddraw" value="true"/>
- <jar href="jar/jogl.test.jar" main="true"/>
+ <jar href="jar/jogl-test.jar" main="true"/>
<extension name="jogl-all-awt" href="http://jogamp.org/deployment/jogamp-current/jogl-all-awt.jnlp" />
</resources>
@@ -170,7 +170,7 @@ Where the referenced JNLP file jogl-applet-runner-newt.jnlp looks as fo
-Note that the jogl.test.jar, which contains the test applet class,
+Note that the jogl-test.jar, which contains the test applet class,
does not need to be signed! JogAmp Community signs
applet-launcher.jar, jogl.jar and gluegen-rt.jar, which contain the
JNLPAppletLauncher and JOGL's supporting classes; this is the only
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-special-napplet.html b/jnlp-files/jogl-applet-runner-newt-gears-special-napplet.html
index 3c1895b45..7df167844 100644
--- a/jnlp-files/jogl-applet-runner-newt-gears-special-napplet.html
+++ b/jnlp-files/jogl-applet-runner-newt-gears-special-napplet.html
@@ -11,8 +11,8 @@ JOGL NEWT JNLP Applet Runner Special Keys:
width="1" height="1">
+ jar/jogl-all.jar,
+ jar/jogl-test.jar">
@@ -32,8 +32,8 @@ JOGL NEWT JNLP Applet Runner Special Keys:
type="application/x-java-applet;version=1.6"
pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
archive="jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar"
+ jar/jogl-all.jar,
+ jar/jogl-test.jar"
java_arguments="-Dsun.java2d.noddraw=true"
gl_event_listener_class="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"
gl_profile="GL2ES2"
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-special.html b/jnlp-files/jogl-applet-runner-newt-gears-special.html
index dcbe898e2..0f5911414 100644
--- a/jnlp-files/jogl-applet-runner-newt-gears-special.html
+++ b/jnlp-files/jogl-applet-runner-newt-gears-special.html
@@ -12,8 +12,8 @@ JOGL NEWT JNLP Applet Runner Special Keys:
+ jar/jogl-all.jar,
+ jar/jogl-test.jar">
@@ -42,8 +42,8 @@ JOGL NEWT JNLP Applet Runner Special Keys:
pluginspage="http://java.sun.com/javase/downloads/ea.jsp"
archive="jar/applet-launcher.jar,
jar/gluegen-rt.jar,
- jar/jogl.all.jar,
- jar/jogl.test.jar"
+ jar/jogl-all.jar,
+ jar/jogl-test.jar"
codebase_lookup" value="false"
subapplet.classname="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run"
subapplet.displayname="JOGL GearsES2 Applet Transparent"
diff --git a/jnlp-files/jogl-applet-runner-newt.jnlp b/jnlp-files/jogl-applet-runner-newt.jnlp
index 259e39f18..c33e1b761 100644
--- a/jnlp-files/jogl-applet-runner-newt.jnlp
+++ b/jnlp-files/jogl-applet-runner-newt.jnlp
@@ -12,7 +12,7 @@
- * FIXME: Still needs AWT for threading impl.,
+ * FIXME: Still needs AWT for threading impl.,
* ie. will issue a 'wrong thread' error if runs in headless mode!
*
+ * FIXME: If this instance runs in multithreading mode, see {@link Threading#isSingleThreaded()} (impossible),
+ * proper recursive locking is required for drawable/context @ destroy and display.
+ * Recreation etc could pull those instances while animating!
+ * Simply locking before using drawable/context offthread
+ * would allow a deadlock situation!
+ *
- * Also disposes of the SWT component.
+ * This impl. calls this class's {@link #dispose()} SWT override,
+ * where the actual implementation resides.
+ *
- * TODO: should this be moved to {@link Threading}?
- *
+ * FIXME: Redundant .. remove! Merge isRenderThread, runInGLThread and runInDesignatedGLThread
+ *
* @return true if the calling thread is the correct thread to execute OpenGL calls in, false otherwise.
*/
protected boolean isRenderThread() {
@@ -494,13 +498,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/**
* Runs the specified action in the designated OpenGL thread. If the current thread is designated, then the
* syncAction is run synchronously, otherwise the asyncAction is dispatched to the appropriate worker thread.
- *
+ *
* @param asyncAction
* The non-null action to dispatch to an OpenGL worker thread. This action should not assume that a
* GLContext is current when invoked.
* @param syncAction
* The non-null action to run synchronously if the current thread is designated to handle OpenGL calls.
* This action may assume the GLContext is current.
+ * FIXME: Redundant .. remove! Merge isRenderThread, runInGLThread and runInDesignatedGLThread
*/
private void runInGLThread(final Runnable asyncAction, final Runnable syncAction) {
if (Threading.isSingleThreaded() && !isRenderThread()) {
@@ -515,9 +520,10 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/**
* Dispatches the specified runnable to the appropriate OpenGL worker thread (either the SWT event dispatch thread,
* or the OpenGL worker thread depending on the state of {@link #useSWTThread}).
- *
+ *
* @param makeCurrentAndRunAction
* The non-null action to dispatch.
+ * FIXME: Redundant .. remove! Merge isRenderThread, runInGLThread and runInDesignatedGLThread
*/
private void runInDesignatedGLThread(final Runnable makeCurrentAndRunAction) {
if (ThreadingImpl.getMode() != ThreadingImpl.Mode.ST_WORKER) {
@@ -529,7 +535,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
}
-
+
public static void main(final String[] args) {
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
@@ -537,7 +543,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
System.err.println(JoglVersion.getInstance());
System.err.println(JoglVersion.getDefaultOpenGLInfo(null).toString());
-
+
final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
final Display display = new Display();
final Shell shell = new Shell(display);
@@ -547,13 +553,17 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
final GLCanvas canvas = new GLCanvas(shell, 0, caps, null, null);
canvas.addGLEventListener(new GLEventListener() {
+ @Override
public void init(final GLAutoDrawable drawable) {
GL gl = drawable.getGL();
System.err.println(JoglVersion.getGLInfo(gl, null));
}
- public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ @Override
public void display(final GLAutoDrawable drawable) {}
- public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
});
shell.open();
canvas.display();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAWT01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAWT01GLn.java
deleted file mode 100644
index 021e1178a..000000000
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAWT01GLn.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.jogl.swt;
-
-import java.awt.Frame;
-import java.lang.reflect.InvocationTargetException;
-
-import javax.media.opengl.GL2ES1;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLProfile;
-import javax.media.opengl.awt.GLCanvas;
-
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.awt.SWT_AWT;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.After;
-import org.junit.Test;
-
-import com.jogamp.nativewindow.swt.SWTAccessor;
-import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-
-/**
- * Tests that a basic SWT app can open without crashing under different GL profiles. Uses the AWT GL canvas with
- * the SWT_AWT bridge.
- * @author Wade Walker, et.al.
- */
-public class TestSWTAWT01GLn extends UITestCase {
-
- static final int duration = 250;
-
- Display display = null;
- Shell shell = null;
- Composite composite = null;
- Frame frame = null;
- GLCanvas glcanvas = null;
-
- @BeforeClass
- public static void startup() {
- System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() );
- if(!GLProfile.isAvailable(GLProfile.GL2)) {
- setTestSupported(false);
- }
- }
-
- @Before
- public void init() throws InterruptedException, InvocationTargetException {
- SWTAccessor.invoke(true, new Runnable() {
- public void run() {
- display = new Display();
- Assert.assertNotNull( display );
- shell = new Shell( display );
- Assert.assertNotNull( shell );
- shell.setLayout( new FillLayout() );
- composite = new Composite( shell, SWT.EMBEDDED | SWT.NO_BACKGROUND );
- composite.setLayout( new FillLayout() );
- Assert.assertNotNull( composite );
- frame = SWT_AWT.new_Frame( composite );
- Assert.assertNotNull( frame );
- }});
- }
-
- @After
- public void release() throws InterruptedException, InvocationTargetException {
- Assert.assertNotNull( display );
- Assert.assertNotNull( shell );
- Assert.assertNotNull( composite );
- Assert.assertNotNull( glcanvas );
- javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
- public void run() {
- frame.setVisible(false);
- frame.remove(glcanvas);
- frame.dispose();
- frame = null;
- glcanvas = null;
- }});
-
- SWTAccessor.invoke(true, new Runnable() {
- public void run() {
- composite.dispose();
- shell.close();
- shell.dispose();
- display.dispose();
- display = null;
- shell = null;
- composite = null;
- }});
- }
-
- protected void runTestGL( GLProfile glprofile ) throws InterruptedException {
- GLCapabilities glcapabilities = new GLCapabilities( glprofile );
- glcanvas = new GLCanvas( glcapabilities );
- Assert.assertNotNull( glcanvas );
- frame.add( glcanvas );
-
- glcanvas.addGLEventListener( new GLEventListener() {
- /* @Override */
- public void init( GLAutoDrawable glautodrawable ) {
- }
-
- /* @Override */
- public void dispose( GLAutoDrawable glautodrawable ) {
- }
-
- /* @Override */
- public void display( GLAutoDrawable glautodrawable ) {
- Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() );
- GL2ES1 gl = glautodrawable.getGL().getGL2ES1();
- OneTriangle.render( gl, rectangle.width, rectangle.height );
- }
-
- /* @Override */
- public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) {
- Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() );
- GL2ES1 gl = glautodrawable.getGL().getGL2ES1();
- OneTriangle.setup( gl, rectangle.width, rectangle.height );
- }
- });
-
- SWTAccessor.invoke(true, new Runnable() {
- public void run() {
- shell.setText( getClass().getName() );
- shell.setSize( 640, 480 );
- shell.open();
- }});
-
- long lStartTime = System.currentTimeMillis();
- long lEndTime = lStartTime + duration;
- try {
- while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) {
- SWTAccessor.invoke(true, new Runnable() {
- public void run() {
- if( !display.readAndDispatch() ) {
- // blocks on linux .. display.sleep();
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) { }
- }
- }});
- }
- }
- catch( Throwable throwable ) {
- throwable.printStackTrace();
- Assume.assumeNoException( throwable );
- }
- }
-
- @Test
- public void test() throws InterruptedException {
- GLProfile glprofile = GLProfile.getGL2ES1();
- runTestGL( glprofile );
- }
-
- public static void main(String args[]) {
- org.junit.runner.JUnitCore.main( TestSWTAWT01GLn.class.getName() );
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
new file mode 100644
index 000000000..966b39c57
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.swt;
+
+import java.awt.Frame;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.awt.SWT_AWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.After;
+import org.junit.Test;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Tests that a basic SWT app can open without crashing under different GL profiles. Uses the AWT GL canvas with
+ * the SWT_AWT bridge.
+ * @author Wade Walker, et.al.
+ */
+public class TestSWTAccessor03AWTGLn extends UITestCase {
+
+ static final int duration = 250;
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite = null;
+ Frame frame = null;
+ GLCanvas glcanvas = null;
+
+ @BeforeClass
+ public static void startup() {
+ System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() );
+ if(!GLProfile.isAvailable(GLProfile.GL2)) {
+ setTestSupported(false);
+ }
+ }
+
+ @Before
+ public void init() throws InterruptedException, InvocationTargetException {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.EMBEDDED | SWT.NO_BACKGROUND );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ frame = SWT_AWT.new_Frame( composite );
+ Assert.assertNotNull( frame );
+ }});
+ }
+
+ @After
+ public void release() throws InterruptedException, InvocationTargetException {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ Assert.assertNotNull( glcanvas );
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ frame.remove(glcanvas);
+ frame.dispose();
+ frame = null;
+ glcanvas = null;
+ }});
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.close();
+ shell.dispose();
+ display.dispose();
+ display = null;
+ shell = null;
+ composite = null;
+ }});
+ }
+
+ protected void runTestGL( GLProfile glprofile ) throws InterruptedException {
+ GLCapabilities glcapabilities = new GLCapabilities( glprofile );
+ glcanvas = new GLCanvas( glcapabilities );
+ Assert.assertNotNull( glcanvas );
+ frame.add( glcanvas );
+
+ glcanvas.addGLEventListener( new GLEventListener() {
+ /* @Override */
+ public void init( GLAutoDrawable glautodrawable ) {
+ }
+
+ /* @Override */
+ public void dispose( GLAutoDrawable glautodrawable ) {
+ }
+
+ /* @Override */
+ public void display( GLAutoDrawable glautodrawable ) {
+ Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() );
+ GL2ES1 gl = glautodrawable.getGL().getGL2ES1();
+ OneTriangle.render( gl, rectangle.width, rectangle.height );
+ }
+
+ /* @Override */
+ public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) {
+ Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() );
+ GL2ES1 gl = glautodrawable.getGL().getGL2ES1();
+ OneTriangle.setup( gl, rectangle.width, rectangle.height );
+ }
+ });
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell.setText( getClass().getName() );
+ shell.setSize( 640, 480 );
+ shell.open();
+ }});
+
+ long lStartTime = System.currentTimeMillis();
+ long lEndTime = lStartTime + duration;
+ try {
+ while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) { }
+ }
+ }});
+ }
+ }
+ catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ @Test
+ public void test() throws InterruptedException {
+ GLProfile glprofile = GLProfile.getGL2ES1();
+ runTestGL( glprofile );
+ }
+
+ public static void main(String args[]) {
+ org.junit.runner.JUnitCore.main( TestSWTAccessor03AWTGLn.class.getName() );
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
new file mode 100644
index 000000000..addb14ce5
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
@@ -0,0 +1,174 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.swt;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.After;
+import org.junit.Test;
+
+import com.jogamp.opengl.swt.GLCanvas;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Tests that a basic SWT app can open without crashing under different GL profiles.
+ *
+ * Uses JOGL's new SWT GLCanvas.
+ *
+ * Holds AWT in it's test name, since our impl. still needs the AWT threading,
+ * see {@link GLCanvas}.
+ *
- * Holds AWT in it's test name, since our impl. still needs the AWT threading, - * see {@link GLCanvas}. - *
- * @author Wade Walker, et.al. - */ -public class TestSWTJOGLGLCanvas01GLnAWT extends UITestCase { - - static int duration = 250; - - static final int iwidth = 640; - static final int iheight = 480; - - Display display = null; - Shell shell = null; - Composite composite = null; - - @BeforeClass - public static void startup() { - System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); - } - - @Before - public void init() { - display = new Display(); - Assert.assertNotNull( display ); - shell = new Shell( display ); - Assert.assertNotNull( shell ); - shell.setLayout( new FillLayout() ); - composite = new Composite( shell, SWT.NONE ); - composite.setLayout( new FillLayout() ); - Assert.assertNotNull( composite ); - } - - @After - public void release() { - Assert.assertNotNull( display ); - Assert.assertNotNull( shell ); - Assert.assertNotNull( composite ); - try { - composite.dispose(); - shell.dispose(); - display.dispose(); - } - catch( Throwable throwable ) { - throwable.printStackTrace(); - Assume.assumeNoException( throwable ); - } - display = null; - shell = null; - composite = null; - } - - protected void runTestAGL( GLProfile glprofile ) throws InterruptedException { - // need SWT.NO_BACKGROUND to prevent SWT from clearing the window - // at the wrong times (we use glClear for this instead) - final GLCapabilitiesImmutable caps = new GLCapabilities( glprofile ); - - final GLCanvas canvas = new GLCanvas( composite, SWT.NO_BACKGROUND, caps, null, null); - Assert.assertNotNull( canvas ); - - canvas.addGLEventListener(new GLEventListener() { - public void init(final GLAutoDrawable drawable) { } - public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { - OneTriangle.setup( drawable.getGL().getGL2(), width, height ); - } - public void display(final GLAutoDrawable drawable) { - OneTriangle.render( drawable.getGL().getGL2(), drawable.getWidth(), drawable.getHeight()); - } - public void dispose(final GLAutoDrawable drawable) {} - }); - - shell.setText( getClass().getName() ); - shell.setSize( 640, 480 ); - shell.open(); - - long lStartTime = System.currentTimeMillis(); - long lEndTime = lStartTime + duration; - try { - while( (System.currentTimeMillis() < lEndTime) && !canvas.isDisposed() ) { - if( !display.readAndDispatch() ) { - // blocks on linux .. display.sleep(); - Thread.sleep(10); - } - } - } catch( Throwable throwable ) { - throwable.printStackTrace(); - Assume.assumeNoException( throwable ); - } - canvas.dispose(); - } - - @Test - public void test() throws InterruptedException { - GLProfile glprofile = GLProfile.getGL2ES1(); - runTestAGL( glprofile ); - } - - static int atoi(String a) { - int i=0; - try { - i = Integer.parseInt(a); - } catch (Exception ex) { ex.printStackTrace(); } - return i; - } - - public static void main(String args[]) { - for(int i=0; iARB_create_context
related: created via ARB_create_context. Cache key value. */
+ /** ARB_create_context
related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IS_ARB_CREATED = 1 << 0;
- /** ARB_create_context
related: compatibility profile. Cache key value. */
+ /** ARB_create_context
related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_COMPAT = 1 << 1;
- /** ARB_create_context
related: core profile. Cache key value. */
+ /** ARB_create_context
related: desktop core profile. Cache key value. See {@link #isGLCoreProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_CORE = 1 << 2;
- /** ARB_create_context
related: ES profile. Cache key value. */
+ /** ARB_create_context
related: ES profile. Cache key value. See {@link #isGLES()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_ES = 1 << 3;
- /** ARB_create_context
related: flag forward compatible. Cache key value. */
+ /** ARB_create_context
related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_OPTION_FORWARD = 1 << 4;
- /** ARB_create_context
related: flag debug. Not a cache key. */
+ /** ARB_create_context
related: flag debug. Not a cache key. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
- /** GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. */
+ /** GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
- /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. */
- protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
+ /** Context supports FBO, details see {@link #hasFBO()}.
+ * Not a cache key.
+ * @see #hasFBO()
+ * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
+ */
+ protected static final int CTX_IMPL_FBO = 1 << 9;
- private static ThreadLocal+ * If the context was current on this thread, it is being released before switching the drawable + * and made current afterwards. However the user shall take extra care that not other thread + * attempts to make this context current. Otherwise a race condition may happen. + *
+ *+ * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary + * switching the drawable of an already established GLContext, i.e. which is already made current once. + * FIXME: Validate functionality! + *
+ * @param readWrite the read/write drawable for framebuffer operations. + * @param setWriteOnly iftrue
and if the current read-drawable differs
+ * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}),
+ * only change the write-drawable. Otherwise set both drawables.
+ * @return the replaced read/write drawable
+ *
+ * @throws GLException in case null
is being passed or
+ * this context is made current on another thread.
+ *
+ * @see #isGLReadDrawableAvailable()
+ * @see #getGLReadDrawable()
+ * @see #setGLReadDrawable()
+ * @see #getGLDrawable()
+ */
+ public abstract GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly);
+
+ /**
+ * Returns the write-drawable this context uses for framebuffer operations.
*/
public abstract GLDrawable getGLDrawable();
/**
- * Return availability of GL read drawable.
- * @return true if a GL read drawable is supported with your driver, otherwise false.
+ * Query whether using a distinguished read-drawable is supported.
+ * @return true if using a read-drawable is supported with your driver/OS, otherwise false.
*/
public abstract boolean isGLReadDrawableAvailable();
/**
- * Set the read GLDrawable for read framebuffer operations.+ * If the context was current on this thread, it is being released before switching the drawable + * and made current afterwards. However the user shall take extra care that not other thread + * attempts to make this context current. Otherwise a race condition may happen. + *
* - * @param read the read GLDrawable for read framebuffer operations. - * If null is passed, the default write drawable will be set. + * @param read the read-drawable for read framebuffer operations. + * If null is passed, the default write drawable will be set. + * @return the replaced read-drawable * - * @throws GLException in case a read drawable is not supported - * and the given drawable is not null and not equal to the internal write drawable. + * @throws GLException in case a read drawable is not supported or + * this context is made current on another thread. * * @see #isGLReadDrawableAvailable() * @see #getGLReadDrawable() */ - public abstract void setGLReadDrawable(GLDrawable read); + public abstract GLDrawable setGLReadDrawable(GLDrawable read); /** - * Returns the read GLDrawable this context uses for read framebuffer operations. + * Returns the read-Drawable this context uses for read framebuffer operations. + *+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)}, + * it equals to the write-drawable (default). + *
* @see #isGLReadDrawableAvailable() * @see #setGLReadDrawable(javax.media.opengl.GLDrawable) + * @see #getGLDrawable() */ public abstract GLDrawable getGLReadDrawable(); @@ -190,7 +245,7 @@ public abstract class GLContext { * ** This method is blocking, i.e. waits until another thread has - * released the context. + * released the context. *
*
* The drawable's surface is being locked at entry
@@ -547,6 +602,28 @@ public abstract class GLContext {
return 0 != ( ctxOptions & CTX_IMPL_ES2_COMPAT ) ;
}
+ /**
+ * @return true if impl. is a hardware rasterizer, otherwise false.
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public final boolean isHardwareRasterizer() {
+ return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
+ }
+
+ /** Returns whether the context supports FBO, hence is either GL-ES >= 2.0, >= core GL 3.0 or implements the extensions
+ *
+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
+ *
+ * FBO support is queried as described in {@link GLContext#hasFBO()}.
+ * Includes [ GLES1, GLES2 ]. Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].
+ * Can be turned off with property
- * FIXME: Still needs AWT for threading impl.,
- * ie. will issue a 'wrong thread' error if runs in headless mode!
- *
* FIXME: If this instance runs in multithreading mode, see {@link Threading#isSingleThreaded()} (impossible),
* proper recursive locking is required for drawable/context @ destroy and display.
* Recreation etc could pull those instances while animating!
@@ -86,12 +82,6 @@ import com.jogamp.opengl.JoglVersion;
However, since the user shall stick to the GLEventListener model while utilizing
GLAutoDrawable implementations, she is safe due to the implicit locked state.
*
- * FIXME: [MT-2] Revise threading code
- The logic whether to spawn off the GL task and
- determination which thread to use is too complex and redundant.
- (See isRenderThread(), runInGLThread() and runInDesignatedGLThread())
- *
- * FIXME: Redundant .. remove! Merge isRenderThread, runInGLThread and runInDesignatedGLThread
- *
- * @return true if the calling thread is the correct thread to execute OpenGL calls in, false otherwise.
- */
- protected boolean isRenderThread() {
- if (Threading.isSingleThreaded()) {
- if (ThreadingImpl.getMode() != ThreadingImpl.Mode.ST_WORKER) {
- final Display display = getDisplay();
- return display != null && display.getThread() == Thread.currentThread();
- }
- return Threading.isOpenGLThread();
- }
- /*
- * For multi-threaded rendering, the render thread is not defined...
- */
- return true;
- }
-
- /**
- * Runs the specified action in the designated OpenGL thread. If the current thread is designated, then the
- * syncAction is run synchronously, otherwise the asyncAction is dispatched to the appropriate worker thread.
- *
- * @param asyncAction
- * The non-null action to dispatch to an OpenGL worker thread. This action should not assume that a
- * GLContext is current when invoked.
- * @param syncAction
- * The non-null action to run synchronously if the current thread is designated to handle OpenGL calls.
- * This action may assume the GLContext is current.
- * FIXME: Redundant .. remove! Merge isRenderThread, runInGLThread and runInDesignatedGLThread
+ * Runs the specified action in an SWT compatible thread, which is:
+ * GL_ARB_ES2_compatibility
, ARB_framebuffer_object
or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ * @see #CTX_IMPL_FBO
+ */
+ public final boolean hasFBO() {
+ return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
+ }
+
+ /**
+ * @return true if context supports GLSL
+ * @see GLProfile#hasGLSL()
+ */
public final boolean hasGLSL() {
return isGL2ES2() ;
}
@@ -555,60 +632,70 @@ public abstract class GLContext {
public boolean isNPOTTextureAvailable() {
return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two);
}
- private static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
public boolean isTextureFormatBGRA8888Available() {
return isGL2GL3() ||
- isExtensionAvailable("GL_EXT_texture_format_BGRA8888") ||
- isExtensionAvailable("GL_IMG_texture_format_BGRA8888") ;
+ isExtensionAvailable(GL_EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GL_IMG_texture_format_BGRA8888) ;
}
+ /** @see GLProfile#isGL4bc() */
public final boolean isGL4bc() {
return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & CTX_PROFILE_COMPAT);
}
+ /** @see GLProfile#isGL4() */
public final boolean isGL4() {
return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
}
+ /** @see GLProfile#isGL3bc() */
public final boolean isGL3bc() {
return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
&& 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & CTX_PROFILE_COMPAT);
}
+ /** @see GLProfile#isGL3() */
public final boolean isGL3() {
return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
&& 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
}
-
+
+ /** @see GLProfile#isGL2() */
public final boolean isGL2() {
return ctxMajorVersion>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT);
}
+ /** @see GLProfile#isGL2GL3() */
public final boolean isGL2GL3() {
return isGL2() || isGL3();
}
+ /** @see GLProfile#isGLES1() */
public final boolean isGLES1() {
return ctxMajorVersion==1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
}
+ /** @see GLProfile#isGLES2() */
public final boolean isGLES2() {
return ctxMajorVersion==2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
}
+ /** @see GLProfile#isGLES() */
public final boolean isGLES() {
return 0 != ( CTX_PROFILE_ES & ctxOptions ) ;
}
+ /** @see GLProfile#isGL2ES1() */
public final boolean isGL2ES1() {
return isGL2() || isGLES1() ;
}
+ /** @see GLProfile#isGL2ES2() */
public final boolean isGL2ES2() {
return isGL2GL3() || isGLES2() ;
}
@@ -846,8 +933,11 @@ public abstract class GLContext {
*/
private static /*final*/ HashSet0
+ */
+ protected static final int getAvailableContextProperties(final AbstractGraphicsDevice device, final GLProfile glp) {
+ final int[] reqMajorCTP = new int[] { 0, 0 };
+ getRequestMajorAndCompat(glp, reqMajorCTP);
+
+ int _major[] = { 0 };
+ int _minor[] = { 0 };
+ int _ctp[] = { 0 };
+ if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1],
+ _major, _minor, _ctp)) {
+ return _ctp[0];
+ }
+ return 0; // n/a
+ }
+
+ /**
+ * @param device the device the profile is being requested
* @param major Key Value either 1, 2, 3 or 4
* @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
- * @return the highest GLProfile string regarding the version and profile bits.
- * @throws GLException if version and context profile bits could not be mapped to a GLProfile
+ * @return the highest GLProfile regarding availability, version and profile bits.
*/
- public static String getAvailableGLProfile(AbstractGraphicsDevice device, int reqMajor, int reqProfile)
+ protected static GLProfile getAvailableGLProfile(AbstractGraphicsDevice device, int reqMajor, int reqProfile)
throws GLException {
int major[] = { 0 };
int minor[] = { 0 };
int ctp[] = { 0 };
if(GLContext.getAvailableGLVersion(device, reqMajor, reqProfile, major, minor, ctp)) {
- return GLContext.getGLProfile(major[0], minor[0], ctp[0]);
+ return GLProfile.get(GLContext.getGLProfile(major[0], minor[0], ctp[0]));
+ }
+ return null;
+ }
+
+ /**
+ * @param device the device the profile is being requested
+ * @param major Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ */
+ protected static String getAvailableGLVersionAsString(AbstractGraphicsDevice device, int major, int profile) {
+ int _major[] = { 0 };
+ int _minor[] = { 0 };
+ int _ctp[] = { 0 };
+ if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
+ return getGLVersion(_major[0], _minor[0], _ctp[0], null);
}
return null;
}
@@ -990,7 +1130,7 @@ public abstract class GLContext {
* @param isHardware return value of one boolean, whether the profile is a hardware rasterizer or not
* @return true if the requested GL version is available regardless of a software or hardware rasterizer, otherwise false.
*/
- public static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int reqMajor, int reqProfile, boolean isHardware[]) {
+ protected static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int reqMajor, int reqProfile, boolean isHardware[]) {
Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
if(null==valI) {
return false;
@@ -1027,21 +1167,7 @@ public abstract class GLContext {
return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware);
}
- /**
- * @param major Key Value either 1, 2, 3 or 4
- * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
- */
- public static String getAvailableGLVersionAsString(AbstractGraphicsDevice device, int major, int profile) {
- int _major[] = { 0 };
- int _minor[] = { 0 };
- int _ctp[] = { 0 };
- if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
- return getGLVersion(_major[0], _minor[0], _ctp[0], null);
- }
- return null;
- }
-
- public static String getGLVersion(int major, int minor, int ctp, String gl_version) {
+ protected static String getGLVersion(int major, int minor, int ctp, String gl_version) {
boolean needColon = false;
StringBuilder sb = new StringBuilder();
sb.append(major);
@@ -1055,6 +1181,7 @@ public abstract class GLContext {
needColon = appendString(sb, "arb", needColon, 0 != ( CTX_IS_ARB_CREATED & ctp ));
needColon = appendString(sb, "debug", needColon, 0 != ( CTX_OPTION_DEBUG & ctp ));
needColon = appendString(sb, "ES2 compatible", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "FBO", needColon, 0 != ( CTX_IMPL_FBO & ctp ));
if( 0 != ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
needColon = appendString(sb, "software", needColon, true);
} else {
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 1093685d6..d6480e7aa 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -492,6 +492,23 @@ public abstract class GLDrawableFactory {
GLContext shareWith)
throws GLException;
+ /**
+ * Returns true if it is possible to create an framebuffer object (FBO).
+ * null
for the platform's default device.
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasFBO()
+ */
+ public final boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp) {
+ return 0 != ( GLContext.CTX_IMPL_FBO & GLContext.getAvailableContextProperties(device, glp) );
+ }
+
//----------------------------------------------------------------------
// Methods for interacting with third-party OpenGL libraries
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index ed457b0ea..cc4f6c517 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -113,9 +113,7 @@ public class GLProfile {
* @param firstUIActionOnProcess Should be true
if called before the first UI action of the running program,
* otherwise false
.
*
- * @deprecated This method shall not need to be called for other reasons than having a defined initialization sequence.
- * To ensure homogeneous behavior with application not calling this method, you shall pass firstUIActionOnProcess=false
.
- * This method is subject to be removed in future versions of JOGL.
+ * @deprecated Use {@link #initSingleton()}. This method is subject to be removed in future versions of JOGL.
*/
public static void initSingleton(final boolean firstUIActionOnProcess) {
initLock.lock();
@@ -1003,6 +1001,11 @@ public class GLProfile {
public final boolean isGLES2() {
return GLES2 == profile;
}
+
+ /** Indicates whether this profile is capable of GLES. true
(default), bootstrapping the available GL profiles
+ * will use the highest compatible GL context for each profile,
+ * hence skipping querying lower profiles if a compatible higher one is found:
+ *
+ *
+ * Otherwise the dedicated GL context would be queried and used:
+ *
+ *
+ * Using aliasing speeds up initialization about:
+ *
+ *
jogl.debug.GLContext.NoProfileAliasing
.
+ *
+ *
+ * @see Platform#AWT_AVAILABLE
+ * @see Platform#getOSType()
*/
- private void runInGLThread(final Runnable asyncAction, final Runnable syncAction) {
- if (Threading.isSingleThreaded() && !isRenderThread()) {
- /* Run in designated GL thread */
- runInDesignatedGLThread(asyncAction);
+ private void runInGLThread(final Runnable action) {
+ if(Platform.OSType.MACOS == Platform.OS_TYPE) {
+ SWTAccessor.invoke(true, action);
} else {
- /* Run in current thread... */
- helper.invokeGL(drawable, context, syncAction, initAction);
+ Threading.invokeOnOpenGLThread(true, action);
}
}
- /**
- * Dispatches the specified runnable to the appropriate OpenGL worker thread (either the SWT event dispatch thread,
- * or the OpenGL worker thread depending on the state of {@link #useSWTThread}).
- *
- * @param makeCurrentAndRunAction
- * The non-null action to dispatch.
- * FIXME: Redundant .. remove! Merge isRenderThread, runInGLThread and runInDesignatedGLThread
- */
- private void runInDesignatedGLThread(final Runnable makeCurrentAndRunAction) {
- if (ThreadingImpl.getMode() != ThreadingImpl.Mode.ST_WORKER) {
- final Display display = getDisplay();
- assert display.getThread() != Thread.currentThread() : "Incorrect use of thread dispatching.";
- display.syncExec(makeCurrentAndRunAction);
- } else {
- Threading.invokeOnOpenGLThread(true, makeCurrentAndRunAction);
- }
- }
-
-
public static void main(final String[] args) {
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index f4309617b..735d85fb1 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -37,11 +37,13 @@ import org.eclipse.swt.widgets.Control;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowFactory;
+
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import jogamp.common.awt.AWTEDTExecutor;
import jogamp.nativewindow.macosx.OSXUtil;
public class SWTAccessor {
@@ -254,8 +256,25 @@ public class SWTAccessor {
});
}
+ /**
+ * Runs the specified action in an SWT compatible thread, which is:
+ *
+ *
+ *
+ *
+ *
+ * @see Platform#AWT_AVAILABLE
+ * @see Platform#getOSType()
+ */
public static void invoke(boolean wait, Runnable runnable) {
- if(Platform.OS_TYPE == Platform.OSType.MACOS) {
+ if( Platform.OS_TYPE == Platform.OSType.MACOS ) {
+ // Use SWT main thread! Only reliable config w/ -XStartOnMainThread !?
OSXUtil.RunOnMainThread(wait, runnable);
} else {
runnable.run();
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index 94f949ea3..2cd87f276 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -30,6 +30,7 @@ package jogamp.nativewindow.macosx;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.util.Point;
+import jogamp.common.awt.AWTEDTExecutor;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
@@ -111,6 +112,27 @@ public class OSXUtil {
return IsMainThread0();
}
+ /***
+ private static boolean isAWTEDTMainThreadInit = false;
+ private static boolean isAWTEDTMainThread;
+
+ public synchronized static boolean isAWTEDTMainThread() {
+ if(!isAWTEDTMainThreadInit) {
+ isAWTEDTMainThreadInit = true;
+ if(Platform.AWT_AVAILABLE) {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ isAWTEDTMainThread = IsMainThread();
+ System.err.println("XXX: "+Thread.currentThread().getName()+" - isAWTEDTMainThread "+isAWTEDTMainThread);
+ }
+ });
+ } else {
+ isAWTEDTMainThread = false;
+ }
+ }
+ return isAWTEDTMainThread;
+ } */
+
private static native boolean initIDs0();
private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
private static native long CreateNSView0(int x, int y, int width, int height);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java
index 0c350255e..2121205e2 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java
@@ -85,26 +85,17 @@ public class TestSWTAccessor02GLn extends UITestCase {
@Before
public void init() {
- final Display[] r = new Display[1];
- final Shell[] s = new Shell[1];
SWTAccessor.invoke(true, new Runnable() {
- public void run() {
- r[0] = new Display();
- s[0] = new Shell();
- }
- });
- display = r[0];
- shell = s[0];
- Assert.assertNotNull( display );
- Assert.assertNotNull( shell );
-
- SWTAccessor.invoke(true, new Runnable() {
- public void run() {
- shell.setLayout( new FillLayout() );
- composite = new Composite( shell, SWT.NONE );
- Assert.assertNotNull( composite );
- composite.setLayout( new FillLayout() );
- }});
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NONE );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ }});
}
@After
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
index 966b39c57..ad8da8ad0 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
@@ -75,7 +75,11 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
@BeforeClass
public static void startup() {
- System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() );
+ System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() );
+ Frame f0 = new Frame("Test - AWT 1st");
+ f0.add(new java.awt.Label("AWT was here 1st"));
+ f0.pack();
+ f0.setVisible(true);
if(!GLProfile.isAvailable(GLProfile.GL2)) {
setTestSupported(false);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java
index f38d5c7dc..0bd47c980 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java
@@ -53,6 +53,7 @@ import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Test;
+import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -81,14 +82,17 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
@Before
public void init() {
- display = new Display();
- Assert.assertNotNull( display );
- shell = new Shell( display );
- Assert.assertNotNull( shell );
- shell.setLayout( new FillLayout() );
- composite = new Composite( shell, SWT.NONE );
- composite.setLayout( new FillLayout() );
- Assert.assertNotNull( composite );
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NONE );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ }});
}
@After
@@ -97,9 +101,12 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
Assert.assertNotNull( shell );
Assert.assertNotNull( composite );
try {
- composite.dispose();
- shell.dispose();
- display.dispose();
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.dispose();
+ display.dispose();
+ }});
}
catch( Throwable throwable ) {
throwable.printStackTrace();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
index addb14ce5..ba33aa31d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
@@ -34,6 +34,8 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
+import jogamp.nativewindow.macosx.OSXUtil;
+
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
@@ -47,6 +49,8 @@ import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Test;
+import com.jogamp.common.os.Platform;
+import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.swt.GLCanvas;
import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -57,10 +61,10 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
* Uses JOGL's new SWT GLCanvas.
*
+ *
+ *
+ *
- * Holds AWT in it's test name, since our impl. still needs the AWT threading, - * see {@link GLCanvas}. + * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ + * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. *
- * @author Wade Walker, et.al. + * @author Wade Walker, et al. */ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { @@ -76,18 +80,24 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { @BeforeClass public static void startup() { System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); + if( Platform.OS_TYPE == Platform.OSType.MACOS ) { + System.err.println("OSXUtil.isAWTEDTMainThread: "+ OSXUtil.isAWTEDTMainThread() ); + } } @Before public void init() { - display = new Display(); - Assert.assertNotNull( display ); - shell = new Shell( display ); - Assert.assertNotNull( shell ); - shell.setLayout( new FillLayout() ); - composite = new Composite( shell, SWT.NONE ); - composite.setLayout( new FillLayout() ); - Assert.assertNotNull( composite ); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); } @After @@ -96,9 +106,12 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { Assert.assertNotNull( shell ); Assert.assertNotNull( composite ); try { - composite.dispose(); - shell.dispose(); - display.dispose(); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + display.dispose(); + }}); } catch( Throwable throwable ) { throwable.printStackTrace(); @@ -118,14 +131,19 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { Assert.assertNotNull( canvas ); canvas.addGLEventListener(new GLEventListener() { - public void init(final GLAutoDrawable drawable) { } + public void init(final GLAutoDrawable drawable) { + System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - init()"); + } public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { - OneTriangle.setup( drawable.getGL().getGL2(), width, height ); + System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - reshape()"); + OneTriangle.setup( drawable.getGL().getGL2(), width, height ); } public void display(final GLAutoDrawable drawable) { OneTriangle.render( drawable.getGL().getGL2(), drawable.getWidth(), drawable.getHeight()); } - public void dispose(final GLAutoDrawable drawable) {} + public void dispose(final GLAutoDrawable drawable) { + System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - dispose()"); + } }); shell.setText( getClass().getName() ); -- cgit v1.2.3 From 4e70a4811a860255b53eeae7a841ca473e1aba86 Mon Sep 17 00:00:00 2001 From: Sven Gothel LPVOID glMapBuffer(GLenum target, GLenum access);
*/
-public java.nio.ByteBuffer glMapBuffer(int target, int access) {
+public final java.nio.ByteBuffer glMapBuffer(int target, int access) {
final long __addr_ = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer;
if (__addr_ == 0) {
throw new GLException("Method \"glMapBuffer\" not available");
@@ -230,7 +232,7 @@ public java.nio.ByteBuffer glMapBuffer(int target, int access) {
native private long dispatch_glMapBuffer(int target, int access, long glProcAddress);
/** Entry point to C language function: GLvoid * {@native glMapNamedBufferEXT}(GLuint buffer, GLenum access);
GL_EXT_direct_state_access
*/
-public java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) {
+public final java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) {
final long __addr_ = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapNamedBufferEXT;
if (__addr_ == 0) {
throw new GLException("Method \"glMapNamedBufferEXT\" not available");
@@ -269,7 +271,8 @@ private native long dispatch_glMapNamedBufferEXT(int buffer, int access, long pr
native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
- public void glVertexPointer(GLArrayData array) {
+ @Override
+ public final void glVertexPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
@@ -277,7 +280,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer());
}
}
- public void glColorPointer(GLArrayData array) {
+ @Override
+ public final void glColorPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
@@ -286,7 +290,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
}
}
- public void glNormalPointer(GLArrayData array) {
+ @Override
+ public final void glNormalPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.getComponentCount()!=3) {
throw new GLException("Only 3 components per normal allowed");
@@ -297,7 +302,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer());
}
}
- public void glTexCoordPointer(GLArrayData array) {
+ @Override
+ public final void glTexCoordPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
index dff33cf81..68eadc683 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
@@ -12,98 +12,122 @@ public GLES1Impl(GLProfile glp, GLContextImpl context) {
this.glProfile = glp;
}
+@Override
public final boolean isGL4bc() {
return false;
}
+@Override
public final boolean isGL4() {
return false;
}
+@Override
public final boolean isGL3bc() {
return false;
}
+@Override
public final boolean isGL3() {
return false;
}
+@Override
public final boolean isGL2() {
return false;
}
+@Override
public final boolean isGLES1() {
return true;
}
+@Override
public final boolean isGLES2() {
return false;
}
+@Override
public final boolean isGLES() {
return true;
}
+@Override
public final boolean isGL2ES1() {
return true;
}
+@Override
public final boolean isGL2ES2() {
return false;
}
+@Override
public final boolean isGLES2Compatible() {
return false;
}
+@Override
public final boolean isGL2GL3() {
return false;
}
+@Override
public final boolean hasGLSL() {
return false;
}
+@Override
public boolean isNPOTTextureAvailable() {
return false;
}
+@Override
public final GL4bc getGL4bc() throws GLException {
throw new GLException("Not a GL4bc implementation");
}
+@Override
public final GL4 getGL4() throws GLException {
throw new GLException("Not a GL4 implementation");
}
+@Override
public final GL3bc getGL3bc() throws GLException {
throw new GLException("Not a GL3bc implementation");
}
+@Override
public final GL3 getGL3() throws GLException {
throw new GLException("Not a GL3 implementation");
}
+@Override
public final GL2 getGL2() throws GLException {
throw new GLException("Not a GL2 implementation");
}
+@Override
public final GLES1 getGLES1() throws GLException {
return this;
}
+@Override
public final GLES2 getGLES2() throws GLException {
throw new GLException("Not a GLES2 implementation");
}
+@Override
public final GL2ES1 getGL2ES1() throws GLException {
return this;
}
+@Override
public final GL2ES2 getGL2ES2() throws GLException {
throw new GLException("Not a GL2ES2 implementation");
}
+@Override
public final GL2GL3 getGL2GL3() throws GLException {
throw new GLException("Not a GL2GL3 implementation");
}
@@ -119,17 +143,17 @@ private final GLStateTracker glStateTracker;
private boolean bufferObjectExtensionsInitialized = false;
private boolean haveOESFramebufferObject;
-private void initBufferObjectExtensionChecks() {
+private final void initBufferObjectExtensionChecks() {
if (bufferObjectExtensionsInitialized)
return;
bufferObjectExtensionsInitialized = true;
haveOESFramebufferObject = isExtensionAvailable("GL_OES_framebuffer_object");
}
-private boolean checkBufferObject(boolean avail,
- boolean enabled,
- int state,
- String kind, boolean throwException) {
+private final boolean checkBufferObject(boolean avail,
+ boolean enabled,
+ int state,
+ String kind, boolean throwException) {
if (!avail) {
if (!enabled)
return true;
@@ -157,7 +181,7 @@ private boolean checkBufferObject(boolean avail,
return true;
}
-private boolean checkArrayVBODisabled(boolean throwException) {
+private final boolean checkArrayVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
false,
@@ -165,7 +189,7 @@ private boolean checkArrayVBODisabled(boolean throwException) {
"array vertex_buffer_object", throwException);
}
-private boolean checkArrayVBOEnabled(boolean throwException) {
+private final boolean checkArrayVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
true,
@@ -173,7 +197,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) {
"array vertex_buffer_object", throwException);
}
-private boolean checkElementVBODisabled(boolean throwException) {
+private final boolean checkElementVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
false,
@@ -181,7 +205,7 @@ private boolean checkElementVBODisabled(boolean throwException) {
"element vertex_buffer_object", throwException);
}
-private boolean checkElementVBOEnabled(boolean throwException) {
+private final boolean checkElementVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
true,
@@ -189,30 +213,30 @@ private boolean checkElementVBOEnabled(boolean throwException) {
"element vertex_buffer_object", throwException);
}
-private boolean checkUnpackPBODisabled(boolean throwException) {
+private final boolean checkUnpackPBODisabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return true;
}
-private boolean checkUnpackPBOEnabled(boolean throwException) {
+private final boolean checkUnpackPBOEnabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return false;
}
-private boolean checkPackPBODisabled(boolean throwException) {
+private final boolean checkPackPBODisabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return true;
}
-private boolean checkPackPBOEnabled(boolean throwException) {
+private final boolean checkPackPBOEnabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return false;
}
-private HashMap LPVOID glMapBuffer(GLenum target, GLenum access);
*/
-public java.nio.ByteBuffer glMapBuffer(int target, int access) {
+public final java.nio.ByteBuffer glMapBuffer(int target, int access) {
final long __addr_ = ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer;
if (__addr_ == 0) {
throw new GLException("Method \"glMapBuffer\" not available");
@@ -252,7 +276,8 @@ native private long dispatch_glMapBuffer(int target, int access, long glProcAddr
native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
-public void glVertexPointer(GLArrayData array) {
+@Override
+public final void glVertexPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
@@ -260,7 +285,8 @@ public void glVertexPointer(GLArrayData array) {
glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer());
}
}
-public void glColorPointer(GLArrayData array) {
+@Override
+public final void glColorPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
@@ -269,7 +295,8 @@ public void glColorPointer(GLArrayData array) {
}
}
-public void glNormalPointer(GLArrayData array) {
+@Override
+public final void glNormalPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.getComponentCount()!=3) {
throw new GLException("Only 3 components per normal allowed");
@@ -280,7 +307,8 @@ public void glNormalPointer(GLArrayData array) {
glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer());
}
}
-public void glTexCoordPointer(GLArrayData array) {
+@Override
+public final void glTexCoordPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
index a4976f5ea..760287364 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
@@ -1,6 +1,3 @@
-// Tracks glBegin/glEnd calls to determine whether it is legal to
-// query Vertex Buffer Object state
-private boolean inBeginEndPair;
public GLES2Impl(GLProfile glp, GLContextImpl context) {
this._context = context;
@@ -16,18 +13,22 @@ public GLES2Impl(GLProfile glp, GLContextImpl context) {
this.glProfile = glp;
}
+@Override
public final boolean isGL4bc() {
return false;
}
+@Override
public final boolean isGL4() {
return false;
}
+@Override
public final boolean isGL3bc() {
return false;
}
+@Override
public final boolean isGL3() {
return false;
}
@@ -36,78 +37,97 @@ public final boolean isGL2() {
return false;
}
+@Override
public final boolean isGLES1() {
return false;
}
+@Override
public final boolean isGLES2() {
return true;
}
+@Override
public final boolean isGLES() {
return true;
}
+@Override
public final boolean isGL2ES1() {
return false;
}
+@Override
public final boolean isGL2ES2() {
return true;
}
+@Override
public final boolean isGLES2Compatible() {
return true;
}
+@Override
public final boolean isGL2GL3() {
return false;
}
+@Override
public final boolean hasGLSL() {
return true;
}
+@Override
public boolean isNPOTTextureAvailable() {
return true;
}
+@Override
public final GL4bc getGL4bc() throws GLException {
throw new GLException("Not a GL4bc implementation");
}
+@Override
public final GL4 getGL4() throws GLException {
throw new GLException("Not a GL4 implementation");
}
+@Override
public final GL3bc getGL3bc() throws GLException {
throw new GLException("Not a GL3bc implementation");
}
+@Override
public final GL3 getGL3() throws GLException {
throw new GLException("Not a GL3 implementation");
}
+@Override
public final GL2 getGL2() throws GLException {
throw new GLException("Not a GL2 implementation");
}
+@Override
public final GLES1 getGLES1() throws GLException {
throw new GLException("Not a GLES1 implementation");
}
+@Override
public final GLES2 getGLES2() throws GLException {
return this;
}
+@Override
public final GL2ES1 getGL2ES1() throws GLException {
throw new GLException("Not a GL2ES1 implementation");
}
+@Override
public final GL2ES2 getGL2ES2() throws GLException {
return this;
}
+@Override
public final GL2GL3 getGL2GL3() throws GLException {
throw new GLException("Not a GL2GL3 implementation");
}
@@ -123,17 +143,17 @@ private final GLStateTracker glStateTracker;
private boolean bufferObjectExtensionsInitialized = false;
private boolean haveOESFramebufferObject;
-private void initBufferObjectExtensionChecks() {
+private final void initBufferObjectExtensionChecks() {
if (bufferObjectExtensionsInitialized)
return;
bufferObjectExtensionsInitialized = true;
haveOESFramebufferObject = isExtensionAvailable("GL_OES_framebuffer_object");
}
-private boolean checkBufferObject(boolean avail,
- boolean enabled,
- int state,
- String kind, boolean throwException) {
+private final boolean checkBufferObject(boolean avail,
+ boolean enabled,
+ int state,
+ String kind, boolean throwException) {
if (!avail) {
if (!enabled)
return true;
@@ -161,7 +181,7 @@ private boolean checkBufferObject(boolean avail,
return true;
}
-private boolean checkArrayVBODisabled(boolean throwException) {
+private final boolean checkArrayVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
false,
@@ -169,7 +189,7 @@ private boolean checkArrayVBODisabled(boolean throwException) {
"array vertex_buffer_object", throwException);
}
-private boolean checkArrayVBOEnabled(boolean throwException) {
+private final boolean checkArrayVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
true,
@@ -177,7 +197,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) {
"array vertex_buffer_object", throwException);
}
-private boolean checkElementVBODisabled(boolean throwException) {
+private final boolean checkElementVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
false,
@@ -185,7 +205,7 @@ private boolean checkElementVBODisabled(boolean throwException) {
"element vertex_buffer_object", throwException);
}
-private boolean checkElementVBOEnabled(boolean throwException) {
+private final boolean checkElementVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
true,
@@ -193,30 +213,31 @@ private boolean checkElementVBOEnabled(boolean throwException) {
"element vertex_buffer_object", throwException);
}
-private boolean checkUnpackPBODisabled(boolean throwException) {
+private final boolean checkUnpackPBODisabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return true;
}
-private boolean checkUnpackPBOEnabled(boolean throwException) {
+private final boolean checkUnpackPBOEnabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return false;
}
-private boolean checkPackPBODisabled(boolean throwException) {
+private final boolean checkPackPBODisabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return true;
}
-private boolean checkPackPBOEnabled(boolean throwException) {
+private final boolean checkPackPBOEnabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return false;
}
-private HashMap LPVOID glMapBuffer(GLenum target, GLenum access);
*/
-public java.nio.ByteBuffer glMapBuffer(int target, int access) {
+@Override
+public final java.nio.ByteBuffer glMapBuffer(int target, int access) {
final long __addr_ = ((GLES2ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer;
if (__addr_ == 0) {
throw new GLException("Method \"glMapBuffer\" not available");
@@ -256,11 +277,13 @@ native private long dispatch_glMapBuffer(int target, int access, long glProcAddr
native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
-public void glClearDepth(double depth) {
+@Override
+public final void glClearDepth(double depth) {
glClearDepthf((float)depth);
}
-public void glDepthRange(double zNear, double zFar) {
+@Override
+public final void glDepthRange(double zNear, double zFar) {
glDepthRangef((float)zNear, (float)zFar);
}
diff --git a/make/scripts/java-win32-dbg.bat b/make/scripts/java-win32-dbg.bat
index d1797bdbb..6f8206721 100755
--- a/make/scripts/java-win32-dbg.bat
+++ b/make/scripts/java-win32-dbg.bat
@@ -9,9 +9,9 @@ set BLD_DIR=..\%BLD_SUB%
set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x32
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\angle\win32;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj
set LIB_DIR=%FFMPEG_LIB%
@@ -20,11 +20,14 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege
echo CP_ALL %CP_ALL%
-set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
+set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK"
+REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
+REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true"
REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true"
REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true"
-REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock"
REM set D_ARGS="-Dnativewindow.debug.TraceLock"
REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display"
diff --git a/make/scripts/java-win32.bat b/make/scripts/java-win32.bat
index 9d59c045e..1d8430280 100755
--- a/make/scripts/java-win32.bat
+++ b/make/scripts/java-win32.bat
@@ -8,8 +8,8 @@ set PROJECT_ROOT=D:\projects\jogamp\jogl
set BLD_DIR=..\%BLD_SUB%
REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
set BLD_DIR=..\%BLD_SUB%
REM set LIB_DIR=..\..\gluegen\%BLD_SUB%\obj;%BLD_DIR%\lib
diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat
index d6b0435ea..109755d2e 100755
--- a/make/scripts/java-win64-dbg.bat
+++ b/make/scripts/java-win64-dbg.bat
@@ -9,7 +9,8 @@ set BLD_DIR=..\%BLD_SUB%
set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x64
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH%
REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj
set LIB_DIR=%FFMPEG_LIB%
@@ -17,7 +18,13 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege
echo CP_ALL %CP_ALL%
-set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
+set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK"
+REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
+REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery"
+REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser -Djogl.debug.GLProfile"
+REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
REM set D_ARGS="-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLSLCode"
REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true"
REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true"
@@ -33,7 +40,6 @@ REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLC
REM set D_ARGS="-Dnewt.debug.Window"
REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL"
REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode"
-REM set D_ARGS="-Djogl.debug.GraphicsConfiguration" "-Djogl.debug.CapabilitiesChooser"
REM set D_ARGS="-Djogl.debug.GLContext" "-Dnewt.debug=all"
REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock"
REM set D_ARGS="-Dnativewindow.debug.TraceLock"
diff --git a/make/scripts/java-win64.bat b/make/scripts/java-win64.bat
index b8f438aab..2c09feedc 100755
--- a/make/scripts/java-win64.bat
+++ b/make/scripts/java-win64.bat
@@ -4,7 +4,8 @@ set J2RE_HOME=c:\jre1.6.0_30_x64
set JAVA_HOME=c:\jdk1.6.0_30_x64
set ANT_PATH=C:\apache-ant-1.8.2
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH%
set BLD_DIR=..\%BLD_SUB%
REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj
diff --git a/make/scripts/tests-x32.bat b/make/scripts/tests-x32.bat
index c29dcef39..7947759a4 100755
--- a/make/scripts/tests-x32.bat
+++ b/make/scripts/tests-x32.bat
@@ -51,7 +51,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode0
REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT
REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %*
-scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %*
+REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %*
REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %*
REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT
@@ -94,6 +94,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe
REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT
REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01
+scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %*
REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01
REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat
index 32729d235..0b3711784 100755
--- a/make/scripts/tests-x64.bat
+++ b/make/scripts/tests-x64.bat
@@ -72,7 +72,7 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingPr
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAWT01GLn %*
-scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
+REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT -time 5000
@@ -96,7 +96,8 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01
+scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %*
+REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 0258187fd..591f5f9d2 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -53,10 +53,17 @@ function jrun() {
swton=$1
shift
+ #D_ARGS="-Djogl.debug.FBObject -Djogl.debug.DebugGL"
+ #D_ARGS="-Djogl.debug.FBObject"
+ #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.FBObject"
#D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing"
#D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
#D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all"
+ #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock"
#D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all"
+ #D_ARGS="-Djogl.debug.EGLDrawableFactory.DontQuery -Djogl.debug.GLDrawable"
+ #D_ARGS="-Djogl.debug.EGLDrawableFactory.QueryNativeTK -Djogl.debug.GLDrawable"
+ #D_ARGS="-Djogl.debug.GLDrawable"
#D_ARGS="-Djogl.debug=all -Dnewt.debug=all"
#D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL"
#D_ARGS="-Djogl.debug.GLDebugMessageHandler"
@@ -71,6 +78,7 @@ function jrun() {
#D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer"
#D_ARGS="-Djogl.debug.GLArrayData"
#D_ARGS="-Djogl.debug.EGL -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable"
+ #D_ARGS="-Djogl.debug.GLDrawable"
#D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen"
#D_ARGS="-Djogl.debug.ExtensionAvailabilityCache -Djogl.debug=all -Dnativewindow.debug=all -Djogamp.debug.ProcAddressHelper=true -Djogamp.debug.NativeLibrary=true -Djogamp.debug.NativeLibrary.Lookup=true"
#D_ARGS="-Dnewt.debug.MainThread"
@@ -85,7 +93,7 @@ function jrun() {
#D_ARGS="-Dnativewindow.debug.NativeWindow"
#D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT"
#D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Window -Djogl.debug.GLContext"
- #D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock -Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util"
+ #D_ARGS="-Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util"
#D_ARGS="-Dnativewindow.debug.X11Util -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnewt.debug=all"
#D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.XSync"
#D_ARGS="-Dnativewindow.debug.X11Util.XSync -Dnewt.debug.Window"
@@ -100,9 +108,9 @@ function jrun() {
#D_ARGS="-Djogl.debug.Animator -Dnewt.debug=all"
#D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Display -Dnativewindow.debug.X11Util -Djogl.debug.GLDrawable -Djogl.debug.GLCanvas"
#D_ARGS="-Djogl.debug.GLContext"
- #D_ARGS="-Djogl.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser"
+ #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser"
#D_ARGS="-Dnewt.debug.Screen -Dnewt.debug.EDT -Djogamp.debug.Lock"
- #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GraphicsConfiguration"
+ #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.GraphicsConfiguration"
#D_ARGS="-Dnewt.debug.EDT"
#D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext"
#D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen"
@@ -115,8 +123,6 @@ function jrun() {
#D_ARGS="-Xprof"
#D_ARGS="-Djogl.debug.Animator"
#D_ARGS="-Dnativewindow.debug=all"
- #D_ARGS="-Djogl.debug.GraphicsConfiguration"
- #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GraphicsConfiguration"
#D_ARGS="-Djogl.debug.GLCanvas"
#D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock"
#D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLCode -Djogl.debug.TraceGL"
@@ -162,20 +168,20 @@ function jrun() {
C_ARG="com.jogamp.newt.util.MainThread"
fi
fi
+ #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH
echo
echo "Test Start: $*"
echo
echo LD_LIBRARY_PATH $LD_LIBRARY_PATH
echo
echo $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
- #LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH \
#LIBGL_DRIVERS_PATH=/usr/lib/mesa:/usr/lib32/mesa \
- #LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=$spath/../lib/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=$spath/../lib/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH \
#gdb --args $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
$javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
echo
@@ -228,6 +234,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $*
@@ -292,7 +299,7 @@ function testawtswt() {
# swt (testswt)
#
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $*
-testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
+#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02GLn $*
@@ -322,7 +329,8 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT $*
#testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT
#testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyNEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT
@@ -358,7 +366,9 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $*
+testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $*
#
# Graph
@@ -394,6 +404,7 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot $*
#linux:
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $* # linux NV: cannot make ctx current ..
# osx:
#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $*
diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h
index e7fe13553..47b51a509 100644
--- a/make/stub_includes/opengl/macosx-window-system.h
+++ b/make/stub_includes/opengl/macosx-window-system.h
@@ -31,7 +31,7 @@ NSView* getNSView(NSOpenGLContext* ctx);
NSOpenGLContext* createContext(NSOpenGLContext* shareContext,
NSView* nsView,
- Bool isBackingLayerView,
+ Bool allowIncompleteView,
NSOpenGLPixelFormat* pixelFormat,
Bool opaque,
int* viewNotReady);
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
index 87a734e1f..482d35cae 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
@@ -293,9 +293,9 @@ public class BuildStaticGLInfo {
output.println(" public static String getFunctionAssociation(String glFunctionName)");
output.println(" {");
output.println(" String mappedName = null;");
- output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutationNumber(glFunctionName);");
+ output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutationNumber(glFunctionName);");
output.println(" for(int i = 0; null==mappedName && i < funcNamePermNum; i++) {");
- output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutation(glFunctionName, i);");
+ output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutation(glFunctionName, i);");
output.println(" try {");
output.println(" mappedName = (String)funcToAssocMap.get(tmp);");
output.println(" } catch (Exception e) { }");
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
index c1a4facd2..ba025e18c 100755
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
@@ -43,7 +43,7 @@ import com.jogamp.gluegen.GlueEmitterControls;
import com.jogamp.gluegen.GlueGen;
import com.jogamp.gluegen.MethodBinding;
import com.jogamp.gluegen.procaddress.ProcAddressConfiguration;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -224,11 +224,11 @@ public class GLConfiguration extends ProcAddressConfiguration {
}
}
}
- boolean isGLEnum = GLExtensionNames.isGLEnumeration(symbol);
- boolean isGLFunc = GLExtensionNames.isGLFunction(symbol);
+ boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol);
+ boolean isGLFunc = GLNameResolver.isGLFunction(symbol);
if (isGLFunc || isGLEnum) {
- if (GLExtensionNames.isExtensionVEN(symbol, isGLFunc)) {
- String extSuffix = GLExtensionNames.getExtensionSuffix(symbol, isGLFunc);
+ if (GLNameResolver.isExtensionVEN(symbol, isGLFunc)) {
+ String extSuffix = GLNameResolver.getExtensionSuffix(symbol, isGLFunc);
if (getDropUniqVendorExtensions(extSuffix)) {
if (DEBUG_IGNORES) {
System.err.println("Ignore UniqVendorEXT: " + symbol + ", vendor " + extSuffix);
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
index f4658ad7b..809c6783d 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
@@ -51,7 +51,7 @@ import com.jogamp.gluegen.SymbolFilter;
import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.procaddress.ProcAddressEmitter;
import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import java.io.IOException;
import java.io.PrintWriter;
@@ -110,13 +110,13 @@ public class GLEmitter extends ProcAddressEmitter {
if (declarations != null) {
for (Iterator
+ * Integrates default read/write framebuffers via {@link GLContext#getDefaultReadFramebuffer()} and {@link GLContext#getDefaultReadFramebuffer()},
+ * which is being hooked at {@link GL#glBindFramebuffer(int, int)} when the default (zero
) framebuffer is selected.
+ *
FIXME: Implement support for {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} .
+ */ +public class FBObject { + protected static final boolean DEBUG = Debug.debug("FBObject"); + + /** + * Returnstrue
if basic FBO support is available, otherwise false
.
+ *
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * ARB_ES2_compatibility
, ARB_framebuffer_object
, EXT_framebuffer_object
or OES_framebuffer_object
.
+ *
+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *
+ * @see GLContext#hasFBO() + */ + public static final boolean supportsBasicFBO(GL gl) { + return gl.getContext().hasFBO(); + } + + /** + * Returnstrue
if full FBO support is available, otherwise false
.
+ *
+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * ARB_framebuffer_object
, or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ *
+ * Full FBO support includes multiple color attachments and multisampling. + *
+ */ + public static final boolean supportsFullFBO(GL gl) { + return gl.isGL3() || // GL >= 3.0 + + gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + + ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) ) ; + } + + public static final int getMaxSamples(GL gl) { + if( supportsFullFBO(gl) ) { + int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + return val[0]; + } else { + return 0; + } + } + + /** Common super class of all attachments */ + public static abstract class Attachment { + public enum Type { + NONE, DEPTH, STENCIL, DEPTH_STENCIL, COLOR, COLOR_TEXTURE, DEPTH_TEXTURE, STENCIL_TEXTURE; + + /** + * Returns {@link #COLOR}, {@link #DEPTH}, {@link #STENCIL} or {@link #DEPTH_STENCIL} + * @throws IllegalArgumentException ifformat
cannot be handled.
+ */
+ public static Type determine(int format) throws IllegalArgumentException {
+ switch(format) {
+ case GL.GL_RGBA4:
+ case GL.GL_RGB5_A1:
+ case GL.GL_RGB565:
+ case GL.GL_RGB8:
+ case GL.GL_RGBA8:
+ return Type.COLOR;
+ case GL.GL_DEPTH_COMPONENT16:
+ case GL.GL_DEPTH_COMPONENT24:
+ case GL.GL_DEPTH_COMPONENT32:
+ return Type.DEPTH;
+ case GL.GL_STENCIL_INDEX1:
+ case GL.GL_STENCIL_INDEX4:
+ case GL.GL_STENCIL_INDEX8:
+ return Type.STENCIL;
+ case GL.GL_DEPTH24_STENCIL8:
+ return Type.DEPTH_STENCIL;
+ default:
+ throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format));
+ }
+ }
+ };
+
+ /** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */
+ public final Type type;
+
+ /** immutable the internal format */
+ public final int format;
+
+ private int width, height;
+
+ private int name;
+
+ /** true
if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */
+ protected boolean resourceOwner;
+
+ private int initCounter;
+
+ protected Attachment(Type type, int iFormat, int width, int height, int name) {
+ this.type = type;
+ this.format = iFormat;
+ this.width = width;
+ this.height = height;
+ this.name = name;
+ this.resourceOwner = false;
+ this.initCounter = 0;
+ }
+
+ /** width of attachment */
+ public final int getWidth() { return width; }
+ /** height of attachment */
+ public final int getHeight() { return height; }
+ /* pp */ final void setSize(int w, int h) { width = w; height = h; }
+
+ /** buffer name [1..max], maybe a texture or renderbuffer name, depending on type. */
+ public final int getName() { return name; }
+ /* pp */ final void setName(int n) { name = n; }
+
+ public final int getInitCounter() { return initCounter; }
+
+ /**
+ * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is zero
.
+ * Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + */ + public void initialize(GL gl) throws GLException { + initCounter++; + /* + super.initialize(gl); + if(1 == getInitCounter() && 0 == getName() ) { + do init .. + freeResources = true; // if all OK + } + */ + } + + /** + * Releases the attachment buffer if initialized, i.e. name iszero
.
+ * Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.
+ * @throws GLException if buffer release fails. + */ + public void free(GL gl) throws GLException { + /* + if(1 == getInitCounter() && freeResources && .. ) { + do free .. + } + super.free(gl); + */ + initCounter--; + if(0 == initCounter) { + resourceOwner = false; + name = 0; + } + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } + } + + /** + *+ * Comparison by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. + *
+ * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if( this == o ) return true; + if( ! ( o instanceof Attachment ) ) return false; + final Attachment a = (Attachment)o; + return type == a.type && + format == a.format || + width == a.width || + height== a.height || + name == a.name ; + } + + /** + *+ * Hashed by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. + *
+ * {@inheritDoc} + */ + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = 31 + type.ordinal(); + hash = ((hash << 5) - hash) + format; + hash = ((hash << 5) - hash) + width; + hash = ((hash << 5) - hash) + height; + hash = ((hash << 5) - hash) + name; + return hash; + } + + int objectHashCode() { return super.hashCode(); } + + public String toString() { + return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+ + ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+ + ", resOwner "+resourceOwner+", initCount "+initCounter+"]"; + } + + public static Type getType(int attachmentPoint, int maxColorAttachments) { + if( GL.GL_COLOR_ATTACHMENT0 <= attachmentPoint && attachmentPoint < GL.GL_COLOR_ATTACHMENT0+maxColorAttachments ) { + return Type.COLOR; + } + switch(attachmentPoint) { + case GL.GL_DEPTH_ATTACHMENT: + return Type.DEPTH; + case GL.GL_STENCIL_ATTACHMENT: + return Type.STENCIL; + default: + throw new IllegalArgumentException("Invalid attachment point 0x"+Integer.toHexString(attachmentPoint)); + } + } + } + + /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ + public static class RenderAttachment extends Attachment { + private int samples; + + /** + * @param type allowed types are {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR} + * @param iFormat + * @param samples + * @param width + * @param height + * @param name + */ + public RenderAttachment(Type type, int iFormat, int samples, int width, int height, int name) { + super(validateType(type), iFormat, width, height, name); + this.samples = samples; + } + + /** number of samples, or zero for no multisampling */ + public final int getSamples() { return samples; } + /* pp */ final void setSamples(int s) { samples = s; } + + private static Type validateType(Type type) { + switch(type) { + case DEPTH: + case STENCIL: + case COLOR: + return type; + default: + throw new IllegalArgumentException("Invalid type: "+type); + } + } + + /** + *+ * Comparison by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. + *
+ * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if( this == o ) return true; + if( ! ( o instanceof RenderAttachment ) ) return false; + return super.equals(o) && + samples == ((RenderAttachment)o).samples; + } + + /** + *+ * Hashed by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. + *
+ * {@inheritDoc} + */ + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = super.hashCode(); + hash = ((hash << 5) - hash) + samples; + return hash; + } + + @Override + public void initialize(GL gl) throws GLException { + super.initialize(gl); + if( 1 == getInitCounter() && 0 == getName() ) { + final int[] name = new int[] { -1 }; + gl.glGenRenderbuffers(1, name, 0); + if( 0 == name[0] ) { + throw new GLException("null renderbuffer, "+this); + } + setName(name[0]); + + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); + if( samples > 0 ) { + ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight()); + } else { + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); + } + int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR != glerr) { + gl.glDeleteRenderbuffers(1, name, 0); + setName(0); + throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); + } + resourceOwner = true; + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } + } + } + + @Override + public void free(GL gl) { + if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { + final int[] name = new int[] { getName() }; + gl.glDeleteRenderbuffers(1, name, 0); + } + super.free(gl); + } + + public String toString() { + return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ + ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+ + ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]"; + } + } + + /** + * Marker interface, denotes a color buffer attachment. + *Always an instance of {@link Attachment}.
+ *Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.
+ */
+ public static interface Colorbuffer {
+ }
+
+ /** Color render buffer attachment */
+ public static class ColorAttachment extends RenderAttachment implements Colorbuffer {
+ public ColorAttachment(int iFormat, int samples, int width, int height, int name) {
+ super(Type.COLOR, iFormat, samples, width, height, name);
+ }
+ }
+
+ /** Texture attachment */
+ public static class TextureAttachment extends Attachment implements Colorbuffer {
+ /** details of the texture setup */
+ public final int dataFormat, dataType, magFilter, minFilter, wrapS, wrapT;
+
+ /**
+ * @param type allowed types are [ {@link Type#COLOR_TEXTURE}, {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} ]
+ * @param iFormat
+ * @param width
+ * @param height
+ * @param dataFormat
+ * @param dataType
+ * @param magFilter
+ * @param minFilter
+ * @param wrapS
+ * @param wrapT
+ * @param name
+ */
+ public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType,
+ int magFilter, int minFilter, int wrapS, int wrapT, int name) {
+ super(validateType(type), iFormat, width, height, name);
+ this.dataFormat = dataFormat;
+ this.dataType = dataType;
+ this.magFilter = magFilter;
+ this.minFilter = minFilter;
+ this.wrapS = wrapS;
+ this.wrapT = wrapT;
+ }
+
+ private static Type validateType(Type type) {
+ switch(type) {
+ case COLOR_TEXTURE:
+ case DEPTH_TEXTURE:
+ case STENCIL_TEXTURE:
+ return type;
+ default:
+ throw new IllegalArgumentException("Invalid type: "+type);
+ }
+ }
+
+ /**
+ * Initializes the texture and set it's parameter, if uninitialized, i.e. name is zero
.
+ * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case.
+ */
+ @Override
+ public void initialize(GL gl) throws GLException {
+ super.initialize(gl);
+ if( 1 == getInitCounter() && 0 == getName() ) {
+ final int[] name = new int[] { -1 };
+ gl.glGenTextures(1, name, 0);
+ if(0 == name[0]) {
+ throw new GLException("null texture, "+this);
+ }
+ setName(name[0]);
+
+ gl.glBindTexture(GL.GL_TEXTURE_2D, name[0]);
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ if( 0 < magFilter ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter);
+ }
+ if( 0 < minFilter ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter);
+ }
+ if( 0 < wrapS ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS);
+ }
+ if( 0 < wrapT ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
+ }
+ int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteTextures(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this);
+ }
+ resourceOwner = true;
+ }
+ if(DEBUG) {
+ System.err.println("Attachment.init: "+this);
+ }
+ }
+
+ @Override
+ public void free(GL gl) {
+ if(1 == getInitCounter() && resourceOwner && 0 != getName() ) {
+ final int[] name = new int[] { getName() };
+ gl.glDeleteTextures(1, name, 0);
+ }
+ super.free(gl);
+ }
+ }
+
+ private boolean initialized;
+ private boolean basicFBOSupport;
+ private boolean fullFBOSupport;
+ private boolean rgba8Avail;
+ private boolean depth24Avail;
+ private boolean depth32Avail;
+ private boolean stencil01Avail;
+ private boolean stencil04Avail;
+ private boolean stencil08Avail;
+ private boolean stencil16Avail;
+ private boolean packedDepthStencilAvail;
+ private int maxColorAttachments, maxSamples, maxTextureSize, maxRenderbufferSize;
+
+ private int width, height, samples;
+ private int vStatus;
+ private int fbName;
+ private boolean bound;
+
+ private int colorAttachmentCount;
+ private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points
+ private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil
+
+ private final FBObject samplesSink; // MSAA sink
+ private TextureAttachment samplesSinkTexture;
+ private boolean samplesSinkDirty;
+
+ //
+ // ColorAttachment helper ..
+ //
+
+ private final void validateColorAttachmentPointRange(int point) {
+ if(maxColorAttachments != colorAttachmentPoints.length) {
+ throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints);
+ }
+ if(0 > point || point >= maxColorAttachments) {
+ throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"]");
+ }
+ }
+
+ private final void validateAddColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ if( null != colorAttachmentPoints[point] ) {
+ throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorAttachmentPoints[point]);
+ }
+ }
+
+ private final void addColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ final Colorbuffer c = colorAttachmentPoints[point];
+ if( null != c && c != ca ) {
+ throw new IllegalArgumentException("Add failed: requested to add "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ }
+ colorAttachmentPoints[point] = ca;
+ colorAttachmentCount++;
+ }
+
+ private final void removeColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ final Colorbuffer c = colorAttachmentPoints[point];
+ if( null != c && c != ca ) {
+ throw new IllegalArgumentException("Remove failed: requested to removed "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ }
+ colorAttachmentPoints[point] = null;
+ colorAttachmentCount--;
+ }
+
+ /**
+ * Return the {@link Colorbuffer} attachment at attachmentPoint
if it is attached to this FBO, otherwise null.
+ *
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachTexture2D(GL, int, boolean, int, int, int, int)
+ * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
+ */
+ public final Colorbuffer getColorbuffer(int attachmentPoint) {
+ validateColorAttachmentPointRange(attachmentPoint);
+ return colorAttachmentPoints[attachmentPoint];
+ }
+
+ /**
+ * Finds the passed {@link Colorbuffer} within the valid range of attachment points
+ * using reference comparison only.
+ *
+ * Note: Slow. Implementation uses a logN array search to save resources, i.e. not using a HashMap. + *
+ * @param ca the {@link Colorbuffer} to look for. + * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1] + */ + public final int getColorbufferAttachmentPoint(Colorbuffer ca) { + for(int i=0; i+ * Note: Slow. Uses {@link #getColorbufferAttachmentPoint(Colorbuffer)} to determine it's attachment point + * to be used for {@link #getColorbuffer(int)} + *
+ * + * @see #attachColorbuffer(GL, boolean) + * @see #attachColorbuffer(GL, boolean) + * @see #attachTexture2D(GL, int, boolean, int, int, int, int) + * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) + */ + public final Colorbuffer getColorbuffer(Colorbuffer ca) { + final int p = getColorbufferAttachmentPoint(ca); + return p>=0 ? getColorbuffer(p) : null; + } + + /** + * Creates an uninitialized FBObject instance. + *+ * Call {@link #init(GL, int, int, int)} .. etc to use it. + *
+ */ + public FBObject() { + this(false); + } + /* pp */ FBObject(boolean isSampleSink) { + this.initialized = false; + + // TBD @ init + this.basicFBOSupport = false; + this.fullFBOSupport = false; + this.rgba8Avail = false; + this.depth24Avail = false; + this.depth32Avail = false; + this.stencil01Avail = false; + this.stencil04Avail = false; + this.stencil08Avail = false; + this.stencil16Avail = false; + this.packedDepthStencilAvail = false; + this.maxColorAttachments=-1; + this.maxSamples=-1; + this.maxTextureSize = 0; + this.maxRenderbufferSize = 0; + + this.width = 0; + this.height = 0; + this.samples = 0; + this.vStatus = -1; + this.fbName = 0; + this.bound = false; + + this.colorAttachmentPoints = null; // at init .. + this.colorAttachmentCount = 0; + this.depth = null; + this.stencil = null; + + this.samplesSink = isSampleSink ? null : new FBObject(true); + this.samplesSinkTexture = null; + this.samplesSinkDirty = true; + } + + private void init(GL gl, int width, int height, int samples) throws GLException { + if(initialized) { + throw new GLException("FBO already initialized"); + } + fullFBOSupport = supportsFullFBO(gl); + + if( !fullFBOSupport && !supportsBasicFBO(gl) ) { + throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this); + } + + basicFBOSupport = true; + + rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8); + depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24); + depth32Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth32); + stencil01Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil1); + stencil04Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil4); + stencil08Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil8); + stencil16Avail = fullFBOSupport; + + packedDepthStencilAvail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil); + + final boolean NV_fbo_color_attachments = gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments); + + int val[] = new int[1]; + + int glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr)); + } + + int realMaxColorAttachments = 1; + maxColorAttachments = 1; + if( null != samplesSink && fullFBOSupport || NV_fbo_color_attachments ) { + try { + gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0); + glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1 + } else if(DEBUG) { + System.err.println("FBObject.init-GL_MAX_COLOR_ATTACHMENTS query GL Error 0x"+Integer.toHexString(glerr)); + } + } catch (GLException gle) {} + } + maxColorAttachments = realMaxColorAttachments <= 8 ? realMaxColorAttachments : 8; // cap to limit array size + + colorAttachmentPoints = new Colorbuffer[maxColorAttachments]; + colorAttachmentCount = 0; + + maxSamples = 0; + if(fullFBOSupport) { + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + maxSamples = val[0]; + } else if(DEBUG) { + System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); + maxTextureSize = val[0]; + gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0); + this.maxRenderbufferSize = val[0]; + + glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("FBObject.init-preexisting.1 GL Error 0x"+Integer.toHexString(glerr)); + } + + this.width = width; + this.height = height; + this.samples = samples <= maxSamples ? samples : maxSamples; + + if(DEBUG) { + System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples"); + System.err.println("basicFBOSupport: "+basicFBOSupport); + System.err.println("fullFBOSupport: "+fullFBOSupport); + System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments); + System.err.println("maxSamples: "+maxSamples); + System.err.println("maxTextureSize: "+maxTextureSize); + System.err.println("maxRenderbufferSize: "+maxRenderbufferSize); + System.err.println("rgba8: "+rgba8Avail); + System.err.println("depth24: "+depth24Avail); + System.err.println("depth32: "+depth32Avail); + System.err.println("stencil01: "+stencil01Avail); + System.err.println("stencil04: "+stencil04Avail); + System.err.println("stencil08: "+stencil08Avail); + System.err.println("stencil16: "+stencil16Avail); + System.err.println("packedDepthStencil: "+packedDepthStencilAvail); + System.err.println("NV_fbo_color_attachments: "+NV_fbo_color_attachments); + System.err.println(gl.getContext().getGLVersion()); + System.err.println(JoglVersion.getGLStrings(gl, null).toString()); + System.err.println(gl.getContext()); + } + + checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error + + if(width > 2 + maxTextureSize || height> 2 + maxTextureSize || + width > maxRenderbufferSize || height> maxRenderbufferSize ) { + throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); + } + + if(null != samplesSink) { + // init sampling sink + samplesSink.reset(gl, width, height); + resetMSAATexture2DSink(gl); + } + + // generate fbo .. + gl.glGenFramebuffers(1, val, 0); + fbName = val[0]; + if(0 == fbName) { + throw new GLException("null framebuffer"); + } + + // bind fbo .. + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName); + checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error + if(!gl.glIsFramebuffer(fbName)) { + checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException + } + bound = true; + initialized = true; + + updateStatus(gl); + if(DEBUG) { + System.err.println("FBObject.init(): "+this); + } + } + + /** + * Initializes or resets this FBO's instance. + *+ * In case the new parameters are compatible with the current ones + * no action will be performed. Otherwise all attachments will be recreated + * to match the new given parameters. + *
+ *+ * Currently incompatibility and hence recreation is given if + * the size or sample count doesn't match for subsequent calls. + *
+ * + *Leaves the FBO bound state untouched
+ * + * @param gl the current GL context + * @param newWidth + * @param newHeight + * @throws GLException in case of an error + */ + public final void reset(GL gl, int newWidth, int newHeight) { + reset(gl, newWidth, newHeight, 0); + } + + /** + * Initializes or resets this FBO's instance. + *+ * In case the new parameters are compatible with the current ones + * no action will be performed. Otherwise all attachments will be recreated + * to match the new given parameters. + *
+ *+ * Currently incompatibility and hence recreation is given if + * the size or sample count doesn't match for subsequent calls. + *
+ * + *Leaves the FBO bound state untouched
+ * + * @param gl the current GL context + * @param newWidth + * @param newHeight + * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}. + * @throws GLException in case of an error + */ + public final void reset(GL gl, int newWidth, int newHeight, int newSamples) { + if(!initialized) { + init(gl, newWidth, newHeight, newSamples); + return; + } + newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp + + if( newWidth != width || newHeight != height || newSamples != samples ) { + if(DEBUG) { + System.err.println("FBObject.reset - START - "+this); + } + + final boolean wasBound = isBound(); + + width = newWidth; + height = newHeight; + samples = newSamples; + detachAllImpl(gl, true , true); + resetMSAATexture2DSink(gl); + + if(wasBound) { + bind(gl); + } else { + unbind(gl); + } + + if(DEBUG) { + System.err.println("FBObject.reset - END - "+this); + } + } + } + + /** + * Note that the status may reflect an incomplete state during transition of attachments. + * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 + * @see #validateStatus() + */ + public final int getStatus() { + return vStatus; + } + + /** return the {@link #getStatus()} as a string. */ + public final String getStatusString() { + return getStatusString(vStatus); + } + + public static final String getStatusString(int fbStatus) { + switch(fbStatus) { + case -1: + return "NOT A FBO"; + + case GL.GL_FRAMEBUFFER_COMPLETE: + return "OK"; + + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + return("GL FBO: incomplete, incomplete attachment\n"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + return("GL FBO: incomplete, missing attachment"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + return("GL FBO: incomplete, attached images must have same dimensions"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + return("GL FBO: incomplete, attached images must have same format"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + return("GL FBO: incomplete, missing draw buffer"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + return("GL FBO: incomplete, missing read buffer"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + return("GL FBO: incomplete, missing multisample buffer"); + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + return("GL FBO: incomplete, layer targets"); + + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + return("GL FBO: Unsupported framebuffer format"); + case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: + return("GL FBO: framebuffer undefined"); + + case 0: + return("GL FBO: incomplete, implementation fault"); + default: + return("GL FBO: incomplete, implementation ERROR 0x"+Integer.toHexString(fbStatus)); + } + } + + /** + * The status may even be valid if incomplete during transition of attachments. + * @see #getStatus() + */ + public final boolean isStatusValid() { + switch(vStatus) { + case GL.GL_FRAMEBUFFER_COMPLETE: + return true; + + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + if(0 == colorAttachmentCount || null == depth) { + // we are in transition + return true; + } + + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: + + case 0: + default: + System.out.println("Framebuffer " + fbName + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + + " : " + getStatusString(vStatus)); + return false; + } + } + + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { + if(GL.GL_NO_ERROR != err) { + if(null != gl) { + destroy(gl); + } + if(null != exceptionMessage) { + throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err)); + } + return false; + } + return true; + } + + private final void checkInitialized() throws GLException { + if(!initialized) { + throw new GLException("FBO not initialized, call init(GL) first."); + } + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * selecting the texture data type and format automatically. + * + *Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.
+ * + *Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set totrue
if you request alpha channel, otherwise false
;
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException {
+ return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the texture data type and format automatically.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set totrue
if you request alpha channel, otherwise false
;
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
+ final int textureInternalFormat, textureDataFormat, textureDataType;
+ if(gl.isGLES()) {
+ textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, + int internalFormat, int dataFormat, int dataType, + int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { + return attachTexture2D(gl, attachmentPoint, + new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, + magFilter, minFilter, wrapS, wrapT, 0 /* name */)); + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * + *
+ * In case the passed TextureAttachment texA
is uninitialized, i.e. it's texture name is zero
,
+ * a new texture name is generated and setup w/ the texture parameter.
+ * Otherwise, i.e. texture name is not zero
, the passed TextureAttachment texA
is
+ * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
+ *
Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above. + * @return the passed TextureAttachmenttexA
instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException {
+ validateAddColorAttachment(attachmentPoint, texA);
+
+ if(samples>0) {
+ removeColorAttachment(attachmentPoint, texA);
+ throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl).");
+ }
+
+ texA.initialize(gl);
+ addColorAttachment(attachmentPoint, texA);
+
+ bind(gl);
+
+ // Set up the color buffer for use as a renderable texture:
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ GL.GL_TEXTURE_2D, texA.getName(), 0);
+ updateStatus(gl);
+
+ if(!isStatusValid()) {
+ detachColorbuffer(gl, attachmentPoint);
+ throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.attachTexture2D: "+this);
+ }
+ return texA;
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the format automatically.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set totrue
if you request alpha channel, otherwise false
;
+ * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException {
+ final int internalFormat;
+ if( rgba8Avail ) {
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
+ } else {
+ internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
+ }
+ return attachColorbuffer(gl, attachmentPoint, internalFormat);
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8} + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + * @throws IllegalArgumentException ifinternalFormat
doesn't reflect a colorbuffer
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, int internalFormat) throws GLException, IllegalArgumentException {
+ final Attachment.Type atype = Attachment.Type.determine(internalFormat);
+ if( Attachment.Type.COLOR != atype ) {
+ throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+
+ return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0));
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param colA the template for the new {@link ColorAttachment} + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + */ + public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException { + validateAddColorAttachment(attachmentPoint, colA); + + colA.initialize(gl); + addColorAttachment(attachmentPoint, colA); + + bind(gl); + + // Attach the color buffer + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_RENDERBUFFER, colA.getName()); + + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint); + throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + if(DEBUG) { + System.err.println("FBObject.attachColorbuffer: "+this); + } + return colA; + } + + + /** + * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, + * selecting the internalFormat automatically. + *+ * Stencil and depth buffer can be attached only once. + *
+ *+ * In case the desired type or bit-number is not supported, the next available one is chosen. + *
+ *+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details + * about the attached buffer. The details cannot be returned, since it's possible 2 buffers + * are being created, depth and stencil. + *
+ * + *Leaves the FBO bound.
+ * + * @param gl + * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL} + * @param reqBits desired bits for depth or -1 for default (24 bits) + * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. + * @throws IllegalArgumentException + * @see #getDepthAttachment() + * @see #getStencilAttachment() + */ + public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException { + if( 0 > reqBits ) { + reqBits = 24; + } + final int internalFormat; + int internalStencilFormat = -1; + + switch ( atype ) { + case DEPTH: + if( 32 <= reqBits && depth32Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT32; + } else if( 24 <= reqBits && depth24Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT24; + } else { + internalFormat = GL.GL_DEPTH_COMPONENT16; + } + break; + + case STENCIL: + if( 16 <= reqBits && stencil16Avail ) { + internalFormat = GL2GL3.GL_STENCIL_INDEX16; + } else if( 8 <= reqBits && stencil08Avail ) { + internalFormat = GL.GL_STENCIL_INDEX8; + } else if( 4 <= reqBits && stencil04Avail ) { + internalFormat = GL.GL_STENCIL_INDEX4; + } else if( 1 <= reqBits && stencil01Avail ) { + internalFormat = GL.GL_STENCIL_INDEX1; + } else { + throw new GLException("stencil buffer n/a"); + } + break; + + case DEPTH_STENCIL: + if( packedDepthStencilAvail ) { + internalFormat = GL.GL_DEPTH24_STENCIL8; + } else { + if( 24 <= reqBits && depth24Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT24; + } else { + internalFormat = GL.GL_DEPTH_COMPONENT16; + } + if( stencil08Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX8; + } else if( stencil04Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX4; + } else if( stencil01Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX1; + } else { + throw new GLException("stencil buffer n/a"); + } + } + break; + default: + throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); + } + + attachRenderbufferImpl(gl, atype, internalFormat); + + if(0<=internalStencilFormat) { + attachRenderbufferImpl(gl, Attachment.Type.STENCIL, internalStencilFormat); + } + } + + /** + * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, + * depending on theinternalFormat
.
+ * + * Stencil and depth buffer can be attached only once. + *
+ *+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details + * about the attached buffer. The details cannot be returned, since it's possible 2 buffers + * are being created, depth and stencil. + *
+ * + *Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param internalFormat {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24}, {@link GL#GL_DEPTH_COMPONENT32}, + * {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} + * or {@link GL#GL_DEPTH24_STENCIL8} + * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. + * @throws IllegalArgumentException + * @see #getDepthAttachment() + * @see #getStencilAttachment() + */ + public final void attachRenderbuffer(GL gl, int internalFormat) throws GLException, IllegalArgumentException { + final Attachment.Type atype = Attachment.Type.determine(internalFormat); + if( Attachment.Type.DEPTH != atype && Attachment.Type.STENCIL != atype && Attachment.Type.DEPTH_STENCIL != atype ) { + throw new IllegalArgumentException("renderformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); + } + attachRenderbufferImpl(gl, atype, internalFormat); + } + + protected final void attachRenderbufferImpl(GL gl, Attachment.Type atype, int internalFormat) throws GLException { + if( null != depth && ( Attachment.Type.DEPTH == atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { + throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this); + } + if( null != stencil && ( Attachment.Type.STENCIL== atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { + throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this); + } + attachRenderbufferImpl2(gl, atype, internalFormat); + } + + private final void attachRenderbufferImpl2(GL gl, Attachment.Type atype, int internalFormat) throws GLException { + if( Attachment.Type.DEPTH == atype ) { + if(null == depth) { + depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0); + } else { + depth.setSize(width, height); + depth.setSamples(samples); + } + depth.initialize(gl); + } else if( Attachment.Type.STENCIL == atype ) { + if(null == stencil) { + stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, 0); + } else { + stencil.setSize(width, height); + stencil.setSamples(samples); + } + stencil.initialize(gl); + } else if( Attachment.Type.DEPTH_STENCIL == atype ) { + if(null == depth) { + depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0); + } else { + depth.setSize(width, height); + depth.setSamples(samples); + } + depth.initialize(gl); + if(null == stencil) { + stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, depth.getName()); + } else { + stencil.setName(depth.getName()); + stencil.setSize(width, height); + stencil.setSamples(samples); + } + stencil.initialize(gl); + } + + bind(gl); + + // Attach the buffer + if( Attachment.Type.DEPTH == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + } else if( Attachment.Type.STENCIL == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); + } else if( Attachment.Type.DEPTH_STENCIL == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); + } + + updateStatus(gl); + if( !isStatusValid() ) { + detachRenderbuffer(gl, atype); + throw new GLException("renderbuffer attachment failed: "+this.getStatusString()); + } + + if(DEBUG) { + System.err.println("FBObject.attachRenderbuffer: "+this); + } + } + + /** + *Leaves the FBO bound!
+ * @param gl + * @param ca + * @throws IllegalArgumentException + */ + public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException { + if(null == detachColorbufferImpl(gl, attachmentPoint, false)) { + throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); + } + if(DEBUG) { + System.err.println("FBObject.detachAll: "+this); + } + } + + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) { + final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here + + if(null == colbuf) { + return null; + } + + bind(gl); + + if(colbuf instanceof TextureAttachment) { + final TextureAttachment texA = (TextureAttachment) colbuf; + if( 0 != texA.getName() ) { + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, 0, 0); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + } + texA.free(gl); + removeColorAttachment(attachmentPoint, texA); + if(recreate) { + texA.setSize(width, height); + attachTexture2D(gl, attachmentPoint, texA); + } + } else if(colbuf instanceof ColorAttachment) { + final ColorAttachment colA = (ColorAttachment) colbuf; + if( 0 != colA.getName() ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0+attachmentPoint, + GL.GL_RENDERBUFFER, 0); + } + colA.free(gl); + removeColorAttachment(attachmentPoint, colbuf); + if(recreate) { + colA.setSize(width, height); + colA.setSamples(samples); + attachColorbuffer(gl, attachmentPoint, colA); + } + } + return colbuf; + } + + /** + * + * @param gl + * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} + */ + public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException { + detachRenderbufferImpl(gl, atype, false); + } + + public final boolean isDepthStencilPackedFormat() { + final boolean res = null != depth && null != stencil && + depth.format == stencil.format ; + if(res && depth.getName() != stencil.getName() ) { + throw new InternalError("depth/stencil packed format not sharing: depth "+depth+", stencil "+stencil); + } + return res; + } + + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException { + switch ( atype ) { + case DEPTH: + case STENCIL: + case DEPTH_STENCIL: + break; + default: + throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); + } + if( null == depth && null == stencil ) { + return ; // nop + } + // reduction of possible combinations, create unique atype command(s) + final ArrayListLeaves the FBO bound!
+ *+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *
+ * @param gl the current GL context + */ + public final void detachAll(GL gl) { + if(null != samplesSink) { + samplesSink.detachAll(gl); + } + detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */); + } + + /** + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s. + *Leaves the FBO bound!
+ *+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *
+ * @param gl the current GL context + */ + public final void detachAllColorbuffer(GL gl) { + if(null != samplesSink) { + samplesSink.detachAllColorbuffer(gl); + } + detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */); + } + + /** + * Detaches all {@link TextureAttachment}s + *Leaves the FBO bound!
+ *+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *
+ * @param gl the current GL context + */ + public final void detachAllTexturebuffer(GL gl) { + if(null != samplesSink) { + samplesSink.detachAllTexturebuffer(gl); + } + for(int i=0; iIf multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()}, + * if full FBO is supported.
+ * + *+ * In case you have attached more than one color buffer, + * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}. + *
+ * @param gl the current GL context + * @throws GLException + */ + public final void bind(GL gl) throws GLException { + if(!bound || fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)) { + checkInitialized(); + if(samples > 0 && fullFBOSupport) { + // draw to multisampling - read from samplesSink + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, getWriteFramebuffer()); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, getReadFramebuffer()); + } else { + // one for all + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer()); + } + + checkNoError(null, gl.glGetError(), "FBObject post-bind"); // throws GLException if error + bound = true; + samplesSinkDirty = true; + } + } + + /** + * Unbind this FBO, i.e. bind read and write framebuffer to default, see {@link GLBase#getDefaultDrawFramebuffer()}. + * + *If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}
+ * + * @param gl the current GL context + * @throws GLException + */ + public final void unbind(GL gl) throws GLException { + if(bound) { + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + } + checkNoError(null, gl.glGetError(), "FBObject post-unbind"); // throws GLException if error + bound = false; + } + } + + /** + * Returnstrue
if framebuffer object is bound via {@link #bind(GL)}, otherwise false
.
+ * + * Method verifies the bound state via {@link GL#getBoundFramebuffer(int)}. + *
+ * @param gl the current GL context + */ + public final boolean isBound(GL gl) { + bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ; + return bound; + } + + /** Returnstrue
if framebuffer object is bound via {@link #bind(GL)}, otherwise false
. */
+ public final boolean isBound() { return bound; }
+
+ /**
+ * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}.
+ *
+ * The operation is skipped, if no multisampling is used or + * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)}, + * see {@link #isSamplingBufferDirty()}
+ * + *If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}
+ * + *In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)} + * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()}); + *
+ * + *Leaves the FBO unbound.
+ * + * @param gl the current GL context + * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} + * @throws IllegalArgumentException + */ + public final void syncSamplingBuffer(GL gl) { + unbind(gl); + if(samples>0 && samplesSinkDirty) { + samplesSinkDirty = false; + resetMSAATexture2DSink(gl); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName); + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer()); + ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, ugly cast is OK + GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST); + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + } + } + } + + /** + * Bind the given texture colorbuffer. + * + *If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called.
+ * + *Leaves the FBO unbound!
+ * + * @param gl the current GL context + * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} + * @throws IllegalArgumentException + */ + public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException { + if(null == ta) { throw new IllegalArgumentException("null TextureAttachment"); } + if(samples > 0 && samplesSinkTexture == ta) { + syncSamplingBuffer(gl); + } else { + unbind(gl); + } + gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it .. + } + + /** + * Unbind texture, ie bind 'non' texture 0 + * + *Leaves the FBO unbound.
+ */ + public final void unuse(GL gl) { + unbind(gl); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it + } + + /** + * Returnstrue
if basic or full FBO is supported, otherwise false
.
+ * @param full true
for full FBO supported query, otherwise false
for basic FBO support query.
+ * @see #supportsFullFBO(GL)
+ * @see #supportsBasicFBO(GL)
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; }
+
+ /**
+ * Returns true
if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise false
.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsRGBA8() throws GLException { checkInitialized(); return rgba8Avail; }
+
+ /**
+ * Returns true
if {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} is supported, otherwise false
.
+ * @param bits 16, 24 or 32 bits
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsDepth(int bits) throws GLException {
+ checkInitialized();
+ switch(bits) {
+ case 16: return basicFBOSupport;
+ case 24: return depth24Avail;
+ case 32: return depth32Avail;
+ default: return false;
+ }
+ }
+
+ /**
+ * Returns true
if {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} or {@link GL2GL3#GL_STENCIL_INDEX16} is supported, otherwise false
.
+ * @param bits 1, 4, 8 or 16 bits
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsStencil(int bits) throws GLException {
+ checkInitialized();
+ switch(bits) {
+ case 1: return stencil01Avail;
+ case 4: return stencil04Avail;
+ case 8: return stencil08Avail;
+ case 16: return stencil16Avail;
+ default: return false;
+ }
+ }
+
+ /**
+ * Returns true
if {@link GL#GL_DEPTH24_STENCIL8} is supported, otherwise false
.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsPackedDepthStencil() throws GLException { checkInitialized(); return packedDepthStencilAvail; }
+
+ /**
+ * Returns the maximum number of colorbuffer attachments.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; }
+
+ /**
+ * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; }
+
+ /**
+ * Returns true
if this instance has been initialized with {@link #reset(GL, int, int)}
+ * or {@link #reset(GL, int, int, int)}, otherwise false
+ */
+ public final boolean isInitialized() { return initialized; }
+ /** Returns the width */
+ public final int getWidth() { return width; }
+ /** Returns the height */
+ public final int getHeight() { return height; }
+ /** Returns the number of samples for multisampling (MSAA). zero if no multisampling is used. */
+ public final int getNumSamples() { return samples; }
+ /** Returns the framebuffer name to render to. */
+ public final int getWriteFramebuffer() { return fbName; }
+ /** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */
+ public final int getReadFramebuffer() { return ( samples > 0 ) ? samplesSink.getReadFramebuffer() : fbName; }
+ /** Return the number of color/texture attachments */
+ public final int getColorAttachmentCount() { return colorAttachmentCount; }
+ /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */
+ public final RenderAttachment getStencilAttachment() { return stencil; }
+ /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */
+ public final RenderAttachment getDepthAttachment() { return depth; }
+
+ /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */
+ public final FBObject getSamplingSinkFBO() { return samplesSink; }
+
+ /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */
+ public final TextureAttachment getSamplingSink() { return samplesSinkTexture; }
+ /**
+ * Returns true
if the multisampling colorbuffer (msaa-buffer)
+ * has been flagged dirty by a previous call of {@link #bind(GL)},
+ * otherwise false
.
+ */
+ public final boolean isSamplingBufferDirty() { return samplesSinkDirty; }
+
+ int objectHashCode() { return super.hashCode(); }
+
+ public final String toString() {
+ final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ;
+ return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+", samples "+samples+"/"+maxSamples+
+ ", depth "+depth+", stencil "+stencil+", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+
+ ": "+caps+", msaa-sink "+samplesSinkTexture+", isSamplesSink "+(null == samplesSink)+
+ ", obj 0x"+Integer.toHexString(objectHashCode())+"]";
+ }
+
+ private final void updateStatus(GL gl) {
+ if( 0 == fbName ) {
+ vStatus = -1;
+ } else {
+ vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
new file mode 100644
index 000000000..f7e25fa01
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+/**
+ * Class holding OpenGL extension strings, commonly used by JOGL's implementation.
+ */
+public class GLExtensions {
+ public static final String VERSION_1_2 = "GL_VERSION_1_2";
+ public static final String VERSION_1_4 = "GL_VERSION_1_4";
+ public static final String VERSION_1_5 = "GL_VERSION_1_5";
+ public static final String VERSION_2_0 = "GL_VERSION_2_0";
+
+ public static final String ARB_debug_output = "GL_ARB_debug_output";
+ public static final String AMD_debug_output = "GL_AMD_debug_output";
+
+ public static final String ARB_framebuffer_object = "GL_ARB_framebuffer_object";
+ public static final String OES_framebuffer_object = "GL_OES_framebuffer_object";
+ public static final String EXT_framebuffer_object = "GL_EXT_framebuffer_object";
+ public static final String EXT_framebuffer_blit = "GL_EXT_framebuffer_blit";
+ public static final String EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample";
+ public static final String EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil";
+ public static final String OES_depth24 = "GL_OES_depth24";
+ public static final String OES_depth32 = "GL_OES_depth32";
+ public static final String OES_packed_depth_stencil = "GL_OES_packed_depth_stencil";
+ public static final String NV_fbo_color_attachments = "GL_NV_fbo_color_attachments";
+
+ public static final String ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
+
+ public static final String EXT_abgr = "GL_EXT_abgr";
+ public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8";
+ public static final String OES_stencil1 = "GL_OES_stencil1";
+ public static final String OES_stencil4 = "GL_OES_stencil4";
+ public static final String OES_stencil8 = "GL_OES_stencil8";
+ public static final String APPLE_float_pixels = "GL_APPLE_float_pixels";
+
+ public static final String ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
+ public static final String ARB_texture_rectangle = "GL_ARB_texture_rectangle";
+ public static final String EXT_texture_rectangle = "GL_EXT_texture_rectangle";
+ public static final String NV_texture_rectangle = "GL_NV_texture_rectangle";
+ public static final String EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888";
+ public static final String IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888";
+ public static final String EXT_texture_compression_s3tc = "GL_EXT_texture_compression_s3tc";
+ public static final String NV_texture_compression_vtc = "GL_NV_texture_compression_vtc";
+ public static final String SGIS_generate_mipmap = "GL_SGIS_generate_mipmap";
+ public static final String OES_read_format = "GL_OES_read_format";
+
+ public static final String OES_EGL_image_external = "GL_OES_EGL_image_external";
+
+ //
+ // Aliased GLX/WGL/.. extensions
+ //
+
+ public static final String ARB_pixel_format = "GL_ARB_pixel_format";
+ public static final String ARB_pbuffer = "GL_ARB_pbuffer";
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 75785fd86..cdb4b82bb 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -93,11 +93,13 @@ public class JoglVersion extends JogampVersion {
return sb;
}
- public static StringBuilder getDefaultOpenGLInfo(StringBuilder sb, boolean withCapabilitiesInfo) {
+ public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, boolean withCapabilitiesInfo) {
if(null==sb) {
sb = new StringBuilder();
}
- final AbstractGraphicsDevice device = GLProfile.getDefaultDevice();
+ if(null == device) {
+ device = GLProfile.getDefaultDevice();
+ }
sb.append("Default Profiles on device ").append(device).append(Platform.getNewline());
if(null!=device) {
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
@@ -120,13 +122,21 @@ public class JoglVersion extends JogampVersion {
if(null==sb) {
sb = new StringBuilder();
}
- GLContext ctx = gl.getContext();
-
+
sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline());
sb.append(device.getClass().getSimpleName()).append("[type ")
.append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ").append(Platform.getNewline());
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
sb.append(Platform.getNewline());
+
+ return getGLStrings(gl, sb);
+ }
+
+ public static StringBuilder getGLStrings(GL gl, StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ final GLContext ctx = gl.getContext();
sb.append("Swap Interval ").append(gl.getSwapInterval());
sb.append(Platform.getNewline());
sb.append("GL Profile ").append(gl.getGLProfile());
diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java
new file mode 100644
index 000000000..1ea8595c6
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import javax.media.opengl.GLAutoDrawableDelegate;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+
+import jogamp.opengl.GLFBODrawableImpl;
+
+/**
+ * Platform-independent class exposing FBO offscreen functionality to
+ * applications.
+ * + * This class distinguishes itself from {@link GLAutoDrawableDelegate} + * with it's {@link #setSize(int, int)} functionality. + *
+ */ +public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { + + public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, Object upstreamWidget) { + super(drawable, context, upstreamWidget); + } + + /** + * Attempts to resize this offscreen auto drawable, if supported + * by the underlying {@link GLDrawable). + * @param newWidth + * @param newHeight + * @returntrue
if resize was executed, otherwise false
.
+ * @throws GLException in case of an error during the resize operation
+ */
+ public boolean setSize(int newWidth, int newHeight) throws GLException {
+ boolean done = false;
+ if(drawable instanceof GLFBODrawableImpl) {
+ context.makeCurrent();
+ try {
+ ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight);
+ done = true;
+ } finally {
+ context.release();
+ }
+ }
+ if(done) {
+ this.defaultWindowResizedOp();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * If the underlying {@link GLDrawable} is an FBO implementation
+ * and contains an {#link FBObject}, the same is returned.
+ * Otherwise returns null
.
+ */
+ public FBObject getFBObject() {
+ if(drawable instanceof GLFBODrawableImpl) {
+ return ((GLFBODrawableImpl)drawable).getFBObject();
+ }
+ return null;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 5ee58b78d..0d9d3ddf5 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -231,6 +231,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite) */
device = SWTAccessor.getDevice(this);
+ /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */
+ final int screenIdx = 0;
/* Native handle for the control, used to associate with GLContext */
nativeWindowHandle = SWTAccessor.getWindowHandle(this);
@@ -243,7 +245,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile());
/* Create a NativeWindow proxy for the SWT canvas */
- proxySurface = glFactory.createProxySurface(device, nativeWindowHandle, caps, chooser);
+ proxySurface = glFactory.createProxySurface(device, screenIdx, nativeWindowHandle, caps, chooser, swtCanvasUpStreamHook);
/* Associate a GL surface with the proxy */
drawable = glFactory.createGLDrawable(proxySurface);
@@ -265,12 +267,58 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
addControlListener(new ControlAdapter() {
@Override
public void controlResized(final ControlEvent arg0) {
- clientArea = GLCanvas.this.getClientArea();
- /* Mark for OpenGL reshape next time the control is painted */
- sendReshape = true;
+ updateSizeCheck();
}
});
}
+ private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final void destroy(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return clientArea.width;
+ }
+
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return clientArea.height;
+ }
+
+ @Override
+ public String toString() {
+ return "SETUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+"]";
+ }
+
+ };
+
+ protected final void updateSizeCheck() {
+ clientArea = GLCanvas.this.getClientArea();
+ if (clientArea != null &&
+ proxySurface.getWidth() != clientArea.width &&
+ proxySurface.getHeight() != clientArea.height) {
+ sendReshape = true; // Mark for OpenGL reshape next time the control is painted
+ }
+ sendReshape = false;
+ }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
+ public int getWidth() {
+ return clientArea.width;
+ }
+
+ @Override
+ public int getHeight() {
+ return clientArea.height;
+ }
@Override
public void addGLEventListener(final GLEventListener arg0) {
@@ -417,25 +465,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
return (drawable != null) ? drawable.getHandle() : 0;
}
- @Override
- public int getHeight() {
- final Rectangle clientArea = this.clientArea;
- if (clientArea == null) return 0;
- return clientArea.height;
- }
-
@Override
public NativeSurface getNativeSurface() {
return (drawable != null) ? drawable.getNativeSurface() : null;
}
- @Override
- public int getWidth() {
- final Rectangle clientArea = this.clientArea;
- if (clientArea == null) return 0;
- return clientArea.width;
- }
-
@Override
public boolean isRealized() {
return (drawable != null) ? drawable.isRealized() : false;
@@ -515,7 +549,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
final Display display = new Display();
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java
deleted file mode 100644
index 3e049a334..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2011 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package com.jogamp.opengl.util;
-
-import javax.media.opengl.*;
-
-public class FBObject {
- static final int MAX_FBO_TEXTURES = 32; // just for our impl .. not the real 'max' FBO color attachments
- private int[] fbo_tex_names;
- private int[] fbo_tex_units;
- private int fbo_tex_num;
- private int colorattachment_num;
-
- private boolean initialized;
- private int width, height;
- private int fb, depth_rb, stencil_rb, vStatus;
- private boolean bound;
-
- public FBObject(int width, int height) {
- this.fbo_tex_names = new int[MAX_FBO_TEXTURES];
- this.fbo_tex_units = new int[MAX_FBO_TEXTURES];
- this.fbo_tex_num = 0;
- this.colorattachment_num = 0;
- this.initialized = false;
- this.width = width;
- this.height = height;
- this.fb = 0;
- this.depth_rb = 0;
- this.stencil_rb = 0;
- this.bound = false;
- }
-
- /**
- * @return true if the FB status is valid, otherwise false
- * @see #getStatus()
- */
- public boolean isStatusValid() {
- switch(vStatus) {
- case GL.GL_FRAMEBUFFER_COMPLETE:
- return true;
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:
- case 0:
- default:
- System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) +
- " : " + getStatusString(vStatus));
- return false;
- }
- }
-
- /**
- * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1
- * @see #validateStatus()
- */
- public int getStatus() {
- return vStatus;
- }
-
- public String getStatusString() {
- return getStatusString(vStatus);
- }
-
- public static final String getStatusString(int fbStatus) {
- switch(fbStatus) {
- case -1:
- return "NOT A FBO";
- case GL.GL_FRAMEBUFFER_COMPLETE:
- return "OK";
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- return("GL FBO: Unsupported framebuffer format");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- return("GL FBO: incomplete, incomplete attachment\n");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- return("GL FBO: incomplete, missing attachment");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- return("GL FBO: incomplete, attached images must have same dimensions");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- return("GL FBO: incomplete, attached images must have same format");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- return("GL FBO: incomplete, missing draw buffer");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- return("GL FBO: incomplete, missing read buffer");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- return("GL FBO: incomplete, missing multisample buffer");
- case 0:
- return("GL FBO: incomplete, implementation fault");
- default:
- return("GL FBO: incomplete, implementation ERROR");
- }
- }
-
- private boolean checkNoError(GL gl, int err, String exceptionMessage) {
- if(GL.GL_NO_ERROR != err) {
- if(null != gl) {
- destroy(gl);
- }
- if(null != exceptionMessage) {
- throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err));
- }
- return false;
- }
- return true;
- }
-
- private final void checkInitialized() {
- if(!initialized) {
- throw new GLException("FBO not initialized, call init(GL) first.");
- }
- }
-
- private final void checkBound(GL gl, boolean shallBeBound) {
- checkInitialized();
- if(bound != shallBeBound) {
- final String s0 = shallBeBound ? "not" : "already" ;
- throw new GLException("FBO "+s0+" bound "+toString());
- }
- checkNoError(null, gl.glGetError(), "FBObject pre"); // throws GLException if error
- }
-
- /**
- * Initializes this FBO's instance with it's texture.
- *
- * Leaves the FBO bound!
- * - * @param gl the current GL context - * @throws GLException in case of an error - */ - public void init(GL gl) throws GLException { - if(initialized) { - throw new GLException("FBO already initialized"); - } - checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error - - // generate fbo .. - int name[] = new int[1]; - - gl.glGenFramebuffers(1, name, 0); - fb = name[0]; - if(fb==0) { - throw new GLException("null generated framebuffer"); - } - - // bind fbo .. - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error - if(!gl.glIsFramebuffer(fb)) { - checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException - } - bound = true; - initialized = true; - - updateStatus(gl); - } - - /** - * Attaches a[nother] Texture2D Color Buffer to this FBO's instance, - * selecting the texture data type and format automatically. - *This may be done as many times as many color attachments are supported, - * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.
- * - *Assumes a bound FBO
- *Leaves the FBO bound!
- * - * @param gl the current GL context - * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)} - * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} - * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} - * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} - * @return idx of the new attached texture, otherwise -1 - * @throws GLException in case of an error - */ - public int attachTexture2D(GL gl, int texUnit, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - final int textureInternalFormat, textureDataFormat, textureDataType; - if(gl.isGLES()) { - textureInternalFormat=GL.GL_RGBA; - textureDataFormat=GL.GL_RGBA; - textureDataType=GL.GL_UNSIGNED_BYTE; - } else { - textureInternalFormat=GL.GL_RGBA8; - textureDataFormat=GL.GL_BGRA; - textureDataType=GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; - } - return attachTexture2D(gl, texUnit, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); - } - - /** - * Attaches a[nother] Texture2D Color Buffer to this FBO's instance, - * selecting the texture data type and format automatically. - *This may be done as many times as many color attachments are supported, - * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.
- * - *Assumes a bound FBO
- *Leaves the FBO bound!
- * - * @param gl the current GL context - * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)} - * @param textureInternalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param textureDataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param textureDataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} - * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} - * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} - * @return index of the texture colorbuffer if bound and configured successfully, otherwise -1 - * @throws GLException in case the texture colorbuffer couldn't be allocated - */ - public int attachTexture2D(GL gl, int texUnit, - int textureInternalFormat, int textureDataFormat, int textureDataType, - int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - checkBound(gl, true); - final int fbo_tex_idx = fbo_tex_num; - gl.glGenTextures(1, fbo_tex_names, fbo_tex_num); - if(fbo_tex_names[fbo_tex_idx]==0) { - throw new GLException("null generated texture"); - } - fbo_tex_units[fbo_tex_idx] = texUnit; - fbo_tex_num++; - if(0<=texUnit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); - } - gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx]); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindTex"); // throws GLException if error - gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, textureInternalFormat, width, height, 0, - textureDataFormat, textureDataType, null); - int glerr = gl.glGetError(); - if(GL.GL_NO_ERROR != glerr) { - int[] sz = new int[1]; - gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0); - // throws GLException if error - checkNoError(gl, glerr, "FBObject Init.texImage2D: "+ - " int-fmt 0x"+Integer.toHexString(textureInternalFormat)+ - ", "+width+"x"+height+ - ", data-fmt 0x"+Integer.toHexString(textureDataFormat)+ - ", data-type 0x"+Integer.toHexString(textureDataType)+ - ", max tex-sz "+sz[0]); - } - if( 0 < magFilter ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter); - } - if( 0 < minFilter ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter); - } - if( 0 < wrapS ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS); - } - if( 0 < wrapT ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); - } - - // Set up the color buffer for use as a renderable texture: - gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + colorattachment_num++, - GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx], 0); - - updateStatus(gl); - return isStatusValid() ? fbo_tex_idx : -1; - } - - /** - * Attaches one Depth Buffer to this FBO's instance. - *This may be done only one time.
- * - *Assumes a bound FBO
- *Leaves the FBO bound!
- * @param gl the current GL context - * @param depthComponentType {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} - * @return true if the depth renderbuffer could be bound and configured, otherwise false - * @throws GLException in case the depth renderbuffer couldn't be allocated or one is already attached. - */ - public boolean attachDepthBuffer(GL gl, int depthComponentType) throws GLException { - checkBound(gl, true); - if(depth_rb != 0) { - throw new GLException("FBO depth buffer already attached (rb "+depth_rb+")"); - } - int name[] = new int[1]; - gl.glGenRenderbuffers(1, name, 0); - depth_rb = name[0]; - if(depth_rb==0) { - throw new GLException("null generated renderbuffer"); - } - // Initialize the depth buffer: - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb); - if(!gl.glIsRenderbuffer(depth_rb)) { - System.err.println("not a depthbuffer: "+ depth_rb); - name[0] = depth_rb; - gl.glDeleteRenderbuffers(1, name, 0); - depth_rb=0; - return false; - } - - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, depthComponentType, width, height); - // Set up the depth buffer attachment: - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_DEPTH_ATTACHMENT, - GL.GL_RENDERBUFFER, depth_rb); - updateStatus(gl); - return isStatusValid(); - } - - /** - * Attaches one Stencil Buffer to this FBO's instance. - *This may be done only one time.
- * - *Assumes a bound FBO
- *Leaves the FBO bound!
- * @param gl the current GL context - * @param stencilComponentType {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4} or {@link GL#GL_STENCIL_INDEX8} - * @return true if the stencil renderbuffer could be bound and configured, otherwise false - * @throws GLException in case the stencil renderbuffer couldn't be allocated or one is already attached. - */ - public boolean attachStencilBuffer(GL gl, int stencilComponentType) throws GLException { - checkBound(gl, true); - if(stencil_rb != 0) { - throw new GLException("FBO stencil buffer already attached (rb "+stencil_rb+")"); - } - int name[] = new int[1]; - gl.glGenRenderbuffers(1, name, 0); - stencil_rb = name[0]; - if(stencil_rb==0) { - throw new GLException("null generated stencilbuffer"); - } - // Initialize the stencil buffer: - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, stencil_rb); - if(!gl.glIsRenderbuffer(stencil_rb)) { - System.err.println("not a stencilbuffer: "+ stencil_rb); - name[0] = stencil_rb; - gl.glDeleteRenderbuffers(1, name, 0); - stencil_rb=0; - return false; - } - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, stencilComponentType, width, height); - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_STENCIL_ATTACHMENT, - GL.GL_RENDERBUFFER, stencil_rb); - updateStatus(gl); - return isStatusValid(); - } - - /** - * @param gl the current GL context - */ - public void destroy(GL gl) { - if(bound) { - unbind(gl); - } - - int name[] = new int[1]; - - if(0!=stencil_rb) { - name[0] = stencil_rb; - gl.glDeleteRenderbuffers(1, name, 0); - stencil_rb = 0; - } - if(0!=depth_rb) { - name[0] = depth_rb; - gl.glDeleteRenderbuffers(1, name, 0); - depth_rb=0; - } - if(null!=fbo_tex_names && fbo_tex_num>0) { - gl.glDeleteTextures(1, fbo_tex_names, fbo_tex_num); - fbo_tex_names = new int[MAX_FBO_TEXTURES]; - fbo_tex_units = new int[MAX_FBO_TEXTURES]; - fbo_tex_num = 0; - } - colorattachment_num = 0; - if(0!=fb) { - name[0] = fb; - gl.glDeleteFramebuffers(1, name, 0); - fb = 0; - } - initialized = false; - } - - /** - * Bind this FBO - *In case you have attached more than one color buffer, - * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.
- * @param gl the current GL context - */ - public void bind(GL gl) { - checkBound(gl, false); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); - bound = true; - } - - /** - * Unbind FBO, ie bind 'non' FBO 0 - * @param gl the current GL context - */ - public void unbind(GL gl) { - checkBound(gl, true); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); - bound = false; - } - - /** - * Bind the texture with given index. - * - *If a valid texture unit was named via {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)}, - * the unit is activated via {@link GL#glActiveTexture(int) glActiveTexture(GL.GL_TEXTURE0 + unit)}.
- * @param gl the current GL context - * @param texIdx index of the texture to use, prev. attached w/ {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)} - */ - public void use(GL gl, int texIdx) { - checkBound(gl, false); - if(texIdx >= fbo_tex_num) { - throw new GLException("Invalid texId, only "+fbo_tex_num+" textures are attached"); - } - if(0<=fbo_tex_units[texIdx]) { - gl.glActiveTexture(GL.GL_TEXTURE0 + fbo_tex_units[texIdx]); - } - gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[texIdx]); // use it .. - } - - /** Unbind texture, ie bind 'non' texture 0 */ - public void unuse(GL gl) { - checkBound(gl, false); - gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it - } - - public final boolean isBound() { return bound; } - public final int getWidth() { return width; } - public final int getHeight() { return height; } - public final int getFBName() { return fb; } - public final int getTextureNumber() { return fbo_tex_num; } - public final int getTextureName(int idx) { return fbo_tex_names[idx]; } - - /** @return the named texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit was desired. */ - public final int getTextureUnit(int idx) { return fbo_tex_units[idx]; } - public final int getColorAttachmentNumber() { return colorattachment_num; } - public final int getStencilBuffer() { return stencil_rb; } - public final int getDepthBuffer() { return depth_rb; } - public final String toString() { - return "FBO[name "+fb+", size "+width+"x"+height+", color num "+colorattachment_num+", tex num "+fbo_tex_num+", depth "+depth_rb+", stencil "+stencil_rb+"]"; - } - - private void updateStatus(GL gl) { - if(!gl.glIsFramebuffer(fb)) { - vStatus = -1; - } else { - vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); - } - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java index 8401b9cd2..331d6fa4e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java @@ -39,6 +39,7 @@ package com.jogamp.opengl.util; import com.jogamp.common.nio.Buffers; + import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GL2ES2; @@ -56,22 +57,32 @@ import java.nio.*; public class GLBuffers extends Buffers { /** - * @param glType shall be one of - * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, - * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, - * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, - * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, - * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, - * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, - * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, - * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV - * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) + * @param glType shall be one of (29)- + based rendering mechanism as well by end users directly. +
The implementation shall initialize itself as soon as possible, ie if the attached {@link javax.media.nativewindow.NativeSurface NativeSurface} becomes visible/realized. The following protocol shall be satisfied: @@ -64,18 +64,18 @@ import jogamp.opengl.Debug; registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.
- +
+
Another implementation detail is the drawable reconfiguration. One use case is where a window is being
dragged to another screen with a different pixel configuration, ie {@link GLCapabilities}. The implementation
- shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.
+ shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.
For example, AWT's {@link java.awt.Canvas} 's {@link java.awt.Canvas#getGraphicsConfiguration getGraphicsConfiguration()}
is capable to determine a display device change. This is demonstrated within {@link javax.media.opengl.awt.GLCanvas}'s
and NEWT's AWTCanvas
{@link javax.media.opengl.awt.GLCanvas#getGraphicsConfiguration getGraphicsConfiguration()}
specialization. Another demonstration is NEWT's {@link javax.media.nativewindow.NativeWindow NativeWindow}
- implementation on the Windows platform, which utilizes the native platform's MonitorFromWindow(HWND) function.
+ implementation on the Windows platform, which utilizes the native platform's MonitorFromWindow(HWND) function.
All OpenGL resources shall be regenerated, while the drawable's {@link GLCapabilities} has
- to be choosen again. The following protocol shall be satisfied.
+ to be chosen again. The following protocol shall be satisfied.
- - However, to not introduce to much breakage with older applications and because of the situation + and make your application comply with the above protocol. +
+ Avoiding breakage with older applications and because of the situation
mentioned above, the boolean
system property jogl.screenchange.action
will control the
- screen change action as follows:
-
+ screen change action as follows:
-Djogl.screenchange.action=false Disable the drawable reconfiguration (the default) -Djogl.screenchange.action=true Enable the drawable reconfiguration+ */ public interface GLAutoDrawable extends GLDrawable { /** Flag reflecting wheather the drawable reconfiguration will be issued in @@ -362,5 +362,29 @@ public interface GLAutoDrawable extends GLDrawable { demos for examples. @return the set GL pipeline or null if not successful */ public GL setGL(GL gl); + + /** + * Method may return the upstream UI toolkit object + * holding this {@link GLAutoDrawable} instance, if exist. + *
+ * Currently known Java UI toolkits and it's known return types are: + * + *
Toolkit | GLAutoDrawable Implementation | ~ | Return Type of getUpstreamWidget() | + *
NEWT | {@link com.jogamp.newt.opengl.GLWindow} | has a | {@link com.jogamp.newt.Window} | + *
SWT | {@link com.jogamp.opengl.swt.GLCanvas} | is a | {@link org.eclipse.swt.widgets.Canvas} | + *
AWT | {@link javax.media.opengl.awt.GLCanvas} | is a | {@link java.awt.Canvas} | + *
AWT | {@link javax.media.opengl.awt.GLJPanel} | is a | {@link javax.swing.JPanel} | + *
+ * This method may also return null
if no UI toolkit is being used,
+ * as common for offscreen rendering.
+ *
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index bd24b15bc..f5831a72d 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -340,5 +340,60 @@ public interface GLBase {
* completeness.
*/
public Object getExtension(String extensionName);
+
+ /** Aliased entrypoint of void {@native glClearDepth}(GLclampd depth);
and void {@native glClearDepthf}(GLclampf depth);
. */
+ public void glClearDepth( double depth );
+
+ /** Aliased entrypoint of void {@native glDepthRange}(GLclampd depth);
and void {@native glDepthRangef}(GLclampf depth);
. */
+ public void glDepthRange(double zNear, double zFar);
+
+ /**
+ * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, ..
+ * @return the GL buffer (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound.
+ */
+ public int glGetBoundBuffer(int target);
+
+ /**
+ * @param buffer a GL buffer name, generated with {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} for example.
+ * @return the size of the given GL buffer
+ */
+ public long glGetBufferSize(int buffer);
+
+ /**
+ * @return true if a VBO is bound to {@link GL.GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean glIsVBOArrayEnabled();
+
+ /**
+ * @return true if a VBO is bound to {@link GL.GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean glIsVBOElementArrayEnabled();
+
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ public int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ *
- * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}
- * and {@link #setFBO(int) setFBO(false)}
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
*
- * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}
- * and {@link #setPBuffer(int) setPBuffer(false)}
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
*
true
(default), bootstrapping the available GL profiles
* will use the highest compatible GL context for each profile,
@@ -120,13 +122,13 @@ public abstract class GLContext {
protected static final int CTX_PROFILE_ES = 1 << 3;
/** ARB_create_context
related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_OPTION_FORWARD = 1 << 4;
- /** ARB_create_context
related: flag debug. Not a cache key. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ /** ARB_create_context
related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
/** GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
- /** Context supports FBO, details see {@link #hasFBO()}.
+ /** Context supports basic FBO, details see {@link #hasFBO()}.
* Not a cache key.
* @see #hasFBO()
* @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
@@ -136,16 +138,6 @@ public abstract class GLContext {
/** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
- protected static final String GL_ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
- protected static final String GL_ARB_framebuffer_object = "GL_ARB_framebuffer_object";
- protected static final String GL_EXT_framebuffer_object = "GL_EXT_framebuffer_object";
- protected static final String GL_EXT_framebuffer_blit = "GL_EXT_framebuffer_blit";
- protected static final String GL_EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample";
- protected static final String GL_EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil";
- protected static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
- protected static final String GL_EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888";
- protected static final String GL_IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888";
-
private static final ThreadLocalGL_ARB_ES2_compatibility
, ARB_framebuffer_object
or all of
- * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
- * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ /**
+ * Returns true
if basic FBO support is available, otherwise false
.
+ *
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * GL_ARB_ES2_compatibility
, GL_ARB_framebuffer_object
, GL_EXT_framebuffer_object
or GL_OES_framebuffer_object
.
+ *
+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *
* @see #CTX_IMPL_FBO + * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) + * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ public final boolean hasFBO() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; @@ -659,13 +659,13 @@ public abstract class GLContext { /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returnstrue
. */
public boolean isNPOTTextureAvailable() {
- return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two);
+ return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
}
public boolean isTextureFormatBGRA8888Available() {
return isGL2GL3() ||
- isExtensionAvailable(GL_EXT_texture_format_BGRA8888) ||
- isExtensionAvailable(GL_IMG_texture_format_BGRA8888) ;
+ isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
}
/** @see GLProfile#isGL4bc() */
@@ -798,7 +798,32 @@ public abstract class GLContext {
}
protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; }
-
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ public abstract int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ *
+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *
+ *+ * FBO support is queried as described in {@link #hasFBO()}. + *
+ * + * @param device the device to request whether FBO is available for + * @param glp {@link GLProfile} to check for FBO capabilities + * @see GLContext#hasFBO() + */ + public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { + return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); + } + /** * @param device the device to request whether the profile is available for * @param reqMajor Key Value either 1, 2, 3 or 4 diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index d6480e7aa..612a02f14 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -50,9 +50,11 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; import javax.media.opengl.GLProfile.ShutdownType; import jogamp.opengl.Debug; @@ -398,9 +400,18 @@ public abstract class GLDrawableFactory { /** * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. *
- * A Pbuffer drawable/surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
- * Otherwise a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below.
+ *
+ * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *
+ *+ * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *
+ *+ * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. *
* * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may benull
for the platform's default device.
@@ -421,42 +432,31 @@ public abstract class GLDrawableFactory {
throws GLException;
/**
- * Creates an offscreen NativeSurface.null
for the platform's default device.
- * @param caps the requested GLCapabilties
- * @param chooser the custom chooser, may be null for default
- * @param width the requested offscreen width
- * @param height the requested offscreen height
- * @return the created offscreen native surface
- *
- * @throws GLException if any window system-specific errors caused
- * the creation of the GLDrawable to fail.
- */
- public abstract NativeSurface createOffscreenSurface(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable caps,
- GLCapabilitiesChooser chooser,
- int width, int height);
-
- /**
- * Highly experimental API entry, allowing developer of new windowing system bindings
- * to leverage the native window handle to produce a NativeSurface implementation (ProxySurface), having the required GLCapabilities.+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + *
+ *+ * Lifecycle (destruction) of the given surface handle shall be handled by the caller. + *
+ *+ * Such surface can be used to instantiate a GLDrawable. With the help of {@link GLAutoDrawableDelegate} + * you will be able to implement a new native windowing system binding almost on-the-fly, see {@link com.jogamp.opengl.swt.GLCanvas}. + *
* - * @param device the platform's target device, shall not benull
+ * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null
for the platform's default device.
+ * Caller has to ensure it is compatible w/ the given windowHandle
+ * @param screenIdx matching screen index of given windowHandle
* @param windowHandle the native window handle
* @param caps the requested GLCapabilties
* @param chooser the custom chooser, may be null for default
- * @return The proxy surface wrapping the windowHandle on the device
+ * @param upstream optional {@link ProxySurface.UpstreamSurfaceHook} allowing control of the {@link ProxySurface}'s lifecycle and data it presents.
+ * @return the created {@link ProxySurface} instance w/ defined surface handle.
*/
- public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
+ public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
+ int screenIdx,
long windowHandle,
- GLCapabilitiesImmutable caps,
- GLCapabilitiesChooser chooser);
+ GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
/**
* Returns true if it is possible to create a GLPbuffer. Some older
@@ -492,23 +492,7 @@ public abstract class GLDrawableFactory {
GLContext shareWith)
throws GLException;
- /**
- * Returns true if it is possible to create an framebuffer object (FBO).
- * - * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. - *
- *- * FBO support is queried as described in {@link GLContext#hasFBO()}. - *
- * - * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may benull
for the platform's default device.
- * @param glp {@link GLProfile} to check for FBO capabilities
- * @see GLContext#hasFBO()
- */
- public final boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp) {
- return 0 != ( GLContext.CTX_IMPL_FBO & GLContext.getAvailableContextProperties(device, glp) );
- }
-
+
//----------------------------------------------------------------------
// Methods for interacting with third-party OpenGL libraries
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index a7200b560..73d13a387 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -117,10 +117,12 @@ public class GLProfile {
* @deprecated Use {@link #initSingleton()}. This method is subject to be removed in future versions of JOGL.
*/
public static void initSingleton(final boolean firstUIActionOnProcess) {
+ final boolean justInitialized;
initLock.lock();
try {
if(!initialized) { // volatile: ok
initialized = true;
+ justInitialized = true;
if(DEBUG) {
System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName());
Thread.dumpStack();
@@ -166,10 +168,17 @@ public class GLProfile {
return null;
}
});
+ } else {
+ justInitialized = false;
}
} finally {
initLock.unlock();
}
+ if(DEBUG) {
+ if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES2Impl ) ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true));
+ }
+ }
}
/**
@@ -1532,18 +1541,17 @@ public class GLProfile {
if(DEBUG) {
// System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
- System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
- System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
- System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
- System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
- System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory);
- System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
- System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl);
- System.err.println("GLProfile.init defaultDevice "+defaultDevice);
- System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
- if(hasGL234Impl || hasGLES1Impl || hasGLES2Impl) { // avoid deadlock
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true));
- }
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
+ System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
+ System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
+ System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
+ System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory);
+ System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
+ System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl);
+ System.err.println("GLProfile.init defaultDevice "+defaultDevice);
+ System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice);
+ System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice);
+ System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
}
}
@@ -1642,24 +1650,6 @@ public class GLProfile {
if (DEBUG) {
System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail);
}
- if( hasGLES2Impl ) {
- // The native ES2 impl. overwrites a previous mapping using 'ES2 compatibility' by a desktop profile
- GLContext.mapAvailableGLVersion(device,
- 2, GLContext.CTX_PROFILE_ES,
- 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_IMPL_ES2_COMPAT);
- if (DEBUG) {
- System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES2 -> ES 2.0");
- }
- }
- if( hasGLES1Impl ) {
- // Always favor the native ES1 impl.
- GLContext.mapAvailableGLVersion(device,
- 1, GLContext.CTX_PROFILE_ES,
- 1, 0, GLContext.CTX_PROFILE_ES);
- if (DEBUG) {
- System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES1 -> ES 1.0");
- }
- }
addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */);
}
@@ -1767,7 +1757,7 @@ public class GLProfile {
}
_mappedProfiles.put(profile, glProfile);
if (DEBUG) {
- System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection());
+ System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection());
}
if(null==defaultGLProfileHW && isHardwareRasterizer[0]) {
defaultGLProfileHW=glProfile;
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 48f7ea24a..c2e36ef9b 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -261,6 +261,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
this.device = device;
}
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
@Override
public void setShallUseOffscreenLayer(boolean v) {
shallUseOffscreenLayer = v;
@@ -1070,7 +1075,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
final Frame frame = new Frame("JOGL AWT Test");
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index cd18c5098..acb8f2183 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -87,7 +87,7 @@ import jogamp.opengl.awt.Java2D;
import jogamp.opengl.awt.Java2DGLContext;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.GLBuffers;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
@@ -250,6 +250,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
this.shareWith = shareWith;
}
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
@Override
public void display() {
if (EventQueue.isDispatchThread()) {
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
index 804e9ee14..aabef29b0 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
@@ -32,7 +32,6 @@ import java.nio.FloatBuffer;
import javax.media.opengl.GL2ES2;
// FIXME: Subsume GL2GL3.GL_DRAW_FRAMEBUFFER -> GL2ES2.GL_DRAW_FRAMEBUFFER !
import javax.media.opengl.GL;
-import javax.media.opengl.GLException;
import javax.media.opengl.GLUniformData;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
@@ -45,7 +44,9 @@ import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderState;
@@ -60,6 +61,7 @@ public class VBORegion2PES2 extends GLRegion {
private FBObject fbo;
+ private TextureAttachment texA;
private PMVMatrix fboPMVMatrix;
GLUniformData mgl_fboPMVMatrix;
@@ -72,7 +74,7 @@ public class VBORegion2PES2 extends GLRegion {
super(renderModes);
fboPMVMatrix = new PMVMatrix();
mgl_fboPMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, fboPMVMatrix.glGetPMvMatrixf());
- mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
+ mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
}
public void update(GL2ES2 gl, RenderState rs) {
@@ -214,8 +216,9 @@ public class VBORegion2PES2 extends GLRegion {
final ShaderState st = rs.getShaderState();
gl.glViewport(0, 0, width, hight);
- st.uniform(gl, mgl_ActiveTexture);
- fbo.use(gl, 0);
+ st.uniform(gl, mgl_ActiveTexture);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + mgl_ActiveTexture.intValue());
+ fbo.use(gl, texA);
verticeFboAttr.enableBuffer(gl, true);
texCoordFboAttr.enableBuffer(gl, true);
indicesFbo.enableBuffer(gl, true);
@@ -244,20 +247,16 @@ public class VBORegion2PES2 extends GLRegion {
// System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5));
if(null != fbo && fbo.getWidth() != tex_width_c && fbo.getHeight() != tex_height_c ) {
- fbo.destroy(gl);
- fbo = null;
+ fbo.reset(gl, tex_width_c, tex_height_c);
}
- if(null == fbo) {
- fbo = new FBObject(tex_width_c, tex_height_c);
- fbo.init(gl);
+ if(null == fbo) {
+ fbo = new FBObject();
+ fbo.reset(gl, tex_width_c, tex_height_c);
// FIXME: shall not use bilinear, due to own AA ? However, w/o bilinear result is not smooth
- fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- // fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- fbo.attachDepthBuffer(gl, GL.GL_DEPTH_COMPONENT16); // FIXME: or shall we use 24 or 32 bit depth ?
- if(!fbo.isStatusValid()) {
- throw new GLException("FBO invalid: "+fbo);
- }
+ texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ // texA = fbo.attachTexture2D(gl, 0, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
} else {
fbo.bind(gl);
}
@@ -305,6 +304,7 @@ public class VBORegion2PES2 extends GLRegion {
if(null != fbo) {
fbo.destroy(gl);
fbo = null;
+ texA = null;
}
if(null != verticeTxtAttr) {
st.ownAttribute(verticeTxtAttr, false);
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 4dd8806fa..e730bc62e 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -49,8 +49,9 @@ import com.jogamp.common.os.DynamicLookupHelper;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.gluegen.runtime.FunctionAddressResolver;
import com.jogamp.gluegen.runtime.ProcAddressTable;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -88,13 +89,14 @@ public abstract class GLContextImpl extends GLContext {
// Tracks creation and initialization of buffer objects to avoid
// repeated glGet calls upon glMapBuffer operations
private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet
- private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
- private GLStateTracker glStateTracker = new GLStateTracker();
+ private final GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
+ private final GLStateTracker glStateTracker = new GLStateTracker();
private GLDebugMessageHandler glDebugHandler = null;
+ private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read }
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
-
+
protected GL gl;
protected static final Object mappedContextTypeObjectLock;
@@ -140,11 +142,11 @@ public abstract class GLContextImpl extends GLContext {
bufferSizeTracker.clearCachedBufferSizes();
}
- if (bufferStateTracker != null) {
+ if (bufferStateTracker != null) { // Invoked by {@link GL#glBindFramebuffer(int, int)}.
+ * + *Assumes valid framebufferName
range of [0..{@link Integer#MAX_VALUE}]
Does not throw an exception if target
is unknown or framebufferName
invalid.
device
{@link AbstractGraphicsDevice#getConnection()},
* either a preexisting or newly created, or null
if creation failed or not supported.1
refers to ES1 and 2
to ES2,
* otherwise the profile is ignored.
@@ -125,6 +126,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
// Dispatching GLDrawable construction in respect to the NativeSurface Capabilities
//
+ @Override
public GLDrawable createGLDrawable(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -132,23 +134,37 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration();
final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
final AbstractGraphicsDevice adevice = config.getScreen().getDevice();
+ final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile());
GLDrawable result = null;
adevice.lock();
try {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
- // layered surface -> Offscreen/PBuffer
+ // layered surface -> Offscreen/[FBO|PBuffer]
final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable();
chosenCapsMod.setOnscreen(false);
- chosenCapsMod.setPBuffer(canCreateGLPbuffer(adevice));
+ if( isFBOAvailable ) {
+ chosenCapsMod.setFBO(true);
+ } else if(canCreateGLPbuffer(adevice)) {
+ chosenCapsMod.setPBuffer(true);
+ } else {
+ chosenCapsMod.setFBO(false);
+ chosenCapsMod.setPBuffer(false);
+ }
config.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
+ }
+ if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
+ // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
+ result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ } else {
+ result = createOffscreenDrawableImpl(target);
}
- result = createOffscreenDrawableImpl(target);
} else if(chosenCaps.isOnscreen()) {
// onscreen
if(DEBUG) {
@@ -158,12 +174,18 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
} else {
// offscreen
if(DEBUG) {
- System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+chosenCaps.isPBuffer()+"): "+target);
+ System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO-chosen(-avail)/PBuffer: "+chosenCaps.isFBO()+"("+isFBOAvailable+")/"+chosenCaps.isPBuffer()+": "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target);
}
- result = createOffscreenDrawableImpl(target);
+ if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
+ // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
+ result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ } else {
+ result = createOffscreenDrawableImpl(target);
+ }
}
} finally {
adevice.unlock();
@@ -176,43 +198,42 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
//
- // Onscreen GLDrawable construction
+ // Onscreen GLDrawable construction
//
protected abstract GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target);
//---------------------------------------------------------------------------
//
- // PBuffer Offscreen GLDrawable construction
+ // PBuffer Offscreen GLDrawable construction
//
-
+
+ @Override
public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
+ @Override
public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
int width,
int height,
GLContext shareWith) {
- if(height<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ if(width<=0 || height<=0) {
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
-
AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
-
- if (!canCreateGLPbuffer(device)) {
- throw new GLException("Pbuffer support not available with device: "+device);
+ if ( !canCreateGLPbuffer(device) ) {
+ throw new GLException("Pbuffer not available with device: "+device);
}
-
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
GLDrawableImpl drawable = null;
device.lock();
try {
- drawable = (GLDrawableImpl) createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
+ drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
if(null != drawable) {
drawable.setRealized(true);
}
@@ -228,75 +249,155 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
//
- // Offscreen GLDrawable construction
+ // Offscreen GLDrawable construction
//
- protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
-
+ @Override
public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
- int width,
- int height) {
+ int width, int height) {
if(width<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
+
+ if( capsRequested.isFBO() && GLContext.isFBOAvailable(device, capsRequested.getGLProfile()) ) {
+ device.lock();
+ try {
+ return createFBODrawableImpl(device, capsRequested, chooser, width, height);
+ } finally {
+ device.unlock();
+ }
+ }
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, false, canCreateGLPbuffer(device));
device.lock();
try {
- return createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
+ return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
} finally {
device.unlock();
}
}
- public NativeSurface createOffscreenSurface(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ /** Creates a platform independent offscreen FBO GLDrawable implementation */
+ protected GLDrawable createFBODrawableImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int initialWidth, int initialHeight) {
+ final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ final NativeSurface dummySurface = createDummySurfaceImpl(device, true, dummyCaps, null, 64, 64);
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
+
+ return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */);
+ }
+
+ /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */
+ protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
+
+ /**
+ * Creates a mutable {@link ProxySurface} w/o defined surface handle.
+ * + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + *
+ *+ * Lifecycle (destruction) of the TBD surface handle shall be handled by the caller. + *
+ * @param device a valid platform dependent target device. + * @param createNewDevice iftrue
a new device instance is created using device
details,
+ * otherwise device
instance is used as-is.
+ * @param capsChosen
+ * @param capsRequested
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ * @param lifecycleHook optional control of the surface's lifecycle
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
+ */
+ protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook);
+
+ /**
+ * A dummy surface is not visible on screen and will not be used to render directly to,
+ * it maybe on- or offscreen.
+ * + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. + * It also allows creation of framebuffer objects which are used for rendering. + *
+ * @param deviceReq which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may benull
for the platform's default device.
+ * @param requestedCaps
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ *
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
+ */
+ public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int width, int height) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
device.lock();
try {
- return createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height);
+ return createDummySurfaceImpl(device, true, requestedCaps, chooser, width, height);
} finally {
device.unlock();
}
}
-
+
/**
- * creates an offscreen NativeSurface, which must implement SurfaceChangeable as well,
- * so the windowing system related implementation is able to set the surface handle.
+ * A dummy surface is not visible on screen and will not be used to render directly to,
+ * it maybe on- or offscreen.
+ * + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. + * It also allows creation of framebuffer objects which are used for rendering. + *
+ * @param device a valid platform dependent target device. + * @param createNewDevice iftrue
a new device instance is created using device
details,
+ * otherwise device
instance is used as-is.
+ * @param requestedCaps
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
*/
- protected abstract NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height);
+ public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);
- public ProxySurface createProxySurface(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ //---------------------------------------------------------------------------
+ //
+ // ProxySurface (Wrapped pre-existing native surface) construction
+ //
+
+ @Override
+ public ProxySurface createProxySurface(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
+ GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
- throw new GLException("No shared device for requested: "+device);
+ throw new GLException("No shared device for requested: "+deviceReq);
}
device.lock();
try {
- return createProxySurfaceImpl(device, windowHandle, capsRequested, chooser);
+ return createProxySurfaceImpl(device, screenIdx, windowHandle, capsRequested, chooser, upstream);
} finally {
device.unlock();
}
- }
-
- protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+ }
+
+ /**
+ * Creates a {@link ProxySurface} with a set surface handle.
+ * + * Implementation is also required to allocate it's own {@link AbstractGraphicsDevice} instance. + *
+ * @param upstream TODO + */ + protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, + GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); //--------------------------------------------------------------------------- // @@ -304,7 +405,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // protected abstract GLContext createExternalGLContextImpl(); - + + @Override public GLContext createExternalGLContext() { NativeWindowFactory.getDefaultToolkitLock().lock(); try { @@ -316,6 +418,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected abstract GLDrawable createExternalGLDrawableImpl(); + @Override public GLDrawable createExternalGLDrawable() { NativeWindowFactory.getDefaultToolkitLock().lock(); try { @@ -398,7 +501,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * normal ahead of time, use resetDisplayGamma(). Throws * IllegalArgumentException if any of the parameters were * out-of-bounds. - * + * * @param gamma The gamma value, typically > 1.0 (default value is * 1.0) * @param brightness The brightness value between -1.0 and 1.0, @@ -484,7 +587,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { return; if (gammaShutdownHook == null) { gammaShutdownHook = new Thread(new Runnable() { - public void run() { + @Override + public void run() { synchronized (GLDrawableFactoryImpl.this) { resetGammaRamp(originalGammaRamp); } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index 58a4ac6b4..abf2bf557 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -42,6 +42,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -75,7 +76,7 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); if ( caps.getDoubleBuffered() ) { if(!surface.surfaceSwap()) { int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] @@ -149,6 +150,9 @@ public abstract class GLDrawableImpl implements GLDrawable { realized = realizedArg; AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice(); if(realizedArg) { + if(surface instanceof ProxySurface) { + ((ProxySurface)surface).createNotify(); + } if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) { throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)"); } @@ -156,17 +160,21 @@ public abstract class GLDrawableImpl implements GLDrawable { aDevice.lock(); } try { - setRealizedImpl(); if(realizedArg) { + setRealizedImpl(); updateHandle(); } else { destroyHandle(); + setRealizedImpl(); } } finally { if(realizedArg) { unlockSurface(); } else { aDevice.unlock(); + if(surface instanceof ProxySurface) { + ((ProxySurface)surface).destroyNotify(); + } } } } else if(DEBUG) { @@ -175,6 +183,39 @@ public abstract class GLDrawableImpl implements GLDrawable { } protected abstract void setRealizedImpl(); + /** + * Callback for special implementations, allowing GLContext to trigger GL related lifecycle:construct
, destroy
.
+ *
+ * If realized
is true
, the context has just been created and made current.
+ *
+ * If realized
is false
, the context is still current and will be release and destroyed after this method returns.
+ *
+ * @see #contextMadeCurrent(GLContext, boolean)
+ */
+ protected void contextRealized(GLContext glc, boolean realized) {}
+
+ /**
+ * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent
, release
.
+ *
+ * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. + *
+ *
+ * If current
is true
, the context has just been made current.
+ *
+ * If current
is false
, the context is still current and will be release after this method returns.
+ *
+ * We intentionally override a non native EGL device ES profile mapping, + * i.e. this will override/modify an already 'set' X11/WGL/.. mapping. + *
+ * + * @param device + */ + protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { + mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } + + protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) { + int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES ); + mapCurrentAvailableGLVersionImpl(device, major, 0, ctp); + } + private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) { + if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) { + // ES1 or ES2 + final int reqMajor = major; + final int reqProfile = GLContext.CTX_PROFILE_ES; + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, + major, minor, ctp); + } + } + + protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) { + return GLContext.getAvailableGLVersionsSet(device); + } + protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) { + GLContext.setAvailableGLVersionsSet(device); + } + protected static String toHexString(int hex) { return GLContext.toHexString(hex); } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index 7f10d3bd9..432010f49 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -136,7 +136,17 @@ public class EGLDisplayUtil { return res; } - public static final EGLGraphicsDevice.EGLTerminateCallback eglTerminateCallback = new EGLGraphicsDevice.EGLTerminateCallback() { + public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() { + public long eglGetAndInitDisplay(long nativeDisplayID) { + long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + return eglDisplay; + } public void eglTerminate(long eglDisplayHandle) { EGLDisplayUtil.eglTerminate(eglDisplayHandle); } @@ -148,17 +158,12 @@ public class EGLDisplayUtil { * @param unitID * @return an initialized EGLGraphicsDevice * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails - * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLTerminateCallback) + * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLDisplayLifecycleCallback) */ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) { - long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, connection, unitID, eglTerminateCallback); + final EGLGraphicsDevice eglDisplay = new EGLGraphicsDevice(nativeDisplayID, 0, connection, unitID, eglLifecycleCallback); + eglDisplay.open(); + return eglDisplay; } /** @@ -189,6 +194,6 @@ public class EGLDisplayUtil { throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); } final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice(); - return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglTerminateCallback); + return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index d777c4f04..383b61f88 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,82 +36,65 @@ package jogamp.opengl.egl; -import jogamp.opengl.GLDynamicLookupHelper; -import jogamp.opengl.GLDrawableImpl; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; -import javax.media.nativewindow.*; -import javax.media.nativewindow.VisualIDHolder.VIDType; -import javax.media.opengl.*; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; -import com.jogamp.nativewindow.egl.*; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public abstract class EGLDrawable extends GLDrawableImpl { - private boolean ownEGLDisplay = false; // for destruction private boolean ownEGLSurface = false; // for destruction - private EGLGraphicsConfiguration eglConfig; - private EGLGraphicsDevice eglDevice; - private long eglSurface; - protected EGLDrawable(EGLDrawableFactory factory, - NativeSurface component) throws GLException { + protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException { super(factory, component, false); - eglSurface=EGL.EGL_NO_SURFACE; - eglDevice=null; - } - - public final long getDisplay() { - return null != eglDevice ? eglDevice.getHandle() : 0; - } - - @Override - public final long getHandle() { - return eglSurface; - } - - public final EGLGraphicsConfiguration getGraphicsConfiguration() { - return eglConfig; - } - - @Override - public final GLCapabilitiesImmutable getChosenGLCapabilities() { - return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities(); } @Override public abstract GLContext createContext(GLContext shareWith); - protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle); + protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle); private final void recreateSurface() { - // create a new EGLSurface .. - if(EGL.EGL_NO_SURFACE!=eglSurface) { - EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface); - } - + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); if(DEBUG) { - System.err.println(getThreadName() + ": createSurface using "+eglDevice+", "+eglConfig); + System.err.println(getThreadName() + ": createSurface using "+eglConfig); + } + if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) { + EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle()); } - - eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surface.getSurfaceHandle()); - int eglError0 = EGL.EGL_SUCCESS; + + final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook(); + final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface(); + long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle()); + + int eglError0; if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) { // Try window handle if available and differs (Windows HDC / HWND). // ANGLE impl. required HWND on Windows. - if(surface instanceof NativeWindow) { - final NativeWindow nw = (NativeWindow) surface; + if(upstreamSurface instanceof NativeWindow) { + final NativeWindow nw = (NativeWindow) upstreamSurface; if(nw.getWindowHandle() != nw.getSurfaceHandle()) { if(DEBUG) { System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); } - eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), nw.getWindowHandle()); + eglSurface = createSurface(eglConfig, nw.getWindowHandle()); if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); } } } } + } else { + eglError0 = EGL.EGL_SUCCESS; } if (EGL.EGL_NO_SURFACE == eglSurface) { throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0)); @@ -120,6 +103,8 @@ public abstract class EGLDrawable extends GLDrawableImpl { if(DEBUG) { System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface)); } + + ((MutableSurface)surface).setSurfaceHandle(eglSurface); } @Override @@ -131,123 +116,71 @@ public abstract class EGLDrawable extends GLDrawableImpl { @Override protected final void setRealizedImpl() { + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); if (realized) { - AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); - AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); - if(aDevice instanceof EGLGraphicsDevice) { + final long eglDisplayHandle = eglDevice.getHandle(); + if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) { + throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + } + int[] tmp = new int[1]; + boolean eglSurfaceValid = 0 != surface.getSurfaceHandle(); + if(eglSurfaceValid) { + eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0); + if(!eglSurfaceValid) { + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface); + } + } + } + if(eglSurfaceValid) { + // surface holds valid EGLSurface if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START"); + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl re-using component's EGLSurface: handle "+toHexString(surface.getSurfaceHandle())); + } + ownEGLSurface=false; + } else { + // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); + // However .. let's validate the surface object first + if( ! (surface instanceof ProxySurface) ) { + throw new InternalError("surface not ProxySurface: "+surface.getClass().getName()+", "+surface); } - // just fetch the data .. trust but verify .. - ownEGLDisplay = false; - eglDevice = (EGLGraphicsDevice) aDevice; - if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) { - throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook(); + if( null == upstreamHook ) { + throw new InternalError("null upstreamHook of: "+surface); } - if(aConfig instanceof EGLGraphicsConfiguration) { - eglConfig = (EGLGraphicsConfiguration) aConfig; // done .. - if (null == eglConfig) { - throw new GLException("Null EGLGraphicsConfiguration from "+aConfig); - } - - int[] tmp = new int[1]; - if ( 0 != surface.getSurfaceHandle() && - EGL.eglQuerySurface(eglDevice.getHandle(), surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { - // surface holds static EGLSurface - eglSurface = surface.getSurfaceHandle(); - if(DEBUG) { - System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface)); - } - ownEGLSurface=false; - } else { - // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); - ownEGLSurface=true; - } - } else { - throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig); + if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) { + throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook); } - } else { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START"); + if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) { + throw new InternalError("null upstream surface"); } - // create a new EGL config .. - ownEGLDisplay=true; - // EGLSurface is ours .. ownEGLSurface=true; - - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); - AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); - final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); - if(aConfig instanceof EGLGraphicsConfiguration) { - final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); - if(0 == capsChosen.getEGLConfig()) { - // 'refresh' the native EGLConfig handle - capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); - if(0 == capsChosen.getEGLConfig()) { - throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); - } - } - eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); - if(DEBUG) { - System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig); - } - } else { - eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); - - if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); - } else if(DEBUG) { - System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig); - } + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface"); } - // subsequent updateHandle() will issue recreateSurface(); - } - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface); } - } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) { + } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) { if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle())); } // Destroy the window surface - if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) { + if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) { throw new GLException("Error destroying window surface (eglDestroySurface)"); } - eglSurface = EGL.EGL_NO_SURFACE; - eglConfig=null; - eglDevice.close(); - eglDevice=null; + ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE); } } @Override protected final void swapBuffersImpl() { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - if(!EGL.eglSwapBuffers(eglDevice.getHandle(), eglSurface)) { + if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); } } - /** - * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable. - * Leave it here for later impl. of an EGLExternalDrawable. - public int getWidth() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) { - throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } - - public int getHeight() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) { - throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } */ - @Override public GLDynamicLookupHelper getGLDynamicLookupHelper() { if (getGLProfile().usesNativeGLES2()) { @@ -263,10 +196,9 @@ public abstract class EGLDrawable extends GLDrawableImpl { public String toString() { return getClass().getName()+"[realized "+isRealized()+ ",\n\tfactory "+getFactory()+ - ",\n\tdevice "+eglDevice+ ",\n\tsurface "+getNativeSurface()+ - ",\n\teglSurface "+toHexString(eglSurface)+ - ",\n\teglConfig "+eglConfig+ + ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+ + ",\n\teglConfig "+surface.getGraphicsConfiguration()+ ",\n\trequested "+getRequestedGLCapabilities()+ ",\n\tchosen "+getChosenGLCapabilities()+"]"; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index f4fa1f13f..c848e3e5c 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -46,21 +46,29 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.nativewindow.VisualIDHolder; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.GLProfile.ShutdownType; +import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.os.Platform; @@ -69,6 +77,9 @@ import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public class EGLDrawableFactory extends GLDrawableFactoryImpl { + /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true); + /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); + private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; private static boolean isANGLE = false; @@ -231,7 +242,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { // final EGLContext getContextES1() { return contextES1; } // final EGLContext getContextES2() { return contextES2; } final boolean wasES1ContextAvailable() { return wasES1ContextCreated; } - final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } + final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } } @Override @@ -245,35 +256,98 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; } - /** - private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) { - boolean madeCurrent = false; - final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile)); - caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); - caps.setDoubleBuffered(false); - caps.setOnscreen(false); - caps.setPBuffer(true); - final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) ); - if(null!=drawable) { + private boolean isEGLContextAvailable(AbstractGraphicsDevice adevice, EGLGraphicsDevice sharedEGLDevice, String profileString) { + if( !GLProfile.isAvailable(adevice, profileString) ) { + return false; + } + final GLProfile glp = GLProfile.get(adevice, profileString) ; + final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory(); + EGLGraphicsDevice eglDevice = null; + NativeSurface surface = null; + ProxySurface upstreamSurface = null; // X11, GLX, .. + boolean success = false; + boolean deviceFromUpstreamSurface = false; + try { + final GLCapabilities caps = new GLCapabilities(glp); + caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); + if(adevice instanceof EGLGraphicsDevice || null == desktopFactory || !QUERY_EGL_ES_NATIVE_TK) { + eglDevice = sharedEGLDevice; // reuse + surface = createDummySurfaceImpl(eglDevice, false, caps, null, 64, 64); // egl pbuffer offscreen + upstreamSurface = (ProxySurface)surface; + upstreamSurface.createNotify(); + deviceFromUpstreamSurface = false; + } else { + surface = desktopFactory.createDummySurface(adevice, caps, null, 64, 64); // X11, WGL, .. dummy window + upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ; + if(null != upstreamSurface) { + upstreamSurface.createNotify(); + } + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + deviceFromUpstreamSurface = true; + } + + final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); + drawable.setRealized(true); final EGLContext context = (EGLContext) drawable.createContext(null); if (null != context) { - context.setSynchronized(true); try { context.makeCurrent(); // could cause exception - madeCurrent = context.isCurrent(); + success = context.isCurrent(); + if(success) { + final String glVersion = context.getGL().glGetString(GL.GL_VERSION); + if(null == glVersion) { + // Oops .. something is wrong + if(DEBUG) { + System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!"); + } + success = false; + } + } + if(success) { + context.mapCurrentAvailableGLVersion(eglDevice); + if(eglDevice != adevice) { + context.mapCurrentAvailableGLVersion(adevice); + } + } } catch (GLException gle) { if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed"); + System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed"); gle.printStackTrace(); } } finally { context.destroy(); } } - drawable.destroy(); + drawable.setRealized(false); + } catch (Throwable t) { + if(DEBUG) { + System.err.println("Catched Exception:"); + t.printStackTrace(); + } + success = false; + } finally { + if(eglDevice == sharedEGLDevice) { + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + } else if( deviceFromUpstreamSurface ) { + if(null != eglDevice) { + eglDevice.close(); + } + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + } else { + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + if(null != eglDevice) { + eglDevice.close(); + } + } } - return madeCurrent; - } */ + return success; + } /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) { if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) { @@ -285,18 +359,41 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { sr = sharedMap.get(connection); } if(null==sr) { - final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, connection, adevice.getUnitID()); + final boolean madeCurrentES1; + final boolean madeCurrentES2; + final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1); - // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2); - final boolean madeCurrentES1 = true; // FIXME - final boolean madeCurrentES2 = true; // FIXME + if(QUERY_EGL_ES) { + madeCurrentES1 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES1); + madeCurrentES2 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES2); + } else { + madeCurrentES1 = true; + madeCurrentES2 = true; + EGLContext.mapStaticGLESVersion(sharedDevice, 1); + if(sharedDevice != adevice) { + EGLContext.mapStaticGLESVersion(adevice, 1); + } + EGLContext.mapStaticGLESVersion(sharedDevice, 2); + if(sharedDevice != adevice) { + EGLContext.mapStaticGLESVersion(adevice, 2); + } + } + + if( !EGLContext.getAvailableGLVersionsSet(adevice) ) { + // Even though we override the non EGL native mapping intentionally, + // avoid exception due to double 'set' - carefull exception of the rule. + EGLContext.setAvailableGLVersionsSet(adevice); + } sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2); + synchronized(sharedMap) { sharedMap.put(connection, sr); + if(adevice != sharedDevice) { + sharedMap.put(sharedDevice.getConnection(), sr); + } } if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: device: " + sharedDevice); + System.err.println("EGLDrawableFactory.createShared: devices: queried " + QUERY_EGL_ES + "[nativeTK "+QUERY_EGL_ES_NATIVE_TK+"], " + adevice + ", " + sharedDevice); System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1); System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2); } @@ -367,8 +464,51 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, target); + return new EGLOnscreenDrawable(this, getEGLSurface(target)); + } + + protected static NativeSurface getEGLSurface(NativeSurface surface) { + AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); + AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); + if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) { + // already in native EGL format + if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - already in EGL format - use as-is: "+aConfig); + } + return surface; + } + // create EGL instance out of platform native types + final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); + final EGLGraphicsConfiguration eglConfig; + if( aConfig instanceof EGLGraphicsConfiguration ) { + // Config is already in EGL type - reuse .. + final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); + if( 0 == capsChosen.getEGLConfig() ) { + // 'refresh' the native EGLConfig handle + capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); + if( 0 == capsChosen.getEGLConfig() ) { + throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); + } + } + eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); + if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - Reusing chosenCaps: "+eglConfig); + } + } else { + eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); + + if (null == eglConfig) { + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); + } else if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - Chosen eglConfig: "+eglConfig); + } + } + return new WrappedSurface(eglConfig, EGL.EGL_NO_SURFACE, surface.getWidth(), surface.getHeight(), new EGLUpstreamSurfaceHook(surface)); } + static String getThreadName() { return Thread.currentThread().getName(); } @Override protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { @@ -390,22 +530,115 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; - final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); - WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser)); - ns.surfaceSizeChanged(width, height); - return ns; + protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + final EGLGraphicsDevice device; + if(createNewDevice) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + } else { + device = (EGLGraphicsDevice) deviceReq; + } + final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); + final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); + if(null == config) { + throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); + } + return new WrappedSurface(config, 0, width, height, lifecycleHook); + } + + @Override + public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { + final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + } + private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { + @Override + public final void create(ProxySurface s) { + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if(0 == eglDevice.getHandle()) { + eglDevice.open(); + s.setImplBitfield(ProxySurface.OWN_DEVICE); + } + createPBufferSurfaceImpl(s, false); + if(DEBUG) { + System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final void destroy(ProxySurface s) { + if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) s.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(EGL.EGL_NO_SURFACE); + if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) { + eglDevice.close(); + } + if(DEBUG) { + System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final int getWidth(ProxySurface s) { + return s.initialWidth; + } + @Override + public final int getHeight(ProxySurface s) { + return s.initialHeight; + } + @Override + public String toString() { + return "EGLSurfaceLifecycleHook[]"; + } + + }; + + /** + * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface. + * It will also hold the resulting pbuffer surface handle. + * @param useTexture + * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle + */ + protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) ms.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final int texFormat; + + if(useTexture) { + texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; + } else { + texFormat = EGL.EGL_NO_TEXTURE; + } + + if (DEBUG) { + System.out.println("Pbuffer config: " + config); + } + + final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat); + final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0); + if (EGL.EGL_NO_SURFACE==surf) { + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+ms.getWidth()+"x"+ms.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); + } + ms.setSurfaceHandle(surf); + return ms; } @Override - protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { - // FIXME device/windowHandle -> screen ?! - EGLGraphicsDevice device = (EGLGraphicsDevice) adevice; - DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - WrappedSurface ns = new WrappedSurface(cfg, windowHandle); - return ns; + protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); + final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); + return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 56e7a4d22..214b36493 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -151,7 +151,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config, boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) { ListEGL.eglGetDisplay(nativeDisplayID)
+ * inclusive EGL.eglInitialize(eglDisplayHandle, ..)
call.
+ * @param eglDisplayHandle
+ */
+ public long eglGetAndInitDisplay(long nativeDisplayID);
+
/**
* Implementation should issue an EGL.eglTerminate(eglDisplayHandle)
call.
* @param eglDisplayHandle
@@ -61,28 +68,45 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
*/
public EGLGraphicsDevice(String connection, int unitID) {
super(NativeWindowFactory.TYPE_EGL, connection, unitID);
- this.nativeDisplayID = 0;
- this.eglTerminateCallback = null;
+ this.nativeDisplayID = 0 ; // EGL.EGL_DEFAULT_DISPLAY
+ this.eglLifecycleCallback = null;
}
- public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLTerminateCallback eglTerminateCallback) {
+ public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLDisplayLifecycleCallback eglLifecycleCallback) {
super(NativeWindowFactory.TYPE_EGL, connection, unitID, eglDisplay);
this.nativeDisplayID = nativeDisplayID;
- this.eglTerminateCallback = eglTerminateCallback;
+ this.eglLifecycleCallback = eglLifecycleCallback;
}
public long getNativeDisplayID() { return nativeDisplayID; }
+ @Override
public Object clone() {
return super.clone();
}
+
+ @Override
+ public boolean open() {
+ if(null != eglLifecycleCallback && 0 == handle) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.open(): "+this);
+ }
+ handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID);
+ if(0 == handle) {
+ throw new NativeWindowException("EGLGraphicsDevice.open() failed: "+this);
+ }
+ return true;
+ }
+ return false;
+ }
+ @Override
public boolean close() {
- if(null != eglTerminateCallback) {
+ if(null != eglLifecycleCallback && 0 != handle) {
if(DEBUG) {
- System.err.println(Thread.currentThread().getName() + " - eglTerminate: "+this);
+ System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.close(): "+this);
}
- eglTerminateCallback.eglTerminate(handle);
+ eglLifecycleCallback.eglTerminate(handle);
}
return super.close();
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index 735d85fb1..0494bb408 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -43,7 +43,6 @@ import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import jogamp.common.awt.AWTEDTExecutor;
import jogamp.nativewindow.macosx.OSXUtil;
public class SWTAccessor {
@@ -204,8 +203,6 @@ public class SWTAccessor {
if( null != OS_gtk_class ) {
long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
long displayHandle = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, widgedHandle);
- // FIXME: May think about creating a private non-shared X11 Display handle, like we use to for AWT
- // to avoid locking problems !
return new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, false);
}
if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index a02332413..7a98e3c25 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -33,7 +33,6 @@
package com.jogamp.nativewindow.x11;
-import jogamp.nativewindow.Debug;
import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
@@ -46,7 +45,7 @@ import javax.media.nativewindow.ToolkitLock;
*/
public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- final boolean closeDisplay;
+ final boolean handleOwner;
/** Constructs a new X11GraphicsDevice corresponding to the given connection and default
* {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.null
.
+ *
+ * The default implementation is a NOP
.
+ *
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
+ * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
+ * issue the native open operation in case handle is null
.
+ *
null
and opening was successful, otherwise false.
+ */
+ public boolean open();
+
/**
- * Optionally closing the device.
+ * Optionally closing the device if handle is not null
.
*
* The default implementation is a NOP
, just setting the handle to null
.
*
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice} + * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice} + * issue the native close operation or skip it depending on the handles's ownership. + *
* - * @return true if the handle was notnull
, otherwise false.
+ * @return true if the handle was not null
and closing was successful, otherwise false.
*/
public boolean close();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 187959a67..583fde07f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -97,22 +97,27 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
}
}
+ @Override
public final String getType() {
return type;
}
+ @Override
public final String getConnection() {
return connection;
}
+ @Override
public final int getUnitID() {
return unitID;
}
+ @Override
public final String getUniqueID() {
return uniqueID;
}
+ @Override
public final long getHandle() {
return handle;
}
@@ -124,6 +129,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock)
*/
+ @Override
public final void lock() {
toolkitLock.lock();
}
@@ -135,10 +141,17 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock)
*/
+ @Override
public final void unlock() {
toolkitLock.unlock();
}
+
+ @Override
+ public boolean open() {
+ return false;
+ }
+ @Override
public boolean close() {
if(0 != handle) {
handle = 0;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
new file mode 100644
index 000000000..ff53c8109
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow;
+
+/**
+ * Provides a {@link NativeSurface} with a mutable surfaceHandle
+ * via {@link #setSurfaceHandle(long)}.
+ *
+ * @see NativeSurface
+ */
+public interface MutableSurface extends NativeSurface {
+
+ /**
+ * Sets the surface handle which is created outside of this implementation.
+ */
+ public void setSurfaceHandle(long surfaceHandle);
+}
+
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
index 1dabc3dcd..7fc9789c2 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
@@ -28,38 +28,108 @@
package javax.media.nativewindow;
-
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.SurfaceUpdatedHelper;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
-public abstract class ProxySurface implements NativeSurface {
+public abstract class ProxySurface implements NativeSurface, MutableSurface {
public static final boolean DEBUG = Debug.debug("ProxySurface");
+
+ /**
+ * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}.
+ * @see #setImplBitfield(int)
+ * @see #getImplBitfield()
+ */
+ public static final int OWN_DEVICE = 1 << 7;
+
+ /**
+ * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete.
+ * @see #setImplBitfield(int)
+ * @see #getImplBitfield()
+ */
+ public static final int INVISIBLE_WINDOW = 1 << 8;
- private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
- private AbstractGraphicsConfiguration config; // control access due to delegation
- protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */
+ public interface UpstreamSurfaceHook {
+ /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */
+ public void create(ProxySurface s);
+ /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */
+ public void destroy(ProxySurface s);
+
+ /** Returns the width of the upstream surface */
+ public int getWidth(ProxySurface s);
+ /** Returns the height of the upstream surface */
+ public int getHeight(ProxySurface s);
+ }
+
+ private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+ private final AbstractGraphicsConfiguration config; // control access due to delegation
+ private final UpstreamSurfaceHook upstream;
+ public final int initialWidth;
+ public final int initialHeight;
private long surfaceHandle_old;
+ protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
protected long displayHandle;
- protected int height;
protected int scrnIndex;
- protected int width;
+ protected int implBitfield;
- public ProxySurface(AbstractGraphicsConfiguration cfg) {
- invalidate();
- config = cfg;
- displayHandle=cfg.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
- surfaceHandle_old = 0;
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param initialWidth the initial width
+ * @param initialHeight the initial height
+ */
+ protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) {
+ if(null == cfg) {
+ throw new IllegalArgumentException("null config");
+ }
+ this.config = cfg;
+ this.upstream = upstream;
+ this.initialWidth = initialWidth;
+ this.initialHeight = initialHeight;
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.surfaceHandle_old = 0;
+ this.implBitfield = 0;
}
- void invalidate() {
- displayHandle = 0;
- invalidateImpl();
+ public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
+
+ /**
+ * If a valid {@link UpstreamSurfaceHook} instance is passed in the
+ * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor},
+ * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set.
+ */
+ public void createNotify() {
+ if(null != upstream) {
+ upstream.create(this);
+ }
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.surfaceHandle_old = 0;
}
- protected abstract void invalidateImpl();
-
+
+ /**
+ * If a valid {@link UpstreamSurfaceHook} instance is passed in the
+ * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor},
+ * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared.
+ */
+ public void destroyNotify() {
+ if(null != upstream) {
+ upstream.destroy(this);
+ invalidateImpl();
+ }
+ this.displayHandle = 0;
+ this.surfaceHandle_old = 0;
+ }
+
+ /**
+ * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed.
+ * @see #destroyNotify()
+ */
+ protected void invalidateImpl() {
+ throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
+ }
+
@Override
public final long getDisplayHandle() {
return displayHandle;
@@ -82,19 +152,23 @@ public abstract class ProxySurface implements NativeSurface {
@Override
public abstract long getSurfaceHandle();
+ @Override
+ public abstract void setSurfaceHandle(long surfaceHandle);
+
@Override
public final int getWidth() {
- return width;
+ if(null != upstream) {
+ return upstream.getWidth(this);
+ }
+ return initialWidth;
}
@Override
public final int getHeight() {
- return height;
- }
-
- public void surfaceSizeChanged(int width, int height) {
- this.width = width;
- this.height = height;
+ if(null != upstream) {
+ return upstream.getHeight(this);
+ }
+ return initialHeight;
}
@Override
@@ -187,7 +261,10 @@ public abstract class ProxySurface implements NativeSurface {
public final Thread getSurfaceLockOwner() {
return surfaceLock.getOwner();
}
-
+
@Override
public abstract String toString();
+
+ public int getImplBitfield() { return implBitfield; }
+ public void setImplBitfield(int v) { implBitfield=v; }
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java
deleted file mode 100644
index 956e68e61..000000000
--- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package javax.media.nativewindow;
-
-public interface SurfaceChangeable {
-
- /** Sets the surface handle which is created outside of this implementation */
- public void setSurfaceHandle(long surfaceHandle);
-
- /**
- * The surface's size has been determined or changed.
- * Implementation shall update the stored surface size with the given ones.
- */
- public void surfaceSizeChanged(int width, int height);
-
-}
-
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
index 4877d5c4f..4f68c6945 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
@@ -34,8 +34,8 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
- private Object surfaceUpdatedListenersLock = new Object();
- private ArrayList+ * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived + * from it at {@link #lockSurface()}. + *
+ */ + @Override + public final void setSurfaceHandle(long surfaceHandle) { + this.windowHandle = surfaceHandle; + } + + /** + * Sets the window handle (HWND). + */ + public final void setWindowHandle(long windowHandle) { + this.windowHandle = windowHandle; + } + + public final long getWindowHandle() { + return windowHandle; } @Override final protected int lockSurfaceImpl() { + if (0 == windowHandle) { + throw new NativeWindowException("null window handle: "+this); + } if (0 != surfaceHandle) { throw new InternalError("surface not released"); } @@ -89,12 +117,15 @@ public class GDISurface extends ProxySurface { @Override final public String toString() { - return "GDISurface[config "+getPrivateGraphicsConfiguration()+ + final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); + final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; + return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+ ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+ ", windowHandle 0x"+Long.toHexString(windowHandle)+ ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+ ", size "+getWidth()+"x"+getHeight()+ - ", surfaceLock "+surfaceLock+"]"; + ", surfaceLock "+surfaceLock+ + ", upstreamSurfaceHook "+ush_s+"]"; } } diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index e010fc440..ebfefe345 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -148,37 +148,6 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS return res; } -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: CreateNSView0 - * Signature: (IIIIZ)J - */ -JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSView0 - (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSRect rect = NSMakeRect(x, y, width, height); - NSView * view = [[NSView alloc] initWithFrame: rect] ; - [view setCanDrawConcurrently: YES]; - [pool release]; - - return (jlong) (intptr_t) view; -} - -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: DestroyNSView0 - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSView0 - (JNIEnv *env, jclass unused, jlong nsView) -{ - NSView* view = (NSView*) (intptr_t) nsView; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [view release]; - [pool release]; -} - /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateNSWindow0 @@ -222,6 +191,27 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSWindow0 [pool release]; } +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: GetNSView0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0 + (JNIEnv *env, jclass unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + + DBG_PRINT( "contentView0 - window: %p (START)\n", win); + + jlong res = (jlong) ((intptr_t) [win contentView]); + + DBG_PRINT( "contentView0 - window: %p (END)\n", win); + + [pool release]; + return res; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateCALayer0 diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 71e86d520..e8537fec5 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -40,8 +40,20 @@ import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.WindowClosingProtocol; /** - * Specifying the public Window functionality for the - * using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}. + * Specifying NEWT's Window functionality: + *+ * One use case is {@link com.jogamp.newt.opengl.GLWindow}, which delegates + * window operation to an instance of this interface while providing OpenGL + * functionality. + *
*/ public interface Window extends NativeWindow, WindowClosingProtocol { public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent"); diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java index 44fcea49c..4db661eeb 100644 --- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java @@ -43,7 +43,7 @@ public class KeyEvent extends InputEvent this.keyChar=keyChar; } - /** Only valid if delivered via {@link KeyListener#keyPressed(KeyEvent)} */ + /** Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)} */ public char getKeyChar() { return keyChar; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index f08fbc8fa..c50ab77c4 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -124,6 +124,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind this.window.setLifecycleHook(new GLLifecycleHook()); } + @Override + public final Object getUpstreamWidget() { + return window; + } + /** * Creates a new GLWindow attaching a new Window referencing a * new default Screen and default Display with the given GLCapabilities. @@ -762,7 +767,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind System.err.println(GlueGenVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString()); + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString()); final GLProfile glp = GLProfile.getDefault(); final GLCapabilitiesImmutable caps = new GLCapabilities( glp ); diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index 050e24b6c..be543aba9 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -34,15 +34,24 @@ package jogamp.newt; -import javax.media.nativewindow.*; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; -public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { +public class OffscreenWindow extends WindowImpl implements MutableSurface { long surfaceHandle = 0; - + ProxySurface.UpstreamSurfaceHook upstreamHook; + ProxySurface dummySurface; + public OffscreenWindow() { + upstreamHook = null; + dummySurface = null; } static long nextWindowHandle = 0x100; // start here - a marker @@ -52,6 +61,17 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { throw new NativeWindowException("Capabilities is onscreen"); } final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + /** Cannot use OpenGL here .. + if(capsRequested instanceof GLCapabilitiesImmutable) { + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) capsRequested; + if(caps.isFBO() && GLContext.isFBOAvailable(aScreen.getDevice(), caps.getGLProfile()) ) { + final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(caps); + final ProxySurface dummySurface = factory.createDummySurfaceImpl(aScreen.getDevice(), false, dummyCaps, null, 64, 64); + upstreamHook = dummySurface.getUpstreamSurfaceHook(); + dummySurface.createNotify(); + } + } */ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, aScreen); if (null == cfg) { @@ -68,13 +88,14 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { // nop } - public void surfaceSizeChanged(int width, int height) { - sizeChanged(false, width, height, false); - } - @Override public synchronized void destroy() { super.destroy(); + if(null != dummySurface) { + dummySurface.destroyNotify(); + dummySurface = null; + upstreamHook = null; + } surfaceHandle = 0; } @@ -84,8 +105,12 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { @Override public long getSurfaceHandle() { + if(null != dummySurface) { + return dummySurface.getSurfaceHandle(); + // return upstreamHook.getWidth(); + } return surfaceHandle; - } + } protected void requestFocusImpl(boolean reparented) { } diff --git a/src/newt/classes/jogamp/newt/driver/android/MD.java b/src/newt/classes/jogamp/newt/driver/android/MD.java index 403eae383..f2f30937b 100644 --- a/src/newt/classes/jogamp/newt/driver/android/MD.java +++ b/src/newt/classes/jogamp/newt/driver/android/MD.java @@ -43,7 +43,7 @@ public class MD { .append(JoglVersion.getInstance()).append(Platform.NEWLINE) .append(Platform.NEWLINE); - JoglVersion.getDefaultOpenGLInfo(sb, true); + JoglVersion.getDefaultOpenGLInfo(null, sb, true); return sb.toString(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 942994c13..fcca5c843 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -38,7 +38,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; @@ -50,7 +50,7 @@ import jogamp.newt.driver.DriverUpdatePosition; import com.jogamp.newt.event.KeyEvent; -public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverClearFocus, DriverUpdatePosition { +public class MacWindow extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition { static { MacDisplay.initSingleton(); @@ -131,10 +131,6 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl } } - public void surfaceSizeChanged(int width, int height) { - sizeChanged(false, width, height, false); - } - @Override protected void setTitleImpl(final String title) { setTitle0(getWindowHandle(), title); diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index f914467af..b58b99e38 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -972,7 +972,7 @@ static jint mods2JavaMods(NSUInteger mods) NSView* nsview = [self contentView]; if( ! [nsview isMemberOfClass:[NewtView class]] ) { - return; + return NO; } NewtView* view = (NewtView *) nsview; @@ -981,14 +981,14 @@ static jint mods2JavaMods(NSUInteger mods) DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { DBG_PRINT("windowWillClose: null javaWindowObject\n"); - return; + return NO; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { DBG_PRINT("windowWillClose: null JNIEnv\n"); - return; + return NO; } [view setDestroyNotifySent: true]; // earmark assumption of being closed diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java index a09cc76ac..b22be0a93 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java @@ -194,7 +194,7 @@ public class TestTextRendererNEWT00 extends UITestCase { pw.printf("%s-%03dx%03d-T%04d", objName, drawable.getWidth(), drawable.getHeight(), texSize[0]); final String filename = dir + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index a3182a30f..6378c1ee3 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -194,7 +194,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize[0], objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java index d0093ad0c..15daf70cd 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java @@ -180,7 +180,7 @@ public abstract class UIListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), 0, objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java new file mode 100644 index 000000000..1a33845b3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java @@ -0,0 +1,272 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLFBODrawableImpl; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.OffscreenAutoDrawable; +import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +public class TestFBODrawableNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + @Test + public void testGL2ES2_Demo1Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(false)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoNormal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + boolean skipShot = false; + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); + Assert.assertNotNull(fboDrawable); + Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl); + + fboDrawable.setRealized(true); + Assert.assertTrue(fboDrawable.isRealized()); + + final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject(); + + System.out.println("Realized: "+fboDrawable); + System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities()); + System.out.println("Realized: "+fbo); + + final GLContext context = fboDrawable.createContext(null); + Assert.assertNotNull(context); + + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + System.out.println("Post Create-Ctx: "+fbo); + final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(colorA); + final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(depthA); + + final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, null); + + glad.addGLEventListener(demo); + glad.addGLEventListener(new GLEventListener() { + volatile int displayCount=0; + volatile int reshapeCount=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight()); + // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo); + // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO()); + // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer()); + if(skipShot) { + skipShot=false; + } else { + snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null); + } + Assert.assertEquals(drawable.getWidth(), widthStep*szStep); + Assert.assertEquals(drawable.getHeight(), heightStep*szStep); + displayCount++; + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); + Assert.assertEquals(drawable.getWidth(), widthStep*szStep); + Assert.assertEquals(drawable.getHeight(), heightStep*szStep); + reshapeCount++; + } + }); + + // 0 - szStep = 2 + glad.display(); + + // 1, 2 (resize + display) + szStep = 1; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + { + // Check whether the attachment reference are still valid! + FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + Assert.assertTrue(colorA.equals(_colorA)); + FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(_depthA); + Assert.assertTrue(depthA == _depthA); + Assert.assertTrue(depthA.equals(_depthA)); + + _colorA = fbo.getColorbuffer(colorA); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + Assert.assertTrue(colorA.equals(_colorA)); + } + + // 3, 4 (resize + display) + szStep = 4; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + { + // Check whether the attachment reference are still valid! + FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(_depthA); + Assert.assertTrue(depthA == _depthA); + + _colorA = fbo.getColorbuffer(colorA); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + } + + // 5 + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + + // 6, 7 (resize + display) + szStep = 3; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + + glad.destroy(); + System.out.println("Fin: "+fboDrawable); + + // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java new file mode 100644 index 000000000..f7c83a03b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -0,0 +1,266 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NEWTGLContext; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.io.IOException; + +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLUniformData; + +import org.junit.Assert; +import org.junit.Test; + +public class TestFBOMRTNEWT01 extends UITestCase { + static long durationPerTest = 10*40*2; // ms + + @Test + public void test01() throws InterruptedException { + final int step = 4; + final int width = 800; + final int height = 600; + // preset .. + if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { + System.err.println("Test requires GL2/GL3 profile."); + return; + } + final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( + new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true); + final GLDrawable drawable = winctx.context.getGLDrawable(); + GL2GL3 gl = winctx.context.getGL().getGL2GL3(); + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3(); + System.err.println(winctx.context); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + // test code .. + final ShaderState st = new ShaderState(); + // st.setVerbose(true); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-1", false); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-1", false); + final ShaderProgram sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + Assert.assertTrue(0<=sp0.program()); + Assert.assertTrue(!sp0.inUse()); + Assert.assertTrue(!sp0.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.attachShaderProgram(gl, sp0, false); + + final ShaderCode vp1 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-2", false); + final ShaderCode fp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-2", false); + final ShaderProgram sp1 = new ShaderProgram(); + sp1.add(gl, vp1, System.err); + sp1.add(gl, fp1, System.err); + Assert.assertTrue(0<=sp1.program()); + Assert.assertTrue(!sp1.inUse()); + Assert.assertTrue(!sp1.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.attachShaderProgram(gl, sp1, true); + + final PMVMatrix pmvMatrix = new PMVMatrix(); + final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 0, vertices0); + vertices0.putf(0); vertices0.putf(1); vertices0.putf(0); + vertices0.putf(1); vertices0.putf(1); vertices0.putf(0); + vertices0.putf(0); vertices0.putf(0); vertices0.putf(0); + vertices0.putf(1); vertices0.putf(0); vertices0.putf(0); + vertices0.seal(gl, true); + st.ownAttribute(vertices0, true); + vertices0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLArrayDataServer colors0 = GLArrayDataServer.createGLSL("gca_Colors", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 1, colors0); + colors0.putf(1); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(0); colors0.putf(1); + colors0.putf(0); colors0.putf(1); colors0.putf(1); colors0.putf(1); + colors0.seal(gl, true); + st.ownAttribute(colors0, true); + colors0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLUniformData texUnit0 = new GLUniformData("gcs_TexUnit0", 0); + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + final GLUniformData texUnit1 = new GLUniformData("gcs_TexUnit1", 1); + st.ownUniform(texUnit1); + st.uniform(gl, texUnit1); + + final GLArrayDataServer texCoords0 = GLArrayDataServer.createGLSL("gca_TexCoords", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 2, texCoords0); + texCoords0.putf(0f); texCoords0.putf(1f); + texCoords0.putf(1f); texCoords0.putf(1f); + texCoords0.putf(0f); texCoords0.putf(0f); + texCoords0.putf(1f); texCoords0.putf(0f); + texCoords0.seal(gl, true); + st.ownAttribute(texCoords0, true); + texCoords0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final int texA0Point = 0; // attachment point for texA0 + final int texA1Point = 1; // attachment point for texA1 + + // FBO w/ 2 texture2D color buffers + final FBObject fbo_mrt = new FBObject(); + fbo_mrt.reset(gl, drawable.getWidth(), drawable.getHeight()); + final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + final TextureAttachment texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, 24); + Assert.assertTrue( fbo_mrt.isStatusValid() ) ; + fbo_mrt.unbind(gl); + + // misc GL setup + gl.glClearColor(1, 1, 1, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0+texA0Point, GL.GL_COLOR_ATTACHMENT0+texA1Point }; + final int[] bck_buffers = new int[] { GL2GL3.GL_BACK_LEFT }; + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + int step_i = 0; + int[] last_snap_size = new int[] { 0, 0 }; + + for(int i=0; i+ * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png + * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png + *+ * + * @param simpleTestName will be used as the filename prefix + * @param sn sequential number + * @param postSNDetail optional detail to be added to the filename after
sn
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename.
+ * @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot.
+ * @param fileSuffix Optional file suffix without a dot defining the file type, i.e. "png"
.
+ * If null
the "png"
as defined in {@link TextureIO#PNG} is being used.
+ * @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator.
+ * It shall not end with a directory separator, {@link File#separatorChar}.
+ * If null
the current working directory is being used.
+ */
+ public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
+ if(null == fileSuffix) {
+ fileSuffix = TextureIO.PNG;
+ }
+ final StringWriter filenameSW = new StringWriter();
+ {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_";
+ final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_";
+ final String aaext = caps.getSampleExtension();
+ final int samples = caps.getNumSamples() ;
+ postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
+ final PrintWriter pw = new PrintWriter(filenameSW);
+ pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s",
+ simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(),
+ drawable.getWidth(), drawable.getHeight(), fileSuffix);
+ }
+ final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString();
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename);
+ gl.glFinish(); // just make sure rendering finished ..
+ if(readBufferUtil.readPixels(gl, false)) {
+ readBufferUtil.write(new File(filename));
+ }
+ }
}
--
cgit v1.2.3
From fb7d2d8a188fe5da159571cfabfd1d6a8879d1da Mon Sep 17 00:00:00 2001
From: Sven Gothel Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.
+ * */ public class GLCanvas extends Canvas implements GLAutoDrawable { + private static final boolean DEBUG = Debug.debug("GLCanvas"); /* * Flag for whether the SWT thread should be used for OpenGL calls when in single-threaded mode. This is controlled @@ -87,18 +92,20 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* GL Stuff */ private final RecursiveLock lock = LockFactory.createRecursiveLock(); private final GLDrawableHelper helper = new GLDrawableHelper(); + + private final GLContext shareWith; + private final GLCapabilitiesImmutable capsRequested; + private final GLCapabilitiesChooser capsChooser; + private volatile GLDrawable drawable; // volatile: avoid locking for read-only access private GLContext context; /* Native window surface */ private AbstractGraphicsDevice device; - private final long nativeWindowHandle; - private final ProxySurface proxySurface; /* Construction parameters stored for GLAutoDrawable accessor methods */ private int additionalCtxCreationFlags = 0; - private final GLCapabilitiesImmutable glCapsRequested; /* Flag indicating whether an unprocessed reshape is pending. */ private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking @@ -218,6 +225,37 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { */ private volatile Rectangle clientArea; + /** + * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)} + * on the SWT thread. + * + * @param parent + * Required (non-null) parent Composite. + * @param style + * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the + * Canvas constructor, so OpenGL handles the background. + * @param caps + * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the + * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are + * actually used may differ based on the capabilities of the graphics device. + * @param chooser + * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the + * requested GLCapabilities, and the available capabilities of the graphics device. + * @param shareWith + * Optional GLContext to share state (textures, vbos, shaders, etc.) with. + * @return a new instance + */ + public static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps, + final GLCapabilitiesChooser chooser, final GLContext shareWith) { + final GLCanvas[] res = new GLCanvas[] { null }; + parent.getDisplay().syncExec(new Runnable() { + public void run() { + res[0] = new GLCanvas( parent, style, caps, chooser, shareWith ); + } + }); + return res[0]; + } + /** * Creates a new SWT GLCanvas. * @@ -250,35 +288,26 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */ device = SWTAccessor.getDevice(this); - /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */ - final int screenIdx = 0; - /* Native handle for the control, used to associate with GLContext */ - nativeWindowHandle = SWTAccessor.getWindowHandle(this); /* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */ if(null == caps) { caps = new GLCapabilities(GLProfile.getDefault(device)); } - glCapsRequested = caps; - - final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); - - /* Create a NativeWindow proxy for the SWT canvas */ - proxySurface = glFactory.createProxySurface(device, screenIdx, nativeWindowHandle, caps, chooser, swtCanvasUpStreamHook); - - /* Associate a GL surface with the proxy */ - drawable = glFactory.createGLDrawable(proxySurface); - drawable.setRealized(true); - - context = drawable.createContext(shareWith); - + this.capsRequested = caps; + this.capsChooser = chooser; + this.shareWith = shareWith; + + // post create .. when ready + drawable = null; + context = null; + /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */ /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */ addPaintListener(new PaintListener() { @Override public void paintControl(final PaintEvent arg0) { - if (!helper.isExternalAnimatorAnimating()) { - display(); + if ( !helper.isExternalAnimatorAnimating() ) { + display(); // checks: null != drawable } } }); @@ -291,39 +320,93 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { }); } private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() { - @Override - public final void create(ProxySurface s) { /* nop */ } - - @Override - public final void destroy(ProxySurface s) { /* nop */ } - - @Override - public final int getWidth(ProxySurface s) { - return clientArea.width; - } - - @Override - public final int getHeight(ProxySurface s) { - return clientArea.height; - } - - @Override - public String toString() { - return "SETUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+"]"; - } - + @Override + public final void create(ProxySurface s) { /* nop */ } + + @Override + public final void destroy(ProxySurface s) { /* nop */ } + + @Override + public final int getWidth(ProxySurface s) { + return clientArea.width; + } + + @Override + public final int getHeight(ProxySurface s) { + return clientArea.height; + } + + @Override + public String toString() { + return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]"; + } }; protected final void updateSizeCheck() { - clientArea = GLCanvas.this.getClientArea(); - if (clientArea != null && - proxySurface.getWidth() != clientArea.width && - proxySurface.getHeight() != clientArea.height) { + final Rectangle oClientArea = clientArea; + final Rectangle nClientArea = GLCanvas.this.getClientArea(); + if ( nClientArea != null && + ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) + ) { + clientArea = nClientArea; // write back new value sendReshape = true; // Mark for OpenGL reshape next time the control is painted } - sendReshape = false; + } + + @Override + public void display() { + if( null != drawable || validateDrawableAndContext() ) { + runInGLThread(makeCurrentAndDisplayOnEDTAction); + } } + + /** assumes drawable == null ! */ + protected final boolean validateDrawableAndContext() { + if( GLCanvas.this.isDisposed() ) { + return false; + } + final Rectangle nClientArea = clientArea; + if(0 == nClientArea.width * nClientArea.height) { + return false; + } + + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile()); + + /* Native handle for the control, used to associate with GLContext */ + final long nativeWindowHandle = SWTAccessor.getWindowHandle(this); + + /* Create a NativeWindow proxy for the SWT canvas */ + ProxySurface proxySurface = null; + try { + proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle, + capsRequested, capsChooser, swtCanvasUpStreamHook); + } catch (GLException gle) { + // not ready yet .. + if(DEBUG) { System.err.println(gle.getMessage()); } + } + + if(null != proxySurface) { + /* Associate a GL surface with the proxy */ + drawable = glFactory.createGLDrawable(proxySurface); + drawable.setRealized(true); + + context = drawable.createContext(shareWith); + } + } finally { + _lock.unlock(); + } + final boolean res = null != drawable; + if(DEBUG && res) { + System.err.println("SWT GLCanvas realized! "+this+", "+drawable); + Thread.dumpStack(); + } + return res; + } + @Override public final Object getUpstreamWidget() { return this; @@ -362,11 +445,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { dispose(); } - @Override - public void display() { - runInGLThread(makeCurrentAndDisplayOnEDTAction); - } - @Override public GLAnimatorControl getAnimator() { return helper.getAnimator(); @@ -379,7 +457,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLContext getContext() { - return context; + return null != drawable ? context : null; } @Override @@ -472,7 +550,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLCapabilitiesImmutable getChosenGLCapabilities() { - return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getChosenCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getChosenGLCapabilities() : null; } /** @@ -481,7 +560,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { * @return Non-null GLCapabilities. */ public GLCapabilitiesImmutable getRequestedGLCapabilities() { - return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getRequestedCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities() : null; } @Override @@ -492,7 +572,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLProfile getGLProfile() { - return glCapsRequested.getGLProfile(); + return capsRequested.getGLProfile(); } @Override @@ -523,10 +603,9 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { runInGLThread(makeCurrentAndSwapBuffersOnEDTAction); } - // FIXME: API of update() method ? @Override public void update() { - // FIXME: display(); ? + // don't paint background etc .. nop avoids flickering } @Override @@ -551,7 +630,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { * @see Platform#AWT_AVAILABLE * @see Platform#getOSType() */ - private void runInGLThread(final Runnable action) { + private static void runInGLThread(final Runnable action) { if(Platform.OSType.MACOS == Platform.OS_TYPE) { SWTAccessor.invoke(true, action); } else { diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index e730bc62e..bf6a0ee6e 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -338,7 +338,6 @@ public abstract class GLContextImpl extends GLContext { if (TRACE_SWITCH) { System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) + ", isShared "+GLContextShareSet.isShared(this)+" - "+lock); - Thread.dumpStack(); // JAU } } } finally { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index 0494bb408..ba07d97dc 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -34,16 +34,21 @@ import java.lang.reflect.Method; import org.eclipse.swt.graphics.GCData; import org.eclipse.swt.widgets.Control; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.VisualIDHolder; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsScreen; import jogamp.nativewindow.macosx.OSXUtil; +import jogamp.nativewindow.x11.X11Lib; public class SWTAccessor { static final Field swt_control_handle; @@ -213,6 +218,26 @@ public class SWTAccessor { } throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); } + public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) { + if( null != OS_gtk_class ) { + return new X11GraphicsScreen((X11GraphicsDevice)device, screen); + } + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) || + NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { + return new DefaultGraphicsScreen(device, screen); + } + throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); + } + public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) { + if( null != OS_gtk_class ) { + return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle); + } + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) || + NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { + return VisualIDHolder.VID_UNDEFINED; + } + throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); + } public static long getWindowHandle(Control swtControl) { long handle = getHandle(swtControl); diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index b85ad47f2..6faa9890c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -561,4 +561,21 @@ public abstract class NativeWindowFactory { } return null; } + + /** + * Returns true if the given visualID is valid for further processing, i.e. OpenGL usage, + * otherwise return false. + *+ * On certain platforms, i.e. X11, a valid visualID is required at window creation. + * Other platforms may determine it later on, e.g. OSX and Windows.
+ *+ * If the visualID is {@link VisualIDHolder#VID_UNDEFINED} and the platform requires it + * at creation time (see above), it is not valid for further processing. + *
+ */ + public static boolean isNativeVisualIDValidForProcessing(int visualID) { + return NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(false) || + VisualIDHolder.VID_UNDEFINED != visualID ; + } + } diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 4767dff18..894084fce 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -28,6 +28,7 @@ package jogamp.nativewindow.macosx; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import jogamp.nativewindow.Debug; @@ -63,8 +64,37 @@ public class OSXUtil { return isNSView0(object); } - public static Point GetLocationOnScreen(long windowOrView, int src_x, int src_y) { - return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + /** + * In case thewindowOrView
is top-level,
+ * you shall set topLevel
to true where
+ * insets gets into account to compute the client position as follows:
+ * + if(topLevel) { + // top-level position -> client window position + final Insets insets = GetInsets(windowOrView); + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + } + *+ * @param windowOrView + * @param topLevel + * @param src_x + * @param src_y + * @return the client position + */ + public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) { + final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + if(topLevel) { + // top-level position -> client window position + final Insets insets = GetInsets(windowOrView); + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + } + return los; + } + + public static Insets GetInsets(long windowOrView) { + return (Insets) GetInsets0(windowOrView); } public static long CreateNSWindow(int x, int y, int width, int height) { @@ -135,6 +165,7 @@ public class OSXUtil { private static native boolean initIDs0(); private static native boolean isNSView0(long object); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); + private static native Object GetInsets0(long windowOrView); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); private static native long GetNSView0(long nsWindow); diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 37fa4c88f..2c853a43d 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -52,12 +52,18 @@ static const char * const ClazzNameRunnable = "java/lang/Runnable"; static jmethodID runnableRunID = NULL; -static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; static const char * const ClazzAnyCstrName = "
+ * If newEDTUtil
is null
,
+ * the device's default EDTUtil is created and used.
+ *
+ * If a previous one exists and it differs from the new one, + * it's being stopped, wait-until-idle and reset to allow restart. + *
+ *
+ * If newEDTUtil
is not null and equals the previous one,
+ * null
is returned and no change is being made.
+ *
+ * A previously detached newChild
will be released to top-level status
+ * and made invisible.
+ *
+ * Note: When switching NEWT child's, detaching the previous first via setNEWTChild(null)
+ * produced much cleaner visual results.
+ *
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *
+ * + * @param parent the SWT composite + * @param style additional styles to SWT#NO_BACKGROUND + * @param child optional preassigned {@link #Window}, maybe null + * @return a new instance + */ + public static NewtCanvasSWT create(final Composite parent, final int style, final Window child) { + final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null }; + parent.getDisplay().syncExec( new Runnable() { + public void run() { + res[0] = new NewtCanvasSWT( parent, style, child); + } + }); + return res[0]; + } + + /** + * Instantiates a NewtCanvas with a NEWT child. + * + *+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *
+ * + * @param parent the SWT composite + * @param style additional styles to SWT#NO_BACKGROUND + * @param child optional preassigned {@link #Window}, maybe null + */ + public NewtCanvasSWT(final Composite parent, final int style, Window child) { + super(parent, style | SWT.NO_BACKGROUND); + + swtEDTUtil = new SWTEDTUtil(parent.getDisplay()); + + SWTAccessor.setRealized(this, true); + + clientArea = getClientArea(); + + final AbstractGraphicsDevice device = SWTAccessor.getDevice(this); + screen = SWTAccessor.getScreen(device, 0); + nativeWindow = null; + + if(null != child) { + setNEWTChild(child); + } + + /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */ + /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */ + addPaintListener(new PaintListener() { + @Override + public void paintControl(final PaintEvent arg0) { + if( null != nativeWindow || validateNative() ) { + if( null !=newtChild ) { + newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height); + } + } + } + }); + + addControlListener(new ControlAdapter() { + @Override + public void controlResized(final ControlEvent arg0) { + updateSizeCheck(); + } + }); + } + + /** assumes nativeWindow == null ! */ + protected final boolean validateNative() { + if( isDisposed() ) { + return false; + } + updateSizeCheck(); + final Rectangle nClientArea = clientArea; + if(0 == nClientArea.width * nClientArea.height) { + return false; + } + + /* Native handle for the control, used to associate with GLContext */ + final long nativeWindowHandle = SWTAccessor.getWindowHandle(this); + final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle); + final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID); + if(DEBUG) { + System.err.println("NewtCanvasSWT.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid); + } + if( visualIDValid ) { + /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). + * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */ + final CapabilitiesImmutable caps = new Capabilities(); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps); + final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID ); + if(DEBUG) { + System.err.println("NewtCanvasSWT.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config); + // Thread.dumpStack(); + } + if (null == config) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + + nativeWindow = new SWTNativeWindow(config, nativeWindowHandle); + reparentWindow( true ); + } + + return null != nativeWindow; + } + + protected final void updateSizeCheck() { + final Rectangle oClientArea = clientArea; + final Rectangle nClientArea = getClientArea(); + if ( nClientArea != null && + ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) + ) { + clientArea = nClientArea; // write back new value + if( null != newtChild ) { + newtChild.setSize(clientArea.width, clientArea.height); + } + } + } + + @Override + public void update() { + // don't paint background etc .. nop avoids flickering + } + + /** + * Destroys this resource: + *destroy()
on the NEWT Child
+ * A previously detached newChild
will be released to top-level status
+ * and made invisible.
+ *
+ * Note: When switching NEWT child's, detaching the previous first via setNEWTChild(null)
+ * produced much cleaner visual results.
+ *
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *
+ * @return the previous attached newt child. + */ + public Window setNEWTChild(final Window newChild) { + final Window prevChild = newtChild; + if(DEBUG) { + System.err.println("NewtCanvasSWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild)); + } + // remove old one + if(null != newtChild) { + reparentWindow( false ); + newtChild = null; + } + // add new one, reparent only if ready + newtChild = newChild; + if(null != nativeWindow && null != newChild) { + reparentWindow( true ); + } + return prevChild; + } + + /** @return the current NEWT child */ + public Window getNEWTChild() { + return newtChild; + } + + @Override + public boolean setParent(Composite parent) { + return super.setParent(parent); + } + + /* package */ void configureNewtChild(boolean attach) { + + if( null != newtChild ) { + newtChild.setKeyboardFocusHandler(null); + if(attach) { + newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); + } else { + newtChild.setFocusAction(null); + newtChild.setDefaultCloseOperation(newtChildCloseOp); + } + } + } + + void reparentWindow(boolean add) { + if( null == newtChild ) { + return; // nop + } + if(DEBUG) { + System.err.println("NewtCanvasSWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + + newtChild.setFocusAction(null); // no AWT focus traversal .. + if(add) { + updateSizeCheck(); + final int w = clientArea.width; + final int h = clientArea.height; + + newtChild.getScreen().getDisplay().setEDTUtil(swtEDTUtil); + + newtChild.setSize(w, h); + newtChild.reparentWindow(nativeWindow); + newtChild.setVisible(true); + configureNewtChild(true); + newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + + // force this SWT Canvas to be focus-able, + // since this it is completely covered by the newtChild (z-order). + setEnabled(true); + } else { + configureNewtChild(false); + newtChild.setVisible(false); + newtChild.reparentWindow(null); + } + if(DEBUG) { + System.err.println("NewtCanvasSWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + } + + private final void requestFocusNEWTChild() { + if( null != newtChild ) { + newtChild.setFocusAction(null); + newtChild.requestFocus(); + } + } + + @Override + public boolean forceFocus() { + final boolean res = NewtCanvasSWT.super.forceFocus(); + requestFocusNEWTChild(); + return res; + } + + private class SWTNativeWindow implements NativeWindow { + private final AbstractGraphicsConfiguration config; + private final long nativeWindowHandle; + private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX + + public SWTNativeWindow(AbstractGraphicsConfiguration config, long nativeWindowHandle) { + this.config = config; + this.nativeWindowHandle = nativeWindowHandle; + if(isOSX) { + this.insets = OSXUtil.GetInsets(nativeWindowHandle); + } else { + this.insets = new Insets(0, 0, 0, 0); + } + } + + @Override + public int lockSurface() throws NativeWindowException, RuntimeException { + return NativeSurface.LOCK_SUCCESS; + } + + @Override + public void unlockSurface() { } + + @Override + public boolean isSurfaceLockedByOtherThread() { + return false; + } + + @Override + public Thread getSurfaceLockOwner() { + return null; + } + + @Override + public boolean surfaceSwap() { + return false; + } + + @Override + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { } + + @Override + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + } + + @Override + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { } + + @Override + public long getSurfaceHandle() { + return 0; + } + + @Override + public int getWidth() { + return clientArea.width; + } + + @Override + public int getHeight() { + return clientArea.height; + } + + @Override + public AbstractGraphicsConfiguration getGraphicsConfiguration() { + return config; + } + + @Override + public long getDisplayHandle() { + return config.getScreen().getDevice().getHandle(); + } + + @Override + public int getScreenIndex() { + return config.getScreen().getIndex(); + } + + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { } + + @Override + public void destroy() { } + + @Override + public NativeWindow getParent() { + return null; + } + + @Override + public long getWindowHandle() { + return nativeWindowHandle; + } + + @Override + public InsetsImmutable getInsets() { + return insets; + } + + @Override + public int getX() { + return 0; + } + + @Override + public int getY() { + return 0; + } + + @Override + public Point getLocationOnScreen(Point point) { + if( isOSX ) { + final Point los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0); + // top-level position -> client window position + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + if(null!=point) { + return point.translate(los); + } else { + return los; + } + } else { + // client position on 'normal' windowing systems is 0/0 + if(null == point) { + point = new Point(0, 0); + } + return point; + } + } + + @Override + public boolean hasFocus() { + return isFocusControl(); + } + }; + + static String newtWinHandleToHexString(Window w) { + return null != w ? toHexString(w.getWindowHandle()) : "nil"; + } + static String toHexString(long l) { + return "0x"+Long.toHexString(l); + } +} + diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java new file mode 100644 index 000000000..3538caad2 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java @@ -0,0 +1,99 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.newt.swt; + +import org.eclipse.swt.widgets.Display; + +import com.jogamp.newt.util.EDTUtil; + +/** + * Simple {@link EDTUtil} implementation utilizing the SWT UI thread + * of the given {@link Display}. + */ +public class SWTEDTUtil implements EDTUtil { + private final Display swtDisplay; + + public SWTEDTUtil(Display swtDisplay) { + this.swtDisplay = swtDisplay; + } + + public final Display getDisplay() { + return swtDisplay; + } + + @Override + public long getPollPeriod() { + return 0; + } + + @Override + public void setPollPeriod(long ms) { + } + + @Override + public void reset() { + } + + @Override + public void start() { + } + + @Override + public boolean isCurrentThreadEDT() { + return swtDisplay.getThread() == Thread.currentThread(); + } + + @Override + public boolean isRunning() { + return true; + } + + @Override + public void invokeStop(Runnable finalTask) { + swtDisplay.syncExec(finalTask); + } + + @Override + public void invoke(boolean wait, Runnable task) { + if(wait) { + swtDisplay.syncExec(task); + } else { + swtDisplay.asyncExec(task); + } + } + + @Override + public void waitUntilIdle() { + // all sync .. + } + + @Override + public void waitUntilStopped() { + // all sync .. + } +} diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index b10561c5b..b178bb5d3 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -101,7 +101,9 @@ public abstract class DisplayImpl extends Display { display.hashCode = display.fqname.hashCode(); displayList.add(display); } - display.createEDTUtil(); + if(null == display.edtUtil) { + display.setEDTUtil(null); // device's default if EDT is used, or null + } if(DEBUG) { System.err.println("Display.create() NEW: "+display+" "+getThreadName()); } @@ -168,15 +170,45 @@ public abstract class DisplayImpl extends Display { return true; } - protected void createEDTUtil() { + protected EDTUtil createEDTUtil() { + final EDTUtil def; if(NewtFactory.useEDT()) { - edtUtil = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable); + def = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable); if(DEBUG) { - System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); + System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); } + } else { + def = null; } + return def; } + @Override + public EDTUtil setEDTUtil(EDTUtil newEDTUtil) { + if(null == newEDTUtil) { + newEDTUtil = createEDTUtil(); + } + if( newEDTUtil == edtUtil ) { + if(DEBUG) { + System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!"); + } + return null; // no change + } + final EDTUtil oldEDTUtil = edtUtil; + if(DEBUG) { + System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil); + } + if(null != oldEDTUtil) { + stopEDT( new Runnable() { public void run() {} } ); + // ready for restart .. + oldEDTUtil.waitUntilStopped(); + oldEDTUtil.reset(); + } + edtUtil = newEDTUtil; + return oldEDTUtil; + } + + @Override public final EDTUtil getEDTUtil() { return edtUtil; } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index b12e42680..606101ade 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -445,9 +445,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected abstract void closeNativeImpl(); /** - * The native implementation must invoke {@link #focusChanged(boolean, boolean)} - * to change the focus state, ifforce == false
.
- * This may happen asynchronous within {@link #TIMEOUT_NATIVEWINDOW}.
+ * Async request which shall be performed within {@link #TIMEOUT_NATIVEWINDOW}.
+ *
+ * If if force == false
the native implementation
+ * may only request focus if not yet owner.
+ * {@link #focusChanged(boolean, boolean)} should be called + * to notify about the focus traversal. + *
* * @param force if true, bypass {@link #focusChanged(boolean, boolean)} and force focus request */ diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java index ce8ed7c49..747e2368e 100644 --- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java +++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java @@ -34,6 +34,7 @@ import javax.media.nativewindow.NativeWindow; import jogamp.newt.driver.DriverUpdatePosition; +import com.jogamp.newt.Window; import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTWindowAdapter; @@ -92,19 +93,20 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.err.println("AWT: componentResized: "+comp); } - getNewtWindow().runOnEDTIfAvail(false, new Runnable() { + final Window newtWindow = getNewtWindow(); + newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { int cw = comp.getWidth(); int ch = comp.getHeight(); if( 0 < cw * ch ) { - if( getNewtWindow().getWidth() != cw || getNewtWindow().getHeight() != ch ) { - getNewtWindow().setSize(cw, ch); - if(comp.isVisible() != getNewtWindow().isVisible()) { - getNewtWindow().setVisible(comp.isVisible()); + if( newtWindow.getWidth() != cw || newtWindow.getHeight() != ch ) { + newtWindow.setSize(cw, ch); + if(comp.isVisible() != newtWindow.isVisible()) { + newtWindow.setVisible(comp.isVisible()); } } - } else if(getNewtWindow().isVisible()) { - getNewtWindow().setVisible(false); + } else if(newtWindow.isVisible()) { + newtWindow.setVisible(false); } }}); } @@ -113,8 +115,9 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.err.println("AWT: componentMoved: "+e); } - if(getNewtWindow().getDelegatedWindow() instanceof DriverUpdatePosition) { - ((DriverUpdatePosition)getNewtWindow().getDelegatedWindow()).updatePosition(); + final Window newtWindow = getNewtWindow(); + if(newtWindow.getDelegatedWindow() instanceof DriverUpdatePosition) { + ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition(); } } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java index 166da5c1c..65f8b4715 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java @@ -36,6 +36,7 @@ package jogamp.newt.driver.awt; import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.util.EDTUtil; import jogamp.newt.DisplayImpl; @@ -54,13 +55,17 @@ public class AWTDisplay extends DisplayImpl { protected void closeNativeImpl() { } @Override - protected void createEDTUtil() { + protected EDTUtil createEDTUtil() { + final EDTUtil def; if(NewtFactory.useEDT()) { - edtUtil = AWTEDTUtil.getSingleton(); + def = AWTEDTUtil.getSingleton(); if(DEBUG) { - System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); + System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); } + } else { + def = null; } + return def; } protected void dispatchMessagesNative() { /* nop */ } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 720d4ee4c..27d7a1679 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -150,7 +150,7 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance); } if(!isOffscreenInstance) { - requestFocusParent0(getWindowHandle()); + resignFocus0(getWindowHandle()); } else { focusChanged(false, false); } @@ -360,7 +360,6 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear if(recreate && 0==surfaceHandle) { throw new NativeWindowException("Internal Error - recreate, window but no view"); } - orderOut0(getWindowHandle()); close0(getWindowHandle()); setWindowHandle(0); } else { @@ -397,7 +396,7 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear private native boolean lockSurface0(long window); private native void unlockSurface0(long window); private native void requestFocus0(long window, boolean force); - private native void requestFocusParent0(long window); + private native void resignFocus0(long window); /** in case of a child window, it actually only issues orderBack(..) */ private native void orderOut0(long window); private native void orderFront0(long window); diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java index 34d76a148..6a8c81f3d 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java @@ -151,8 +151,8 @@ public class WindowsWindow extends WindowImpl { } protected void closeNativeImpl() { - if (hdc != 0) { - if(windowHandleClose != 0) { + if(windowHandleClose != 0) { + if (hdc != 0) { try { GDI.ReleaseDC(windowHandleClose, hdc); } catch (Throwable t) { @@ -162,11 +162,8 @@ public class WindowsWindow extends WindowImpl { } } } - hdc = 0; - hdc_old = 0; - } - if(windowHandleClose != 0) { try { + GDI.SetParent(windowHandleClose, 0); // detach first, experience hang w/ SWT parent GDI.DestroyWindow(windowHandleClose); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { @@ -177,6 +174,8 @@ public class WindowsWindow extends WindowImpl { windowHandleClose = 0; } } + hdc = 0; + hdc_old = 0; } protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 01cbd80ec..bbadc9dd0 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -599,6 +599,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 } DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]); + // Remove animations for child windows + if(NULL != parentWindow) { +NS_DURING + // Available >= 10.7 - Removes default animations + [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; +NS_HANDLER +NS_ENDHANDLER + } + #ifdef VERBOSE_ON int dbgIdx = 1; #endif @@ -734,7 +743,7 @@ NS_ENDHANDLER if(NULL!=pWin) { [mWin detachFromParent: pWin]; } - [mWin orderOut: mWin]; + [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); @@ -742,11 +751,6 @@ NS_ENDHANDLER // Only release window, if release is not yet in process. // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked. if(!destroyNotifySent) { - // '[mWin close]' causes a crash at exit. - // This probably happens b/c it sends events to the main loop - // but our resources are gone ?! - // However, issuing a simple release seems to work quite well. - // [mWin release]; [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; } @@ -806,11 +810,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); [mWin makeFirstResponder: nil]; - [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderFrontRegardless]; - // [mWin makeKeyWindow]; + [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; + [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force); @@ -819,26 +820,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 /* * Class: jogamp_newt_driver_macosx_MacWindow - * Method: requestFocusParent0 + * Method: resignFocus0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_resignFocus0 (JNIEnv *env, jobject window, jlong w) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) w); NSWindow* pWin = [mWin parentWindow]; -#ifdef VERBOSE_ON BOOL hasFocus = [mWin isKeyWindow]; -#endif - DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); - if(NULL != pWin) { - [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [pWin makeKeyWindow]; + DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); + if( hasFocus ) { + if(NULL != pWin) { + // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO]; + [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; + } else { + [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO]; + } } - DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin); + DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin); [pool release]; } @@ -856,9 +858,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0 DBG_PRINT( "orderFront0 - window: %p (START)\n", win); - [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [win orderFrontRegardless]; + [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; DBG_PRINT( "orderFront0 - window: %p (END)\n", win); @@ -880,13 +880,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0 DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin); if(NULL == pWin) { - [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderOut: mWin]; + [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; } else { - [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderBack: mWin]; + [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO]; } DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java new file mode 100644 index 000000000..6a27e6f27 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java @@ -0,0 +1,233 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.swt; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.Test; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Tests that a basic SWT app can open without crashing under different GL profiles + * _and_ custom GLCapabilities. + *
+ * Uses JOGL's NewtCanvasSWT, which allows to be a native container of a NEWT Window.
+ * This method allows utilizing custom GLCapability settings,
+ * independent from the already instantiated SWT visual.
+ *
+ * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ + * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. + *
+ */ +public class TestNewtCanvasSWTGLn extends UITestCase { + + static int duration = 250; + + static final int iwidth = 640; + static final int iheight = 480; + + Display display = null; + Shell shell = null; + Composite composite = null; + + @BeforeClass + public static void startup() { + System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite = null; + } + + protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo, + boolean postAttach, boolean useAnimator ) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + + final GLWindow glWindow1 = GLWindow.create(caps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.addGLEventListener(demo); + glWindow1.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(final GLAutoDrawable drawable) { } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + public void display(final GLAutoDrawable drawable) { + if(displayCount < 3) { + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + public void dispose(final GLAutoDrawable drawable) { } + }); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, postAttach ? null : glWindow1 ); + Assert.assertNotNull( canvas1 ); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } + }); + + if(postAttach) { + canvas1.setNEWTChild(glWindow1); + } + + // canvas1.update(); + + Animator anim; + if(useAnimator) { + anim = new Animator(glWindow1); + anim.start(); + } else { + anim = null; + } + + long lStartTime = System.currentTimeMillis(); + long lEndTime = lStartTime + duration; + try { + while( (System.currentTimeMillis() < lEndTime) && !canvas1.isDisposed() ) { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + if(null != anim) { + anim.stop(); + } + + canvas1.dispose(); + } + + @Test + public void preAttach_WithAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, true /* animator */); + } + + @Test + public void preAttach_NoAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, false /* animator */); + } + + @Test + public void postAttach_WithAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), true /* postAttach */, true /* animator */); + } + + @Test + public void test_MultisampleAndAlpha() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + caps.setSampleBuffers(true); + caps.setNumSamples(2); + runTestAGL( caps, new MultisampleDemoES2(true), false /* postAttach */, false /* animator */); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) { + for(int i=0; i+ * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used. + *
+ ** Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. *
@@ -116,34 +121,32 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { composite = null; } - protected void runTestAGL( GLProfile glprofile ) throws InterruptedException { - // need SWT.NO_BACKGROUND to prevent SWT from clearing the window - // at the wrong times (we use glClear for this instead) - final GLCapabilitiesImmutable caps = new GLCapabilities( glprofile ); + protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo ) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - final GLCanvas canvas = new GLCanvas( composite, 0, caps, null, null); + final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null, null); Assert.assertNotNull( canvas ); + canvas.addGLEventListener( demo ); canvas.addGLEventListener(new GLEventListener() { - public void init(final GLAutoDrawable drawable) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - init()"); - } - public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - reshape()"); - OneTriangle.setup( drawable.getGL().getGL2(), width, height ); - } + int displayCount = 0; + public void init(final GLAutoDrawable drawable) { } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } public void display(final GLAutoDrawable drawable) { - OneTriangle.render( drawable.getGL().getGL2(), drawable.getWidth(), drawable.getHeight()); + if(displayCount < 3) { + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } } - public void dispose(final GLAutoDrawable drawable) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - dispose()"); - } - }); + public void dispose(final GLAutoDrawable drawable) { } + }); - shell.setText( getClass().getName() ); - shell.setSize( 640, 480 ); - shell.open(); - + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } } ); + long lStartTime = System.currentTimeMillis(); long lEndTime = lStartTime + duration; try { @@ -157,13 +160,15 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } - canvas.dispose(); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + canvas.dispose(); + } } ); } @Test public void test() throws InterruptedException { - GLProfile glprofile = GLProfile.getGL2ES1(); - runTestAGL( glprofile ); + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() ); } static int atoi(String a) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java new file mode 100644 index 000000000..11aef7c24 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java @@ -0,0 +1,210 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.newt.parenting; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Simple visibility test .. + */ +public class TestParenting01aSWT extends UITestCase { + static int width, height; + static long durationPerTest = 800; + static GLCapabilities glCaps; + + Display display = null; + Shell shell = null; + Composite composite1 = null; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite1 = new Composite( shell, SWT.NONE ); + composite1.setLayout( new FillLayout() ); + Assert.assertNotNull( composite1 ); + }}); + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite1 ); + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite1.dispose(); + shell.dispose(); + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite1 = null; + } + + @Test + public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + + GLWindow glWindow1 = GLWindow.create(glCaps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + GLEventListener demo1 = new RedSquareES2(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 ); + Assert.assertNotNull(canvas1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } + }); + + // visible test + Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent()); + + for(int i=0; i*10true
if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass false
. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ */
+ public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, boolean ownDevice) {
+ super(drawable, context, null, ownDevice);
}
/**
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
index 76959f3f4..67e81270d 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
@@ -28,6 +28,8 @@
package javax.media.opengl;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
@@ -57,12 +59,16 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase {
public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate");
/**
- * @param drawable
- * @param context
+ * @param drawable a valid {@link GLDrawable}, may not be realized yet.
+ * @param context a valid {@link GLContext}, may not be made current (created) yet.
* @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
+ * @param ownDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass false
. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
*/
- public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget) {
- super((GLDrawableImpl)drawable, (GLContextImpl)context);
+ public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) {
+ super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
this.upstreamWidget = null;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index fe6d0fd76..cc4e1b434 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -30,6 +30,8 @@ package jogamp.opengl;
import java.io.PrintStream;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
@@ -66,13 +68,23 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
protected GLContextImpl context;
+ protected final boolean ownDevice;
protected int additionalCtxCreationFlags = 0;
protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking
protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking
- public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context) {
+ /**
+ * @param drawable a valid {@link GLDrawableImpl}, may not be realized yet.
+ * @param context a valid {@link GLContextImpl}, may not be made current (created) yet.
+ * @param ownDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass false
. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ */
+ public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) {
this.drawable = drawable;
this.context = context;
+ this.ownDevice = ownDevice;
resetFPSCounter();
}
@@ -174,7 +186,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
/**
- * Calls {@link #destroyImplInLock()} while claiming the lock.
+ * Calls {@link #destroyImplInLock()} while claiming the lock.
*/
protected final void defaultDestroy() {
final RecursiveLock lock = getLock();
@@ -200,17 +212,22 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
protected void destroyImplInLock() {
final GLContext _context = context;
final GLDrawable _drawable = drawable;
- if( null != _drawable && _drawable.isRealized() ) {
- if( null != _context && _context.isCreated() ) {
- // Catch dispose GLExceptions by GLEventListener, just 'print' them
- // so we can continue with the destruction.
- try {
- helper.disposeGL(this, _drawable, _context, null);
- } catch (GLException gle) {
- gle.printStackTrace();
+ if( null != _drawable ) {
+ if( _drawable.isRealized() ) {
+ if( null != _context && _context.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ helper.disposeGL(this, _drawable, _context, null);
+ } catch (GLException gle) {
+ gle.printStackTrace();
+ }
}
+ _drawable.setRealized(false);
+ }
+ if( ownDevice ) {
+ _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close();
}
- _drawable.setRealized(false);
}
context = null;
drawable = null;
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index f092288fb..f7808294b 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -245,7 +245,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
if(null==drawable) {
throw new GLException("Could not create Pbuffer drawable for: "+device+", "+capsChosen+", "+width+"x"+height);
}
- return new GLPbufferImpl( drawable, shareWith);
+ return new GLPbufferImpl( drawable, shareWith, true);
}
//---------------------------------------------------------------------------
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index 6b64120fe..32f4cb696 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
@@ -58,8 +58,8 @@ import com.jogamp.common.util.locks.RecursiveLock;
public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
private int floatMode;
- public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext) {
- super(pbufferDrawable, null); // drawable := pbufferDrawable
+ public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext, boolean ownDevice) {
+ super(pbufferDrawable, null, ownDevice); // drawable := pbufferDrawable
GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)
drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities();
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index fcc374751..7b46a1df0 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -255,7 +255,7 @@ public class X11Util {
*/
public static int shutdown(boolean realXCloseOpenAndPendingDisplays, boolean verbose) {
int num=0;
- if(DEBUG||verbose||pendingDisplayList.size() > 0) {
+ if(DEBUG || verbose || openDisplayMap.size() > 0 || pendingDisplayList.size() > 0) {
System.err.println("X11Util.Display: Shutdown (close open / pending Displays: "+realXCloseOpenAndPendingDisplays+
", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
", pending (not closed, marked uncloseable): "+pendingDisplayList.size()+")");
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index d662a743a..0fc1b4e89 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -97,7 +97,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
* Constructor. Do not call this directly -- use {@link #create()} instead.
*/
protected GLWindow(Window window) {
- super(null, null);
+ super(null, null, false);
this.window = (WindowImpl) window;
this.window.setHandleDestroyNotify(false);
window.addWindowListener(new WindowAdapter() {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java
index 1a33845b3..7977347a7 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java
@@ -167,7 +167,7 @@ public class TestFBODrawableNEWT extends UITestCase {
final FBObject.RenderAttachment depthA = fbo.getDepthAttachment();
Assert.assertNotNull(depthA);
- final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, null);
+ final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, true);
glad.addGLEventListener(demo);
glad.addGLEventListener(new GLEventListener() {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
index 426b7734f..96d9b2e28 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
@@ -85,7 +85,7 @@ public class TestGLAutoDrawableDelegateNEWT extends UITestCase {
Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
context.release();
- final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window) {
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false) {
@Override
protected void destroyImplInLock() {
super.destroyImplInLock(); // destroys drawable/context
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
index 92b4c5238..cece4c6d5 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
@@ -88,7 +88,7 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
drawable.setRealized(true);
Assert.assertTrue(drawable.isRealized());
- final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window) {
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false) {
@Override
protected void destroyImplInLock() {
super.destroyImplInLock();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
index e14d5b800..33a9b7799 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
@@ -43,10 +43,10 @@ public class TestNEWTCloseX11DisplayBug565 {
if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
final int openD = X11Util.getOpenDisplayConnectionNumber() - open0;
- if(openD>1) {
+ if( openD > 0) {
X11Util.dumpOpenDisplayConnections();
X11Util.dumpPendingDisplayConnections();
- Assert.assertTrue("More than 1 new open display connections", false);
+ Assert.assertEquals("New display connection didn't close", 0, openD);
}
}
}
@@ -86,10 +86,10 @@ public class TestNEWTCloseX11DisplayBug565 {
if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
final int openD = X11Util.getOpenDisplayConnectionNumber() - open0;
- if(openD>1) {
+ if(openD > 0) {
X11Util.dumpOpenDisplayConnections();
X11Util.dumpPendingDisplayConnections();
- Assert.assertTrue("More than 1 new open display connections", false);
+ Assert.assertEquals("New display connection didn't close", 0, openD);
}
}
}
--
cgit v1.2.3
From 6e4051d8c9faeec003b15b68bd01e3caf22869fb Mon Sep 17 00:00:00 2001
From: Xerxes RÃ¥nby
*
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index 867a1f176..bac4031f0 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -44,7 +44,6 @@ import com.jogamp.newt.util.EDTUtil;
import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.NativeWindowFactory;
public abstract class DisplayImpl extends Display {
private static int serialno = 1;
@@ -52,26 +51,9 @@ public abstract class DisplayImpl extends Display {
private static Class> getDisplayClass(String type)
throws ClassNotFoundException
{
- Class> displayClass = NewtFactory.getCustomClass(type, "Display");
+ final Class> displayClass = NewtFactory.getCustomClass(type, "DisplayDriver");
if(null==displayClass) {
- if (NativeWindowFactory.TYPE_ANDROID == type) {
- displayClass = Class.forName("jogamp.newt.driver.android.AndroidDisplay");
- } else if (NativeWindowFactory.TYPE_EGL == type) {
- displayClass = Class.forName("jogamp.newt.driver.kd.Display");
- } else if (NativeWindowFactory.TYPE_WINDOWS == type) {
- displayClass = Class.forName("jogamp.newt.driver.windows.WindowsDisplay");
- } else if (NativeWindowFactory.TYPE_MACOSX == type) {
- displayClass = Class.forName("jogamp.newt.driver.macosx.MacDisplay");
- } else if (NativeWindowFactory.TYPE_X11 == type) {
- displayClass = Class.forName("jogamp.newt.driver.x11.X11Display");
- } else if (NativeWindowFactory.TYPE_AWT == type) {
- displayClass = Class.forName("jogamp.newt.driver.awt.AWTDisplay");
- } else {
- throw new RuntimeException("Unknown display type \"" + type + "\"");
- }
- }
- if(null==displayClass) {
- throw new ClassNotFoundException("Failed to find NEWT Display Class <"+type+".Display>");
+ throw new ClassNotFoundException("Failed to find NEWT Display Class <"+type+".DisplayDriver>");
}
return displayClass;
}
diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java
index 9f75a0d25..e2c0f746f 100644
--- a/src/newt/classes/jogamp/newt/ScreenImpl.java
+++ b/src/newt/classes/jogamp/newt/ScreenImpl.java
@@ -90,31 +90,13 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
});
}
- @SuppressWarnings("unchecked")
- private static Class extends Screen> getScreenClass(String type) throws ClassNotFoundException
+ private static Class> getScreenClass(String type) throws ClassNotFoundException
{
- Class> screenClass = NewtFactory.getCustomClass(type, "Screen");
+ final Class> screenClass = NewtFactory.getCustomClass(type, "ScreenDriver");
if(null==screenClass) {
- if (NativeWindowFactory.TYPE_ANDROID == type) {
- screenClass = Class.forName("jogamp.newt.driver.android.AndroidScreen");
- } else if (NativeWindowFactory.TYPE_EGL == type) {
- screenClass = Class.forName("jogamp.newt.driver.kd.Screen");
- } else if (NativeWindowFactory.TYPE_WINDOWS == type) {
- screenClass = Class.forName("jogamp.newt.driver.windows.WindowsScreen");
- } else if (NativeWindowFactory.TYPE_MACOSX == type) {
- screenClass = Class.forName("jogamp.newt.driver.macosx.MacScreen");
- } else if (NativeWindowFactory.TYPE_X11 == type) {
- screenClass = Class.forName("jogamp.newt.driver.x11.X11Screen");
- } else if (NativeWindowFactory.TYPE_AWT == type) {
- screenClass = Class.forName("jogamp.newt.driver.awt.AWTScreen");
- } else {
- throw new RuntimeException("Unknown window type \"" + type + "\"");
- }
- }
- if(null==screenClass) {
- throw new ClassNotFoundException("Failed to find NEWT Screen Class <"+type+".Screen>");
+ throw new ClassNotFoundException("Failed to find NEWT Screen Class <"+type+".ScreenDriver>");
}
- return (Class extends Screen>)screenClass;
+ return screenClass;
}
public static Screen create(Display display, int idx) {
@@ -133,7 +115,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
}
}
synchronized(screenList) {
- Class extends Screen> screenClass = getScreenClass(display.getType());
+ Class> screenClass = getScreenClass(display.getType());
ScreenImpl screen = (ScreenImpl) screenClass.newInstance();
screen.display = (DisplayImpl) display;
idx = screen.validateScreenIndex(idx);
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 2971fa07e..ad7195944 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -152,26 +152,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private static Class> getWindowClass(String type)
throws ClassNotFoundException
{
- Class> windowClass = NewtFactory.getCustomClass(type, "Window");
+ final Class> windowClass = NewtFactory.getCustomClass(type, "WindowDriver");
if(null==windowClass) {
- if (NativeWindowFactory.TYPE_ANDROID == type) {
- windowClass = Class.forName("jogamp.newt.driver.android.AndroidWindow");
- } else if (NativeWindowFactory.TYPE_EGL == type) {
- windowClass = Class.forName("jogamp.newt.driver.kd.Window");
- } else if (NativeWindowFactory.TYPE_WINDOWS == type) {
- windowClass = Class.forName("jogamp.newt.driver.windows.WindowsWindow");
- } else if (NativeWindowFactory.TYPE_MACOSX == type) {
- windowClass = Class.forName("jogamp.newt.driver.macosx.MacWindow");
- } else if (NativeWindowFactory.TYPE_X11 == type) {
- windowClass = Class.forName("jogamp.newt.driver.x11.X11Window");
- } else if (NativeWindowFactory.TYPE_AWT == type) {
- windowClass = Class.forName("jogamp.newt.driver.awt.AWTWindow");
- } else {
- throw new NativeWindowException("Unknown window type \"" + type + "\"");
- }
- }
- if(null==windowClass) {
- throw new ClassNotFoundException("Failed to find NEWT Window Class <"+type+".Window>");
+ throw new ClassNotFoundException("Failed to find NEWT Window Class <"+type+".WindowDriver>");
}
return windowClass;
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java b/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java
deleted file mode 100644
index 0a43c9b8f..000000000
--- a/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright 2011 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package jogamp.newt.driver.android;
-
-import jogamp.newt.*;
-import jogamp.opengl.egl.*;
-
-import javax.media.nativewindow.*;
-
-public class AndroidDisplay extends jogamp.newt.DisplayImpl {
- static {
- NEWTJNILibLoader.loadNEWT();
-
- if (!AndroidWindow.initIDs0()) {
- throw new NativeWindowException("Failed to initialize Android NEWT Windowing library");
- }
- }
-
- public static void initSingleton() {
- // just exist to ensure static init has been run
- }
-
-
- public AndroidDisplay() {
- }
-
- protected void createNativeImpl() {
- // EGL Device
- aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
- }
-
- protected void closeNativeImpl() {
- aDevice.close();
- }
-
- protected void dispatchMessagesNative() {
- // n/a .. DispatchMessages();
- }
-}
-
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java b/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java
deleted file mode 100644
index e108ed0bb..000000000
--- a/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Copyright 2011 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package jogamp.newt.driver.android;
-
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
-
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.util.DisplayMetrics;
-import android.view.Surface;
-import android.view.WindowManager;
-
-public class AndroidScreen extends jogamp.newt.ScreenImpl {
-
- static {
- AndroidDisplay.initSingleton();
- }
-
- public AndroidScreen() {
- }
-
- protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
- }
-
- protected void closeNativeImpl() { }
-
- protected ScreenMode getCurrentScreenModeImpl() {
- final Context ctx = jogamp.common.os.android.StaticContext.getContext();
- final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
- final DisplayMetrics outMetrics = new DisplayMetrics();
- final android.view.Display aDisplay = wmgr.getDefaultDisplay();
- aDisplay.getMetrics(outMetrics);
-
- final int arot = aDisplay.getRotation();
- final int nrot = androidRotation2NewtRotation(arot);
- int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
- int offset = 1; // set later for verification of iterator
- offset = getScreenSize(outMetrics, nrot, props, offset);
- offset = getBpp(aDisplay, props, offset);
- offset = getScreenSizeMM(outMetrics, props, offset);
- props[offset++] = (int) aDisplay.getRefreshRate();
- props[offset++] = nrot;
- props[offset - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = offset; // count
- return ScreenModeUtil.streamIn(props, 0);
- }
-
- protected int validateScreenIndex(int idx) {
- return 0; // FIXME: only one screen available ?
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- final ScreenMode sm = getCurrentScreenMode();
- virtualSize.setWidth(sm.getRotatedWidth());
- virtualSize.setHeight(sm.getRotatedHeight());
- }
-
- //----------------------------------------------------------------------
- // Internals only
- //
- static int androidRotation2NewtRotation(int arot) {
- switch(arot) {
- case Surface.ROTATION_270: return ScreenMode.ROTATE_270;
- case Surface.ROTATION_180: return ScreenMode.ROTATE_180;
- case Surface.ROTATION_90: return ScreenMode.ROTATE_90;
- case Surface.ROTATION_0:
- }
- return ScreenMode.ROTATE_0;
- }
- static int getScreenSize(DisplayMetrics outMetrics, int nrot, int[] props, int offset) {
- // swap width and height, since Android reflects rotated dimension, we don't
- if (ScreenMode.ROTATE_90 == nrot || ScreenMode.ROTATE_270 == nrot) {
- props[offset++] = outMetrics.heightPixels;
- props[offset++] = outMetrics.widthPixels;
- } else {
- props[offset++] = outMetrics.widthPixels;
- props[offset++] = outMetrics.heightPixels;
- }
- return offset;
- }
- static int getBpp(android.view.Display aDisplay, int[] props, int offset) {
- int bpp;
- switch(aDisplay.getPixelFormat()) {
- case PixelFormat.RGBA_8888: bpp=32; break;
- case PixelFormat.RGBX_8888: bpp=32; break;
- case PixelFormat.RGB_888: bpp=24; break;
- case PixelFormat.RGB_565: bpp=16; break;
- case PixelFormat.RGBA_5551: bpp=16; break;
- case PixelFormat.RGBA_4444: bpp=16; break;
- case PixelFormat.RGB_332: bpp= 8; break;
- default: bpp=32;
- }
- props[offset++] = bpp;
- return offset;
- }
- static int getScreenSizeMM(DisplayMetrics outMetrics, int[] props, int offset) {
- final float iw = (float) outMetrics.widthPixels / outMetrics.xdpi;
- final float ih = (float) outMetrics.heightPixels / outMetrics.xdpi;
- final float mmpi = 25.4f;
- props[offset++] = (int) ((iw * mmpi)+0.5);
- props[offset++] = (int) ((ih * mmpi)+0.5);
- return offset;
- }
-}
-
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java
deleted file mode 100644
index 73192a07f..000000000
--- a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/**
- * Copyright 2011 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package jogamp.newt.driver.android;
-
-import jogamp.common.os.android.StaticContext;
-import jogamp.newt.driver.android.event.AndroidNewtEventFactory;
-
-import javax.media.nativewindow.Capabilities;
-import javax.media.nativewindow.CapabilitiesImmutable;
-import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.VisualIDHolder;
-import javax.media.nativewindow.util.Insets;
-import javax.media.nativewindow.util.Point;
-import javax.media.opengl.GLCapabilitiesChooser;
-import javax.media.opengl.GLCapabilitiesImmutable;
-
-import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
-
-import jogamp.opengl.egl.EGL;
-import jogamp.opengl.egl.EGLGraphicsConfiguration;
-import jogamp.opengl.egl.EGLGraphicsConfigurationFactory;
-
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ResultReceiver;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceHolder.Callback2;
-import android.view.inputmethod.InputMethodManager;
-import android.view.SurfaceView;
-import android.view.View;
-
-public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 {
- static {
- AndroidDisplay.initSingleton();
- }
-
- public static CapabilitiesImmutable fixCaps(boolean matchFormatPrecise, int format, CapabilitiesImmutable rCaps) {
- PixelFormat pf = new PixelFormat();
- PixelFormat.getPixelFormatInfo(format, pf);
- final CapabilitiesImmutable res;
- int r, g, b, a;
-
- switch(format) {
- case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break;
- case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break;
- case PixelFormat.RGB_888: r=8; g=8; b=8; a=0; break;
- case PixelFormat.RGB_565: r=5; g=6; b=5; a=0; break;
- case PixelFormat.RGBA_5551: r=5; g=5; b=5; a=1; break;
- case PixelFormat.RGBA_4444: r=4; g=4; b=4; a=4; break;
- case PixelFormat.RGB_332: r=3; g=3; b=2; a=0; break;
- default: throw new InternalError("Unhandled pixelformat: "+format);
- }
- final boolean change = matchFormatPrecise ||
- rCaps.getRedBits() > r &&
- rCaps.getGreenBits() > g &&
- rCaps.getBlueBits() > b &&
- rCaps.getAlphaBits() > a ;
-
- if(change) {
- Capabilities nCaps = (Capabilities) rCaps.cloneMutable();
- nCaps.setRedBits(r);
- nCaps.setGreenBits(g);
- nCaps.setBlueBits(b);
- nCaps.setAlphaBits(a);
- res = nCaps;
- } else {
- res = rCaps;
- }
- Log.d(MD.TAG, "fixCaps: format: "+format);
- Log.d(MD.TAG, "fixCaps: requested: "+rCaps);
- Log.d(MD.TAG, "fixCaps: chosen: "+res);
-
- return res;
- }
-
- public static int getFormat(CapabilitiesImmutable rCaps) {
- int fmt = PixelFormat.UNKNOWN;
-
- if(!rCaps.isBackgroundOpaque()) {
- fmt = PixelFormat.TRANSLUCENT;
- } else if(rCaps.getRedBits()<=5 &&
- rCaps.getGreenBits()<=6 &&
- rCaps.getBlueBits()<=5 &&
- rCaps.getAlphaBits()==0) {
- fmt = PixelFormat.RGB_565;
- }
- /* else if(rCaps.getRedBits()<=5 &&
- rCaps.getGreenBits()<=5 &&
- rCaps.getBlueBits()<=5 &&
- rCaps.getAlphaBits()==1) {
- fmt = PixelFormat.RGBA_5551; // FIXME: Supported ?
- } */
- else {
- fmt = PixelFormat.RGBA_8888;
- }
- Log.d(MD.TAG, "getFormat: requested: "+rCaps);
- Log.d(MD.TAG, "getFormat: returned: "+fmt);
-
- return fmt;
- }
-
- public static boolean isAndroidFormatTransparent(int aFormat) {
- switch (aFormat) {
- case PixelFormat.TRANSLUCENT:
- case PixelFormat.TRANSPARENT:
- return true;
- }
- return false;
- }
-
- class AndroidEvents implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener {
-
- @Override
- public boolean onTouch(View v, android.view.MotionEvent event) {
- final com.jogamp.newt.event.MouseEvent[] newtEvents = AndroidNewtEventFactory.createMouseEvents(event, AndroidWindow.this);
- if(null != newtEvents) {
- focusChanged(false, true);
- for(int i=0; i
+ * In case {@link X11Util#HAS_XLOCKDISPLAY_BUG} and {@link X11Util#XINITTHREADS_ALWAYS_ENABLED},
+ * we use null locking. Even though this seems not to be rational, it gives most stable results on all platforms.
+ *
+ * Otherwise we use basic locking via the constructor {@link X11GraphicsDevice#X11GraphicsDevice(long, int, boolean)},
+ * since it is possible to share this device via {@link com.jogamp.newt.NewtFactory#createDisplay(String, boolean)}.
+ *
* You may test this, ie just reverse the destroy order below. - * See also native test: jogl/test/native/displayMultiple02.c + * See also native test: jogl/test-native/displayMultiple02.c *
** Workaround is to not close them at all if driver vendor is ATI. *
*/ - public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = true; + public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true); /** Value istrue
, best 'stable' results if always using XInitThreads(). */
public static final boolean XINITTHREADS_ALWAYS_ENABLED = true;
@@ -95,6 +95,9 @@ public class X11Util {
private static Object setX11ErrorHandlerLock = new Object();
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
public static void initSingleton() {
if(!isInit) {
synchronized(X11Util.class) {
@@ -138,6 +141,52 @@ public class X11Util {
}
}
+ /**
+ * Cleanup resources.
+ * + * Called by {@link NativeWindowFactory#shutdown()} + *
+ */ + public static void shutdown() { + if(isInit) { + synchronized(X11Util.class) { + if(isInit) { + final boolean isJVMShuttingDown = NativeWindowFactory.isJVMShuttingDown() ; + if(DEBUG || openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0) { + System.err.println("X11Util.Display: Shutdown (JVM shutdown: "+isJVMShuttingDown+ + ", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+ + ", reusable (open, marked uncloseable): "+reusableDisplayList.size()+ + ", pending (post closing): "+pendingDisplayList.size()+ + ")"); + if(DEBUG) { + Thread.dumpStack(); + } + if( openDisplayList.size() > 0) { + X11Util.dumpOpenDisplayConnections(); + } + if( reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) { + X11Util.dumpPendingDisplayConnections(); + } + } + + synchronized(globalLock) { + // Only at JVM shutdown time, since AWT impl. seems to + // dislike closing of X11 Display's (w/ ATI driver). + if( isJVMShuttingDown ) { + isInit = false; + closePendingDisplayConnections(); + openDisplayList.clear(); + reusableDisplayList.clear(); + pendingDisplayList.clear(); + openDisplayMap.clear(); + shutdown0(); + } + } + } + } + } + } + public static synchronized boolean isNativeLockAvailable() { return isX11LockAvailable; } @@ -183,6 +232,7 @@ public class X11Util { private static Object globalLock = new Object(); private static LongObjectHashMap openDisplayMap = new LongObjectHashMap(); // handle -> name private static ListrealXCloseOpenAndPendingDisplays
is false
,
- * keep alive all references (open display connection) for restart on same ClassLoader.
- *
- * @return number of unclosed X11 Displays.true
if basic FBO support is available, otherwise false
.
- *
- * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
- * ARB_ES2_compatibility
, ARB_framebuffer_object
, EXT_framebuffer_object
or OES_framebuffer_object
.
- *
- * Basic FBO support may only include one color attachment and no multisampling, - * as well as limited internal formats for renderbuffer. - *
- * @see GLContext#hasFBO() - */ - public static final boolean supportsBasicFBO(GL gl) { - return gl.getContext().hasFBO(); - } - - /** - * Returnstrue
if full FBO support is available, otherwise false
.
- *
- * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
- * ARB_framebuffer_object
, or all of
- * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
- * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
- *
- * Full FBO support includes multiple color attachments and multisampling. - *
+ * Marker interface, denotes a color buffer attachment. + *Always an instance of {@link Attachment}.
+ *Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.
*/
- public static final boolean supportsFullFBO(GL gl) {
- return !forceMinimumFBOSupport &&
- ( gl.isGL3() || // GL >= 3.0
- gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
-
- ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object*
- gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
- gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
- gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
- )
- ) ;
- }
-
- public static final int getMaxSamples(GL gl) {
- if( supportsFullFBO(gl) ) {
- int[] val = new int[] { 0 } ;
- gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
- return val[0];
- } else {
- return 0;
- }
+ public static interface Colorbuffer {
+ /**
+ * Initializes the color buffer and set it's parameter, if uninitialized, i.e. name is zero
.
+ * @return true
if newly initialized, otherwise false
.
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
+ */
+ public boolean initialize(GL gl) throws GLException;
+
+ /**
+ * Releases the color buffer if initialized, i.e. name is not zero
.
+ * @throws GLException if buffer release fails.
+ */
+ public void free(GL gl) throws GLException;
+
+ /**
+ * Writes the internal format to the given GLCapabilities object.
+ * @param caps the destination for format bits
+ * @param rgba8Avail whether rgba8 is available
+ */
+ public void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail);
}
/** Common super class of all attachments */
@@ -155,21 +134,89 @@ public class FBObject {
private int name;
- /** true
if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */
- protected boolean resourceOwner;
-
- private int initCounter;
-
protected Attachment(Type type, int iFormat, int width, int height, int name) {
this.type = type;
this.format = iFormat;
this.width = width;
this.height = height;
this.name = name;
- this.resourceOwner = false;
- this.initCounter = 0;
}
+ /**
+ * Writes the internal format to the given GLCapabilities object.
+ * @param caps the destination for format bits
+ * @param rgba8Avail whether rgba8 is available
+ */
+ public final void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail) {
+ final int _format;
+ switch(format) {
+ case GL.GL_RGBA:
+ _format = rgba8Avail ? GL.GL_RGBA8 : GL.GL_RGBA4;
+ break;
+ case GL.GL_RGB:
+ _format = rgba8Avail ? GL.GL_RGB8 : GL.GL_RGB565;
+ break;
+ default:
+ _format = format;
+ }
+ switch(_format) {
+ case GL.GL_RGBA4:
+ caps.setRedBits(4);
+ caps.setGreenBits(4);
+ caps.setBlueBits(4);
+ caps.setAlphaBits(4);
+ break;
+ case GL.GL_RGB5_A1:
+ caps.setRedBits(5);
+ caps.setGreenBits(5);
+ caps.setBlueBits(5);
+ caps.setAlphaBits(1);
+ break;
+ case GL.GL_RGB565:
+ caps.setRedBits(5);
+ caps.setGreenBits(6);
+ caps.setBlueBits(5);
+ caps.setAlphaBits(0);
+ break;
+ case GL.GL_RGB8:
+ caps.setRedBits(8);
+ caps.setGreenBits(8);
+ caps.setBlueBits(8);
+ caps.setAlphaBits(0);
+ break;
+ case GL.GL_RGBA8:
+ caps.setRedBits(8);
+ caps.setGreenBits(8);
+ caps.setBlueBits(8);
+ caps.setAlphaBits(8);
+ break;
+ case GL.GL_DEPTH_COMPONENT16:
+ caps.setDepthBits(16);
+ break;
+ case GL.GL_DEPTH_COMPONENT24:
+ caps.setDepthBits(24);
+ break;
+ case GL.GL_DEPTH_COMPONENT32:
+ caps.setDepthBits(32);
+ break;
+ case GL.GL_STENCIL_INDEX1:
+ caps.setStencilBits(1);
+ break;
+ case GL.GL_STENCIL_INDEX4:
+ caps.setStencilBits(4);
+ break;
+ case GL.GL_STENCIL_INDEX8:
+ caps.setStencilBits(8);
+ break;
+ case GL.GL_DEPTH24_STENCIL8:
+ caps.setDepthBits(24);
+ caps.setStencilBits(8);
+ break;
+ default:
+ throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format));
+ }
+ }
+
/** width of attachment */
public final int getWidth() { return width; }
/** height of attachment */
@@ -180,45 +227,31 @@ public class FBObject {
public final int getName() { return name; }
/* pp */ final void setName(int n) { name = n; }
- public final int getInitCounter() { return initCounter; }
-
/**
- * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is zero
.
- *
Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.
- * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. - */ - public void initialize(GL gl) throws GLException { - initCounter++; - /* - super.initialize(gl); - if(1 == getInitCounter() && 0 == getName() ) { + * Initializes the attachment and set it's parameter, if uninitialized, i.e. name iszero
.
+ * + final boolean init = 0 == name; + if( init ) { do init .. - freeResources = true; // if all OK } - */ - } + return init; + *+ * @return
true
if newly initialized, otherwise false
.
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
+ */
+ public abstract boolean initialize(GL gl) throws GLException;
/**
- * Releases the attachment buffer if initialized, i.e. name is zero
.
- * Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.
- * @throws GLException if buffer release fails. - */ - public void free(GL gl) throws GLException { - /* - if(1 == getInitCounter() && freeResources && .. ) { + * Releases the attachment if initialized, i.e. name is notzero
.
+ * + if(0 != name) { do free .. - } - super.free(gl); - */ - initCounter--; - if(0 == initCounter) { - resourceOwner = false; name = 0; } - if(DEBUG) { - System.err.println("Attachment.free: "+this); - } - } + *+ * @throws GLException if buffer release fails. + */ + public abstract void free(GL gl) throws GLException; /** *
@@ -232,9 +265,9 @@ public class FBObject { if( ! ( o instanceof Attachment ) ) return false; final Attachment a = (Attachment)o; return type == a.type && - format == a.format || - width == a.width || - height== a.height || + format == a.format && + width == a.width && + height== a.height && name == a.name ; } @@ -259,8 +292,7 @@ public class FBObject { public String toString() { return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+ - ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+ - ", resOwner "+resourceOwner+", initCount "+initCounter+"]"; + ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+"]"; } public static Type getType(int attachmentPoint, int maxColorAttachments) { @@ -277,7 +309,7 @@ public class FBObject { } } } - + /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ public static class RenderAttachment extends Attachment { private int samples; @@ -339,14 +371,13 @@ public class FBObject { } @Override - public void initialize(GL gl) throws GLException { - super.initialize(gl); - if( 1 == getInitCounter() && 0 == getName() ) { + public boolean initialize(GL gl) throws GLException { + final boolean init = 0 == getName(); + if( init ) { + int glerr = checkPreGLError(gl); + final int[] name = new int[] { -1 }; gl.glGenRenderbuffers(1, name, 0); - if( 0 == name[0] ) { - throw new GLException("null renderbuffer, "+this); - } setName(name[0]); gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); @@ -355,43 +386,37 @@ public class FBObject { } else { gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); } - int glerr = gl.glGetError(); + glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { gl.glDeleteRenderbuffers(1, name, 0); setName(0); throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); } - resourceOwner = true; if(DEBUG) { System.err.println("Attachment.init: "+this); } } + return init; } @Override public void free(GL gl) { - if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { - final int[] name = new int[] { getName() }; + final int[] name = new int[] { getName() }; + if( 0 != name[0] ) { gl.glDeleteRenderbuffers(1, name, 0); + setName(0); + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } } - super.free(gl); } public String toString() { return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ - ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+ - ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]"; + ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+"]"; } } - /** - * Marker interface, denotes a color buffer attachment. - *
Always an instance of {@link Attachment}.
- *Either an instance of {@link ColorAttachment} or {@link TextureAttachment}. - */ - public static interface Colorbuffer { - } - /** Color render buffer attachment */ public static class ColorAttachment extends RenderAttachment implements Colorbuffer { public ColorAttachment(int iFormat, int samples, int width, int height, int name) { @@ -444,9 +469,11 @@ public class FBObject { * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case. */ @Override - public void initialize(GL gl) throws GLException { - super.initialize(gl); - if( 1 == getInitCounter() && 0 == getName() ) { + public boolean initialize(GL gl) throws GLException { + final boolean init = 0 == getName(); + if( init ) { + int glerr = checkPreGLError(gl); + final int[] name = new int[] { -1 }; gl.glGenTextures(1, name, 0); if(0 == name[0]) { @@ -468,31 +495,111 @@ public class FBObject { if( 0 < wrapT ) { gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); } - int glerr = gl.glGetError(); + glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { gl.glDeleteTextures(1, name, 0); setName(0); throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); } - resourceOwner = true; - } - if(DEBUG) { - System.err.println("Attachment.init: "+this); + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } } + return init; } @Override public void free(GL gl) { - if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { - final int[] name = new int[] { getName() }; + final int[] name = new int[] { getName() }; + if( 0 != name[0] ) { gl.glDeleteTextures(1, name, 0); + setName(0); + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } } - super.free(gl); + } + } + + /** + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, + * selecting the texture data type and format automatically. + * + *
Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.
+ * + * @param glp the chosen {@link GLProfile} + * @param alpha set totrue
if you request alpha channel, otherwise false
;
+ * @param width texture width
+ * @param height texture height
+ * @return the created and uninitialized color {@link TextureAttachment}
+ */
+ public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height) {
+ return createColorTextureAttachment(glp, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ }
+
+ /**
+ * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE},
+ * selecting the texture data type and format automatically.
+ *
+ * @param glp the chosen {@link GLProfile}
+ * @param alpha set to true
if you request alpha channel, otherwise false
;
+ * @param width texture width
+ * @param height texture height
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return the created and uninitialized color {@link TextureAttachment}
+ */
+ public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height,
+ int magFilter, int minFilter, int wrapS, int wrapT) {
+ final int textureInternalFormat, textureDataFormat, textureDataType;
+ if(glp.isGLES()) {
+ textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return createColorTextureAttachment(textureInternalFormat, width, height, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
+ /**
+ * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}.
+ *
+ * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param width texture width
+ * @param height texture height
+ * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return the created and uninitialized color {@link TextureAttachment}
+ */
+ public static final TextureAttachment createColorTextureAttachment(int internalFormat, int width, int height, int dataFormat, int dataType,
+ int magFilter, int minFilter, int wrapS, int wrapT) {
+ return new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType,
+ magFilter, minFilter, wrapS, wrapT, 0 /* name */);
+ }
+
+ private static boolean hasAlpha(int format) {
+ switch(format) {
+ case GL.GL_RGBA8:
+ case GL.GL_RGBA4:
+ case GL.GL_RGBA:
+ case GL.GL_BGRA:
+ case 4:
+ return true;
+ default:
+ return false;
}
}
private boolean initialized;
- private boolean basicFBOSupport;
private boolean fullFBOSupport;
private boolean rgba8Avail;
private boolean depth24Avail;
@@ -523,6 +630,9 @@ public class FBObject {
//
private final void validateColorAttachmentPointRange(int point) {
+ if(!initialized) {
+ throw new GLException("FBO not initialized");
+ }
if(maxColorAttachments != colorAttachmentPoints.length) {
throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints);
}
@@ -621,7 +731,6 @@ public class FBObject {
this.initialized = false;
// TBD @ init
- this.basicFBOSupport = false;
this.fullFBOSupport = false;
this.rgba8Avail = false;
this.depth24Avail = false;
@@ -657,14 +766,11 @@ public class FBObject {
private void init(GL gl, int width, int height, int samples) throws GLException {
if(initialized) {
throw new GLException("FBO already initialized");
- }
- fullFBOSupport = supportsFullFBO(gl);
-
- if( !fullFBOSupport && !supportsBasicFBO(gl) ) {
+ }
+ if( !gl.hasBasicFBOSupport() ) {
throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this);
}
-
- basicFBOSupport = true;
+ fullFBOSupport = gl.hasFullFBOSupport();
rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8);
depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24);
@@ -680,10 +786,7 @@ public class FBObject {
int val[] = new int[1];
- int glerr = gl.glGetError();
- if(DEBUG && GL.GL_NO_ERROR != glerr) {
- System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr));
- }
+ int glerr = checkPreGLError(gl);
int realMaxColorAttachments = 1;
maxColorAttachments = 1;
@@ -703,16 +806,7 @@ public class FBObject {
colorAttachmentPoints = new Colorbuffer[maxColorAttachments];
colorAttachmentCount = 0;
- maxSamples = 0;
- if(fullFBOSupport) {
- gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
- glerr = gl.glGetError();
- if(GL.GL_NO_ERROR == glerr) {
- maxSamples = val[0];
- } else if(DEBUG) {
- System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
- }
- }
+ maxSamples = gl.getMaxRenderbufferSamples();
if(!forceMinimumFBOSupport) {
gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
maxTextureSize = val[0];
@@ -733,10 +827,9 @@ public class FBObject {
this.samples = samples <= maxSamples ? samples : maxSamples;
if(DEBUG) {
- System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples");
- System.err.println("basicFBOSupport: "+basicFBOSupport);
+ System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+this.samples+" samples");
System.err.println("fullFBOSupport: "+fullFBOSupport);
- System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments);
+ System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments+" [capped/real]");
System.err.println("maxSamples: "+maxSamples);
System.err.println("maxTextureSize: "+maxTextureSize);
System.err.println("maxRenderbufferSize: "+maxRenderbufferSize);
@@ -761,12 +854,8 @@ public class FBObject {
throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]");
}
- if(null != samplesSink) {
- // init sampling sink
- samplesSink.reset(gl, width, height);
- resetMSAATexture2DSink(gl);
- }
-
+ resetMSAATexture2DSink(gl);
+
// generate fbo ..
gl.glGenFramebuffers(1, val, 0);
fbName = val[0];
@@ -780,7 +869,8 @@ public class FBObject {
if(!gl.glIsFramebuffer(fbName)) {
checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
}
- bound = true;
+ bound = true;
+ samplesSinkDirty = true;
initialized = true;
updateStatus(gl);
@@ -797,7 +887,7 @@ public class FBObject {
* to match the new given parameters.
*
* - * Currently incompatibility and hence recreation is given if + * Incompatibility and hence recreation is forced if * the size or sample count doesn't match for subsequent calls. *
* @@ -820,17 +910,17 @@ public class FBObject { * to match the new given parameters. * *- * Currently incompatibility and hence recreation is given if - * the size or sample count doesn't match for subsequent calls. + * Currently incompatibility and hence recreation of the attachments will be performed + * if the size or sample count doesn't match for subsequent calls. *
* *Leaves the FBO bound state untouched
* * @param gl the current GL context - * @param newWidth - * @param newHeight + * @param newWidth the new width, it's minimum is capped to 1 + * @param newHeight the new height, it's minimum is capped to 1 * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}. - * @throws GLException in case of an error + * @throws GLException in case of an error, i.e. size too big, etc .. */ public final void reset(GL gl, int newWidth, int newHeight, int newSamples) { if(!initialized) { @@ -841,13 +931,15 @@ public class FBObject { newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp if( newWidth != width || newHeight != height || newSamples != samples ) { + if(0>=newWidth) { newWidth = 1; } + if(0>=newHeight) { newHeight = 1; } if(newWidth > 2 + maxTextureSize || newHeight> 2 + maxTextureSize || newWidth > maxRenderbufferSize || newHeight> maxRenderbufferSize ) { throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); } if(DEBUG) { - System.err.println("FBObject.reset - START - "+this); + System.err.println("FBObject.reset - START - "+width+"x"+height+", "+samples+" -> "+newWidth+"x"+newHeight+", "+newSamples+"; "+this); } final boolean wasBound = isBound(); @@ -856,11 +948,18 @@ public class FBObject { height = newHeight; samples = newSamples; detachAllImpl(gl, true , true); - resetMSAATexture2DSink(gl); - if(wasBound) { - bind(gl); - } else { + /** + * Postpone reset of samplesSink until syncFramebuffer, + * issued at use(..) method (swapBuffer usually initiates it). + * This allows another thread to still use the 'samplesSinkTexture' + * until swapBuffer happens and does not invalidate the GL_FRONT + * FBO (framebuffer & texture). + resetMSAATexture2DSink(gl); + */ + samplesSinkDirty = true; + + if(!wasBound) { unbind(gl); } @@ -870,6 +969,28 @@ public class FBObject { } } + /** + * Writes the internal format of the attachments to the given GLCapabilities object. + * @param caps the destination for format bits + */ + public final void formatToGLCapabilities(GLCapabilities caps) { + caps.setSampleBuffers(samples > 0); + caps.setNumSamples(samples); + caps.setDepthBits(0); + caps.setStencilBits(0); + + final Colorbuffer cb = samples > 0 ? getSamplingSink() : getColorbuffer(0); + if(null != cb) { + cb.formatToGLCapabilities(caps, rgba8Avail); + } + if(null != depth) { + depth.formatToGLCapabilities(caps, rgba8Avail); + } + if(null != stencil && stencil != depth) { + stencil.formatToGLCapabilities(caps, rgba8Avail); + } + } + /** * Note that the status may reflect an incomplete state during transition of attachments. * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 @@ -954,6 +1075,15 @@ public class FBObject { } } + private static int checkPreGLError(GL gl) { + int glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("Pre-existing GL error: 0x"+Integer.toHexString(glerr)); + Thread.dumpStack(); + } + return glerr; + } + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { if(GL.GL_NO_ERROR != err) { if(null != gl) { @@ -974,7 +1104,7 @@ public class FBObject { } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point, * selecting the texture data type and format automatically. * *Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.
@@ -986,13 +1116,15 @@ public class FBObject { * @param alpha set totrue
if you request alpha channel, otherwise false
;
* @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
* @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ * @see #createColorTextureAttachment(GLProfile, boolean, int, int)
*/
public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException {
- return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ return (TextureAttachment)attachColorbuffer(gl, attachmentPoint,
+ createColorTextureAttachment(gl.getGLProfile(), alpha, width, height));
}
/**
- * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point,
+ * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point,
* selecting the texture data type and format automatically.
*
* Leaves the FBO bound.
@@ -1006,23 +1138,15 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - final int textureInternalFormat, textureDataFormat, textureDataType; - if(gl.isGLES()) { - textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; - textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; - textureDataType = GL.GL_UNSIGNED_BYTE; - } else { - textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; - textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB; - textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE; - } - return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(gl.getGLProfile(), alpha, width, height, magFilter, minFilter, wrapS, wrapT)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point. * *Leaves the FBO bound.
* @@ -1037,66 +1161,33 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(int, int, int, int, int, int, int, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, int internalFormat, int dataFormat, int dataType, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - return attachTexture2D(gl, attachmentPoint, - new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, - magFilter, minFilter, wrapS, wrapT, 0 /* name */)); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * Creates a {@link ColorAttachment}, selecting the format automatically. * - *
- * In case the passed TextureAttachment texA
is uninitialized, i.e. it's texture name is zero
,
- * a new texture name is generated and setup w/ the texture parameter.
- * Otherwise, i.e. texture name is not zero
, the passed TextureAttachment texA
is
- * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
- *
Leaves the FBO bound.
- * - * @param gl the current GL context - * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above. - * @return the passed TextureAttachmenttexA
instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
- * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ * @param alpha set to true
if you request alpha channel, otherwise false
;
+ * @return uninitialized ColorAttachment instance describing the new attached colorbuffer
*/
- public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException {
- validateAddColorAttachment(attachmentPoint, texA);
-
- if(samples>0) {
- removeColorAttachment(attachmentPoint, texA);
- throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl).");
- }
-
- texA.initialize(gl);
- addColorAttachment(attachmentPoint, texA);
-
- bind(gl);
-
- // Set up the color buffer for use as a renderable texture:
- gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
- GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
- GL.GL_TEXTURE_2D, texA.getName(), 0);
-
- if(!ignoreStatus) {
- updateStatus(gl);
- if(!isStatusValid()) {
- detachColorbuffer(gl, attachmentPoint);
- throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
- }
- }
- if(DEBUG) {
- System.err.println("FBObject.attachTexture2D: "+this);
+ public final ColorAttachment createColorAttachment(boolean alpha) {
+ final int internalFormat;
+ if( rgba8Avail ) {
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
+ } else {
+ internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
}
- return texA;
+ return new ColorAttachment(internalFormat, samples, width, height, 0);
}
-
+
/**
- * Attaches a Color Buffer to this FBO's instance at the given attachment point,
+ * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point,
* selecting the format automatically.
*
* Leaves the FBO bound.
@@ -1106,19 +1197,14 @@ public class FBObject { * @param alpha set totrue
if you request alpha channel, otherwise false
;
* @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
* @throws GLException in case the colorbuffer couldn't be allocated
+ * @see #createColorAttachment(boolean)
*/
public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException {
- final int internalFormat;
- if( rgba8Avail ) {
- internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
- } else {
- internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
- }
- return attachColorbuffer(gl, attachmentPoint, internalFormat);
+ return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, createColorAttachment(alpha));
}
/**
- * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point.
*
* Leaves the FBO bound.
* @@ -1135,46 +1221,80 @@ public class FBObject { throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); } - return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); + return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); } /** - * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}, + * to this FBO's instance at the given attachment point. * + *
+ * If {@link Colorbuffer} is a {@link TextureAttachment} and is uninitialized, i.e. it's texture name is zero
,
+ * a new texture name is generated and setup w/ the texture parameter.
+ * Otherwise, i.e. texture name is not zero
, the passed TextureAttachment texA
is
+ * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
+ *
Leaves the FBO bound.
* * @param gl * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param colA the template for the new {@link ColorAttachment} - * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown - * @throws GLException in case the colorbuffer couldn't be allocated + * @param colbuf the to be attached {@link Colorbuffer} + * @return newly attached {@link Colorbuffer} instance if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated or MSAA has been chosen in case of a {@link TextureAttachment} */ - public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException { - validateAddColorAttachment(attachmentPoint, colA); - - colA.initialize(gl); - addColorAttachment(attachmentPoint, colA); + public final Colorbuffer attachColorbuffer(GL gl, int attachmentPoint, Colorbuffer colbuf) throws GLException { + validateAddColorAttachment(attachmentPoint, colbuf); - bind(gl); + final boolean initializedColorbuf = colbuf.initialize(gl); + addColorAttachment(attachmentPoint, colbuf); - // Attach the color buffer - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, - GL.GL_RENDERBUFFER, colA.getName()); + bind(gl); - if(!ignoreStatus) { - updateStatus(gl); - if(!isStatusValid()) { - detachColorbuffer(gl, attachmentPoint); - throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + if(colbuf instanceof TextureAttachment) { + final TextureAttachment texA = (TextureAttachment) colbuf; + + if(samples>0) { + removeColorAttachment(attachmentPoint, texA); + if(initializedColorbuf) { + texA.free(gl); + } + throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); + } + + // Set up the color buffer for use as a renderable texture: + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, texA.getName(), 0); + + if(!ignoreStatus) { + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint, true); + throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + } + } else if(colbuf instanceof ColorAttachment) { + final ColorAttachment colA = (ColorAttachment) colbuf; + + // Attach the color buffer + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_RENDERBUFFER, colA.getName()); + + if(!ignoreStatus) { + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint, true); + throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } } } if(DEBUG) { - System.err.println("FBObject.attachColorbuffer: "+this); + System.err.println("FBObject.attachColorbuffer: [attachmentPoint "+attachmentPoint+", colbuf "+colbuf+"]: "+this); } - return colA; + return colbuf; } - /** * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, @@ -1355,33 +1475,39 @@ public class FBObject { if(!ignoreStatus) { updateStatus(gl); if( !isStatusValid() ) { - detachRenderbuffer(gl, atype); + detachRenderbuffer(gl, atype, true); throw new GLException("renderbuffer attachment failed: "+this.getStatusString()); } } if(DEBUG) { - System.err.println("FBObject.attachRenderbuffer: "+this); - } + System.err.println("FBObject.attachRenderbuffer: [attachmentType "+atype+"]: "+this); + } } /** + * Detaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}. *Leaves the FBO bound!
+ * * @param gl - * @param ca + * @param attachmentPoint + * @param dispose true if the Colorbuffer shall be disposed + * @return the detached Colorbuffer * @throws IllegalArgumentException */ - public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException { - if(null == detachColorbufferImpl(gl, attachmentPoint, false)) { + public final Colorbuffer detachColorbuffer(GL gl, int attachmentPoint, boolean dispose) throws IllegalArgumentException { + final Colorbuffer res = detachColorbufferImpl(gl, attachmentPoint, dispose ? DetachAction.DISPOSE : DetachAction.NONE); + if(null == res) { throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); } if(DEBUG) { - System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+"]: "+this); + System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+", dispose "+dispose+"]: "+res+", "+this); } + return res; } - private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) { - final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, DetachAction detachAction) { + Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here if(null == colbuf) { return null; @@ -1389,6 +1515,8 @@ public class FBObject { bind(gl); + removeColorAttachment(attachmentPoint, colbuf); + if(colbuf instanceof TextureAttachment) { final TextureAttachment texA = (TextureAttachment) colbuf; if( 0 != texA.getName() ) { @@ -1397,11 +1525,22 @@ public class FBObject { GL.GL_TEXTURE_2D, 0, 0); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); } - texA.free(gl); - removeColorAttachment(attachmentPoint, texA); - if(recreate) { - texA.setSize(width, height); - attachTexture2D(gl, attachmentPoint, texA); + switch(detachAction) { + case DISPOSE: + texA.free(gl); + break; + case RECREATE: + texA.free(gl); + if(samples == 0) { + // stay non MSAA + texA.setSize(width, height); + } else { + // switch to MSAA + colbuf = createColorAttachment(hasAlpha(texA.format)); + } + attachColorbuffer(gl, attachmentPoint, colbuf); + break; + default: } } else if(colbuf instanceof ColorAttachment) { final ColorAttachment colA = (ColorAttachment) colbuf; @@ -1410,12 +1549,30 @@ public class FBObject { GL.GL_COLOR_ATTACHMENT0+attachmentPoint, GL.GL_RENDERBUFFER, 0); } - colA.free(gl); - removeColorAttachment(attachmentPoint, colbuf); - if(recreate) { - colA.setSize(width, height); - colA.setSamples(samples); - attachColorbuffer(gl, attachmentPoint, colA); + switch(detachAction) { + case DISPOSE: + colA.free(gl); + break; + case RECREATE: + colA.free(gl); + if(samples > 0) { + // stay MSAA + colA.setSize(width, height); + colA.setSamples(samples); + } else { + // switch to non MSAA + if(null != samplesSinkTexture) { + colbuf = createColorTextureAttachment(samplesSinkTexture.format, width, height, + samplesSinkTexture.dataFormat, samplesSinkTexture.dataType, + samplesSinkTexture.magFilter, samplesSinkTexture.minFilter, + samplesSinkTexture.wrapS, samplesSinkTexture.wrapT); + } else { + colbuf = createColorTextureAttachment(gl.getGLProfile(), true, width, height); + } + } + attachColorbuffer(gl, attachmentPoint, colbuf); + break; + default: } } return colbuf; @@ -1424,10 +1581,14 @@ public class FBObject { /** * * @param gl + * @param dispose true if the Colorbuffer shall be disposed * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} */ - public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException { - detachRenderbufferImpl(gl, atype, false); + public final void detachRenderbuffer(GL gl, Attachment.Type atype, boolean dispose) throws IllegalArgumentException { + detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE); + if(DEBUG) { + System.err.println("FBObject.detachRenderbuffer: [attachmentType "+atype+", dispose "+dispose+"]: "+this); + } } public final boolean isDepthStencilPackedFormat() { @@ -1439,7 +1600,7 @@ public class FBObject { return res; } - private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException { + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, DetachAction detachAction) throws IllegalArgumentException { switch ( atype ) { case DEPTH: case STENCIL: @@ -1485,8 +1646,14 @@ public class FBObject { if( 0 != depth.getName() ) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - depth.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + depth.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { depth = null; } break; @@ -1495,8 +1662,14 @@ public class FBObject { if(0 != stencil.getName()) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - stencil.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + stencil.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { stencil = null; } break; @@ -1506,9 +1679,15 @@ public class FBObject { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - depth.free(gl); - stencil.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + depth.free(gl); + stencil.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { depth = null; stencil = null; } @@ -1516,14 +1695,15 @@ public class FBObject { default: throw new InternalError("XXX"); } - if(recreate) { + if(DetachAction.RECREATE == detachAction) { attachRenderbufferImpl2(gl, action, format); } } } /** - * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s. + * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s + * and disposes them. *Leaves the FBO bound!
** An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1538,7 +1718,8 @@ public class FBObject { } /** - * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s. + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s + * and disposes them. *
Leaves the FBO bound!
** An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1553,7 +1734,7 @@ public class FBObject { } /** - * Detaches all {@link TextureAttachment}s + * Detaches all {@link TextureAttachment}s and disposes them. *
Leaves the FBO bound!
*
* An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
@@ -1566,30 +1747,33 @@ public class FBObject {
}
for(int i=0; i
+ * Only use this method if a subsequent {@link #unbind(GL)}, {@link #use(GL, TextureAttachment)} or {@link #bind(GL)}
+ * follows on any FBO.
+ * The operation is skipped, if no multisampling is used or
- * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)},
- * see {@link #isSamplingBufferDirty()} If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing
- * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()} In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
+ * If multisampling is being used and flagged dirty by a previous call of {@link #bind(GL)} or after initialization,
+ * the msaa-buffers are sampled to it's sink {@link #getSamplingSink()}.
+ *
+ * Method also updates the sampling sink configuration (if used). Hence it is recommended to call this
+ * method after your have initialized the FBO and attached renderbuffer etc for the 1st time.
+ * Method is called automatically by {@link #use(GL, TextureAttachment)}.
+ *
+ * Methos always resets the framebuffer binding to default in the end.
+ * If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing
+ * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}
+ *
+ * In case you use this FBO w/o the {@link GLFBODrawable} and intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
* you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()});
* Leaves the FBO unbound. If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called. If using multiple texture units, ensure you call {@link GL#glActiveTexture(int)} first! {@link #syncFramebuffer(GL)} is being called Leaves the FBO unbound!
+ * Since no native windowing system events are being processed, it is recommended
+ * to handle at least:
+ * true
if framebuffer object is bound via {@link #bind(GL)}, otherwise false
.
@@ -1785,49 +1988,54 @@ public class FBObject {
public final boolean isBound() { return bound; }
/**
- * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}.
- *
- * true
if basic or full FBO is supported, otherwise false
.
- * @param full true
for full FBO supported query, otherwise false
for basic FBO support query.
- * @see #supportsFullFBO(GL)
- * @see #supportsBasicFBO(GL)
- * @throws GLException if {@link #init(GL)} hasn't been called.
- */
- public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; }
+ /** @see GL#hasFullFBOSupport() */
+ public final boolean hasFullFBOSupport() throws GLException { checkInitialized(); return this.fullFBOSupport; }
/**
* Returns true
if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise false
.
@@ -1878,7 +2076,7 @@ public class FBObject {
public final boolean supportsDepth(int bits) throws GLException {
checkInitialized();
switch(bits) {
- case 16: return basicFBOSupport;
+ case 16: return true;
case 24: return depth24Avail;
case 32: return depth32Avail;
default: return false;
@@ -1913,11 +2111,11 @@ public class FBObject {
*/
public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; }
- /**
- * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported.
- * @throws GLException if {@link #init(GL)} hasn't been called.
- */
- public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; }
+ public final int getMaxTextureSize() throws GLException { checkInitialized(); return this.maxTextureSize; }
+ public final int getMaxRenderbufferSize() throws GLException { checkInitialized(); return this.maxRenderbufferSize; }
+
+ /** @see GL#getMaxRenderbufferSamples() */
+ public final int getMaxSamples() throws GLException { checkInitialized(); return this.maxSamples; }
/**
* Returns true
if this instance has been initialized with {@link #reset(GL, int, int)}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
new file mode 100644
index 000000000..38a8deef8
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
@@ -0,0 +1,189 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLException;
+
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+import jogamp.opengl.GLAutoDrawableBase;
+import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLDrawableImpl;
+
+
+/**
+ * Fully functional {@link GLAutoDrawable} implementation
+ * utilizing already created created {@link GLDrawable} and {@link GLContext} instances.
+ *
+ *
+ *
+ * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. + *
+ */ +public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAutoDrawable { + /** + * @param drawable a valid and already realized {@link GLDrawable} + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param ownDevice passtrue
if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass false
. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ * @param lock optional custom {@link RecursiveLock}.
+ */
+ public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice, RecursiveLock lock) {
+ super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
+ if(null == drawable) {
+ throw new IllegalArgumentException("null drawable");
+ }
+ if(null == context) {
+ throw new IllegalArgumentException("null context");
+ }
+ if(!drawable.isRealized()) {
+ throw new IllegalArgumentException("drawable not realized");
+ }
+ this.upstreamWidget = upstreamWidget;
+ this.lock = ( null != lock ) ? lock : LockFactory.createRecursiveLock() ;
+ }
+
+ //
+ // expose default methods
+ //
+
+ /** Default implementation to handle repaint events from the windowing system */
+ public final void windowRepaintOp() {
+ super.defaultWindowRepaintOp();
+ }
+
+ /** Implementation to handle resize events from the windowing system. All required locks are being claimed. */
+ public final void windowResizedOp(int newWidth, int newHeight) {
+ super.defaultWindowResizedOp(newWidth, newHeight);
+ }
+
+ /**
+ * Implementation to handle destroy notifications from the windowing system.
+ *
+ * + * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} + * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), + * a thread safe destruction is being induced. + *
+ */ + public final void windowDestroyNotifyOp() { + super.defaultWindowDestroyNotifyOp(); + } + + // + // Complete GLAutoDrawable + // + + private Object upstreamWidget; + private final RecursiveLock lock; + + @Override + protected final RecursiveLock getLock() { return lock; } + + @Override + public final Object getUpstreamWidget() { + return upstreamWidget; + } + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + public final void setUpstreamWidget(Object newUpstreamWidget) { + upstreamWidget = newUpstreamWidget; + } + + /** + * {@inheritDoc} + *+ * This implementation calls {@link #defaultDestroy()}. + *
+ *+ * User still needs to destroy the upstream window, which details are hidden from this aspect. + * This can be performed by overriding {@link #destroyImplInLock()}. + *
+ */ + @Override + public final void destroy() { + defaultDestroy(); + } + + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); + } + + @Override + public void display() { + defaultDisplay(); + } + + // + // GLDrawable delegation + // + + @Override + public final GLDrawableFactory getFactory() { + return drawable.getFactory(); + } + + @Override + public final void setRealized(boolean realized) { + } + + @Override + public final void swapBuffers() throws GLException { + defaultSwapBuffers(); + } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + ", \n\tUpstreamWidget: "+upstreamWidget+ /** ", \n\tFactory: "+factory+ */ "]"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java index f7e25fa01..cf81b85ee 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java +++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java @@ -72,6 +72,9 @@ public class GLExtensions { public static final String OES_EGL_image_external = "GL_OES_EGL_image_external"; + public static final String ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; + public static final String ARB_shader_objects = "GL_ARB_shader_objects"; + // // Aliased GLX/WGL/.. extensions // diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java deleted file mode 100644 index 4caea03b2..000000000 --- a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.GLAutoDrawableDelegate; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLException; - -import jogamp.opengl.GLFBODrawableImpl; - -/** - * Platform-independent class exposing FBO offscreen functionality to - * applications. - *- * This class distinguishes itself from {@link GLAutoDrawableDelegate} - * with it's {@link #setSize(int, int)} functionality. - *
- */ -public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param ownDevice passtrue
if {@link AbstractGraphicsDevice#close()} shall be issued,
- * otherwise pass false
. Closing the device is required in case
- * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
- * and no further lifecycle handling is applied.
- */
- public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, boolean ownDevice) {
- super(drawable, context, null, ownDevice);
- }
-
- /**
- * Attempts to resize this offscreen auto drawable, if supported
- * by the underlying {@link GLDrawable).
- * @param newWidth
- * @param newHeight
- * @return true
if resize was executed, otherwise false
.
- * @throws GLException in case of an error during the resize operation
- */
- public boolean setSize(int newWidth, int newHeight) throws GLException {
- boolean done = false;
- if(drawable instanceof GLFBODrawableImpl) {
- Throwable tFBO = null;
- Throwable tGL = null;
- context.makeCurrent();
- try {
- ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight);
- done = true;
- } catch (Throwable t) {
- tFBO = t;
- } finally {
- try {
- context.release();
- } catch (Throwable t) {
- tGL = t;
- }
- }
- if(null != tFBO) {
- throw new GLException("OffscreenAutoDrawable.setSize(..) GLFBODrawableImpl.setSize(..) exception", tFBO);
- }
- if(null != tGL) {
- throw new GLException("OffscreenAutoDrawable.setSize(..) GLContext.release() exception", tGL);
- }
- }
- if(done) {
- this.defaultWindowResizedOp();
- return true;
- }
- return false;
- }
-
- /**
- * If the underlying {@link GLDrawable} is an FBO implementation
- * and contains an {#link FBObject}, the same is returned.
- * Otherwise returns null
.
- */
- public FBObject getFBObject() {
- if(drawable instanceof GLFBODrawableImpl) {
- return ((GLFBODrawableImpl)drawable).getFBObject();
- }
- return null;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 8d237162c..02f62daec 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -30,6 +30,7 @@ package com.jogamp.opengl.swt;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import javax.media.opengl.GL;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
@@ -48,6 +49,7 @@ import javax.media.opengl.Threading;
import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
+import jogamp.opengl.GLDrawableImpl;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
@@ -97,8 +99,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
private final GLCapabilitiesImmutable capsRequested;
private final GLCapabilitiesChooser capsChooser;
- private volatile GLDrawable drawable; // volatile: avoid locking for read-only access
- private GLContext context;
+ private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
+ private GLContextImpl context;
/* Native window surface */
private AbstractGraphicsDevice device;
@@ -319,7 +321,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
});
}
- private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() {
+ private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() {
@Override
public final void create(ProxySurface s) { /* nop */ }
@@ -349,7 +351,27 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
) {
clientArea = nClientArea; // write back new value
- sendReshape = true; // Mark for OpenGL reshape next time the control is painted
+
+ GLDrawableImpl _drawable = drawable;
+ if( null != _drawable ) {
+ if(DEBUG) {
+ System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ }
+ if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientArea.width, nClientArea.height);
+ if(_drawable != _drawableNew) {
+ // write back
+ drawable = _drawableNew;
+ }
+ } finally {
+ _lock.unlock();
+ }
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
+ }
+ }
}
}
@@ -391,10 +413,10 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
if(null != proxySurface) {
/* Associate a GL surface with the proxy */
- drawable = glFactory.createGLDrawable(proxySurface);
+ drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
drawable.setRealized(true);
- context = drawable.createContext(shareWith);
+ context = (GLContextImpl) drawable.createContext(shareWith);
}
} finally {
_lock.unlock();
@@ -455,6 +477,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
return helper.getAutoSwapBufferMode();
}
+ @Override
+ public final GLDrawable getDelegatedDrawable() {
+ return drawable;
+ }
+
@Override
public GLContext getContext() {
return null != drawable ? context : null;
@@ -502,7 +529,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
_lock.lock();
try {
final GLContext oldCtx = context;
- final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
if(newCtxCurrent) {
context.makeCurrent();
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 0b2c664fe..38f1746f9 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -114,6 +114,12 @@ public interface GLAutoDrawable extends GLDrawable {
* where you drag the window to another monitor. */
public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true);
+ /**
+ * If the implementation uses delegation, return the delegated {@link GLDrawable} instance,
+ * otherwise return this
instance.
+ */
+ public GLDrawable getDelegatedDrawable();
+
/**
* Returns the context associated with this drawable. The returned
* context will be synchronized.
@@ -124,23 +130,31 @@ public interface GLAutoDrawable extends GLDrawable {
/**
* Associate a new context to this drawable and also propagates the context/drawable switch by
* calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- * drawable
might be an inner GLDrawable instance if using such a delegation pattern,
- * or this GLAutoDrawable itself.
- * - * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - *
+ *drawable
might be an inner GLDrawable instance if using a delegation pattern,
+ * or this GLAutoDrawable instance.
* * If the old or new context was current on this thread, it is being released before switching the drawable. * The new context will be made current afterwards, if it was current before. - * However the user shall take extra care that not other thread - * attempts to make this context current. Otherwise a race condition may happen. + * However the user shall take extra care that no other thread + * attempts to make this context current. + *
+ *+ * Be aware that the old context is still bound to the drawable, + * and that one context can only be bound to one drawable at one time! *
*- * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! + * In case you do not intend to use the old context anymore, i.e. + * not assigning it to another drawable, it shall be + * destroyed before setting the new context, i.e.: + *
+ GLContext oldCtx = glad.getContext(); + if(null != oldCtx) { + oldCtx.destroy(); + } + glad.setContext(newCtx); + *+ * This is required, since a context must have a valid drawable at all times + * and this API shall not restrict the user in any way. * * * @param newCtx the new context diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java deleted file mode 100644 index 67e81270d..000000000 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package javax.media.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; - -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -import jogamp.opengl.Debug; -import jogamp.opengl.GLAutoDrawableBase; -import jogamp.opengl.GLContextImpl; -import jogamp.opengl.GLDrawableImpl; - - -/** - * Fully functional {@link GLAutoDrawable} implementation - * utilizing already created created {@link GLDrawable} and {@link GLContext} instances. - *
- * Since no native windowing system events are being processed, it is recommended - * to handle at least: - *
- * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. - *
- */ -public class GLAutoDrawableDelegate extends GLAutoDrawableBase { - public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. - * @param ownDevice passtrue
if {@link AbstractGraphicsDevice#close()} shall be issued,
- * otherwise pass false
. Closing the device is required in case
- * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
- * and no further lifecycle handling is applied.
- */
- public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) {
- super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
- this.upstreamWidget = null;
- }
-
- //
- // expose default methods
- //
-
- public final void windowRepaintOp() {
- super.defaultWindowRepaintOp();
- }
-
- public final void windowResizedOp() {
- super.defaultWindowResizedOp();
- }
-
- public final void windowDestroyNotifyOp() {
- super.defaultWindowDestroyNotifyOp();
- }
-
- //
- // Complete GLAutoDrawable
- //
-
- private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
- private final Object upstreamWidget;
-
- @Override
- protected final RecursiveLock getLock() { return lock; }
-
- @Override
- public final Object getUpstreamWidget() {
- return upstreamWidget;
- }
-
- /**
- * {@inheritDoc}
- * - * This implementation calls {@link #defaultDestroy()}. - *
- *- * User still needs to destroy the upstream window, which details are hidden from this aspect. - * This can be performed by overriding {@link #destroyImplInLock()}. - *
- */ - @Override - public final void destroy() { - defaultDestroy(); - } - - @Override - public void display() { - defaultDisplay(); - } - - // - // GLDrawable delegation - // - - @Override - public final GLDrawableFactory getFactory() { - return drawable.getFactory(); - } - - @Override - public final void setRealized(boolean realized) { - } - - @Override - public final void swapBuffers() throws GLException { - defaultSwapBuffers(); - } - -} diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index f5831a72d..9bcee819a 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -273,6 +273,42 @@ public interface GLBase { */ public boolean isExtensionAvailable(String glExtensionName); + /** + * Returnstrue
if basic FBO support is available, otherwise false
.
+ *
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * GL_ARB_ES2_compatibility
, GL_ARB_framebuffer_object
, GL_EXT_framebuffer_object
or GL_OES_framebuffer_object
.
+ *
+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *
+ * @see GLContext#hasBasicFBOSupport() + */ + public boolean hasBasicFBOSupport(); + + /** + * Returnstrue
if full FBO support is available, otherwise false
.
+ *
+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * ARB_framebuffer_object
, or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ *
+ * Full FBO support includes multiple color attachments and multisampling. + *
+ * @see GLContext#hasFullFBOSupport() + */ + public boolean hasFullFBOSupport(); + + /** + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. + * @see GLContext#getMaxRenderbufferSamples() + */ + public int getMaxRenderbufferSamples(); + /** * Returns true if the GL context supports non power of two (NPOT) textures, * otherwise false. @@ -284,6 +320,8 @@ public interface GLBase { */ public boolean isNPOTTextureAvailable(); + public boolean isTextureFormatBGRA8888Available(); + /** Provides a platform-independent way to specify the minimum swap interval for buffer swaps. An argument of 0 disables sync-to-vertical-refresh completely, while an argument of 1 diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index c2f94b9af..a5e639c74 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -96,6 +96,9 @@ public abstract class GLContext { */ public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true); + protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true); + protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true); + public static final boolean DEBUG = Debug.debug("GLContext"); public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true); @@ -127,9 +130,9 @@ public abstract class GLContext { /**GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
- /** Context supports basic FBO, details see {@link #hasFBO()}.
+ /** Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
* Not a cache key.
- * @see #hasFBO()
+ * @see #hasBasicFBOSupport()
* @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
*/
protected static final int CTX_IMPL_FBO = 1 << 9;
@@ -178,11 +181,6 @@ public abstract class GLContext {
* and made current afterwards. However the user shall take extra care that not other thread
* attempts to make this context current. Otherwise a race condition may happen.
*
- * - * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! - *
* @param readWrite the read/write drawable for framebuffer operations. * @param setWriteOnly iftrue
and if the current read-drawable differs
* from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}),
@@ -603,12 +601,23 @@ public abstract class GLContext {
/**
* @return true if impl. is a hardware rasterizer, otherwise false.
+ * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile)
* @see GLProfile#isHardwareRasterizer()
*/
public final boolean isHardwareRasterizer() {
return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
}
+ /**
+ * @return true if context supports GLSL, i.e. is either {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} and major-version > 1.
+ * @see GLProfile#hasGLSL()
+ */
+ public final boolean hasGLSL() {
+ return isGLES2() ||
+ isGL3() ||
+ isGL2() && ctxMajorVersion>1 ;
+ }
+
/**
* Returns true
if basic FBO support is available, otherwise false
.
* @@ -620,21 +629,54 @@ public abstract class GLContext { * as well as limited internal formats for renderbuffer. *
* @see #CTX_IMPL_FBO - * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) - * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ - public final boolean hasFBO() { + public final boolean hasBasicFBOSupport() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; } + /** + * Returnstrue
if full FBO support is available, otherwise false
.
+ *
+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * ARB_framebuffer_object
, or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ *
+ * Full FBO support includes multiple color attachments and multisampling. + *
+ */ + public final boolean hasFullFBOSupport() { + return !FORCE_MIN_FBO_SUPPORT && hasBasicFBOSupport() && + ( isGL3() || // GL >= 3.0 + isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) + ) + ) ; + } + /** - * @return true if context supports GLSL - * @see GLProfile#hasGLSL() + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. */ - public final boolean hasGLSL() { - return isGL2ES2() ; + public final int getMaxRenderbufferSamples() { + if( hasFullFBOSupport() ) { + final GL gl = getGL(); + final int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + final int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + return val[0]; + } else if(DEBUG) { + System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + return 0; } - + /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returnstrue
. */
public boolean isNPOTTextureAvailable() {
return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
@@ -1014,6 +1056,9 @@ public abstract class GLContext {
validateProfileBits(profile, "profile");
validateProfileBits(resCtp, "resCtp");
+ if(FORCE_NO_FBO_SUPPORT) {
+ resCtp &= ~CTX_IMPL_FBO ;
+ }
if(DEBUG) {
System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
// Thread.dumpStack();
@@ -1197,17 +1242,35 @@ public abstract class GLContext {
* FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
*
* - * FBO support is queried as described in {@link #hasFBO()}. + * FBO support is queried as described in {@link #hasBasicFBOSupport()}. *
* * @param device the device to request whether FBO is available for * @param glp {@link GLProfile} to check for FBO capabilities - * @see GLContext#hasFBO() + * @see GLContext#hasBasicFBOSupport() */ public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); } + /** + * @return1
if using a hardware rasterizer, 0
if using a software rasterizer and -1
if not determined yet.
+ * @see GLContext#isHardwareRasterizer()
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public static final int isHardwareRasterizer(AbstractGraphicsDevice device, GLProfile glp) {
+ final int r;
+ final int ctp = getAvailableContextProperties(device, glp);
+ if(0 == ctp) {
+ r = -1;
+ } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
+ r = 1;
+ } else {
+ r = 0;
+ }
+ return r;
+ }
+
/**
* @param device the device to request whether the profile is available for
* @param reqMajor Key Value either 1, 2, 3 or 4
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 9fd895c1f..b6e7b0576 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -48,13 +48,16 @@ import java.util.List;
import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import jogamp.opengl.Debug;
@@ -373,44 +376,63 @@ public abstract class GLDrawableFactory {
// Methods to create high-level objects
/**
- * Returns a GLDrawable according to it's chosen Capabilities,- * The native platform's chosen Capabilties are referenced within the target - * NativeSurface's AbstractGraphicsConfiguration.
- *
- * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is true,
- * an onscreen GLDrawable will be realized.
+ * The chosen {@link GLCapabilitiesImmutable} are referenced within the target
+ * {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.
+ *
*
- * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is false,
- * either a Pbuffer drawable is created if target's {@link javax.media.opengl.GLCapabilities#isPBuffer()} is true,
- * or a simple pixmap/bitmap drawable is created. The latter is unlikely to be hardware accelerated.
+ * An onscreen GLDrawable is created if {@link CapabilitiesImmutable#isOnscreen() caps.isOnscreen()} is true.
+ *
- * + * A FBO drawable is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *
+ *+ * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *
+ *+ * If not onscreen and neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + *
+ * * @throws IllegalArgumentException if the passed target is null * @throws GLException if any window system-specific errors caused * the creation of the GLDrawable to fail. * + * @see #canCreateGLPbuffer(AbstractGraphicsDevice) + * @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) + * @see javax.media.opengl.GLCapabilities#isOnscreen() + * @see javax.media.opengl.GLCapabilities#isFBO() + * @see javax.media.opengl.GLCapabilities#isPBuffer() * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) */ public abstract GLDrawable createGLDrawable(NativeSurface target) throws IllegalArgumentException, GLException; - + /** - * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. + * Creates an {@link GLOffscreenAutoDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. *- * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below. + * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is realized and it's {@link GLContext} assigned but not yet made current. *
*
- * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()}
+ * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
+ * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} == true
,
+ * it is auto-configured. The latter will set offscreen and also FBO or Pbuffer, whichever is available in that order.
+ *
+ * A FBO based auto drawable, {@link GLOffscreenAutoDrawable.FBO}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. *
*- * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} - * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + * A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. *
*- * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap auto drawable is created, which is unlikely to be hardware accelerated. *
* * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may benull
for the platform's default device.
@@ -418,17 +440,55 @@ public abstract class GLDrawableFactory {
* @param chooser the custom chooser, may be null for default
* @param width the requested offscreen width
* @param height the requested offscreen height
+ * @return the created and initialized offscreen {@link GLOffscreenAutoDrawable} instance
*
- * @return the created offscreen GLDrawable
+ * @throws GLException if any window system-specific errors caused
+ * the creation of the Offscreen to fail.
+ *
+ * @see #createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int)
+ */
+ public abstract GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice device,
+ GLCapabilitiesImmutable caps,
+ GLCapabilitiesChooser chooser,
+ int width, int height,
+ GLContext shareWith) throws GLException;
+ /**
+ * Creates a offscreen {@link GLDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
+ *
+ * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
+ * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} == true
,
+ * it is auto-configured. The latter will set offscreen and also FBO or Pbuffer, whichever is available in that order.
+ *
+ * A resizeable FBO drawable, {@link GLFBODrawable.Resizeable}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *
+ *+ * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *
+ *+ * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable is created, which is unlikely to be hardware accelerated. + *
+ * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may benull
for the platform's default device.
+ * @param caps the requested GLCapabilties
+ * @param chooser the custom chooser, may be null for default
+ * @param width the requested offscreen width
+ * @param height the requested offscreen height
+ *
+ * @return the created offscreen {@link GLDrawable}
*
* @throws GLException if any window system-specific errors caused
* the creation of the Offscreen to fail.
+ *
+ * @see #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)
*/
public abstract GLDrawable createOffscreenDrawable(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities,
+ GLCapabilitiesImmutable caps,
GLCapabilitiesChooser chooser,
- int width, int height)
- throws GLException;
+ int width, int height) throws GLException;
/**
* Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance.
@@ -458,6 +518,21 @@ public abstract class GLDrawableFactory {
long windowHandle,
GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
+ /**
+ * Returns true if it is possible to create an framebuffer object (FBO).
+ * + * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *
+ *+ * FBO support is queried as described in {@link GLContext#hasBasicFBOSupport()}. + *
+ * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may benull
for the platform's default device.
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasBasicFBOSupport()
+ */
+ public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp);
+
/**
* Returns true if it is possible to create a GLPbuffer. Some older
* graphics cards do not have this capability.
@@ -467,7 +542,10 @@ public abstract class GLDrawableFactory {
public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
/**
- * Creates a GLPbuffer with the given capabilites and dimensions. + * Creates a GLPbuffer {@link GLAutoDrawable} with the given capabilites and dimensions. + *
+ * The GLPbuffer drawable is realized and initialized eagerly. + *
* * See the note in the overview documentation on * context sharing. @@ -479,10 +557,12 @@ public abstract class GLDrawableFactory { * @param initialHeight initial height of pbuffer * @param shareWith a shared GLContext this GLPbuffer shall use * - * @return the new {@link GLPbuffer} specific {@link GLAutoDrawable} + * @return the created and initialized {@link GLPbuffer} instance * * @throws GLException if any window system-specific errors caused * the creation of the GLPbuffer to fail. + * + * @deprecated {@link GLPbuffer} is deprecated, use {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)} */ public abstract GLPbuffer createGLPbuffer(AbstractGraphicsDevice device, GLCapabilitiesImmutable capabilities, diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java new file mode 100644 index 000000000..45fd3b686 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java @@ -0,0 +1,173 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; + +/** + * Platform-independent {@link GLDrawable} specialization, + * exposing {@link FBObject} functionality. + * + *+ * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound + * and made current the first time. + *
+ * + *+ * MSAA is used if {@link GLCapabilitiesImmutable#getNumSamples() requested}. + *
+ *+ * Double buffering is used if {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}. + *
+ *+ * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}. + * Hence double buffering is always the case w/ MSAA. + *
+ *+ * In non MSAA a second explicit {@link FBObject framebuffer} is being used. + * This method allows compliance w/ the spec, i.e. read and draw framebuffer selection + * and double buffer usage for e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}. + * This method also allows usage of both textures seperately. + *
+ *+ * It would be possible to implement double buffering simply using + * {@link FBObject.TextureAttachment texture attachment}s with one {@link FBObject framebuffer}. + * This would require mode selection and hence complicate the API. Besides, it would + * not support differentiation of read and write framebuffer and hence not be spec compliant. + *
+ *
+ * Actual swapping of the {@link FBObject.TextureAttachment texture}s or {@link FBObject framebuffer}
+ * is performed either in the {@link #contextMadeCurrent(boolean) context current hook}
+ * or when {@link #swapBuffersImpl(boolean) swapping buffers}, whatever comes first.
+ *
true
if initialized, i.e. a {@link GLContext} is bound and made current once, otherwise false
.
+ */
+ public boolean isInitialized();
+
+ /**
+ * Notify this instance about upstream size change
+ * to reconfigure the {@link FBObject}.
+ * @param gl GL context object bound to this drawable, will be made current during operation.
+ * A prev. current context will be make current after operation.
+ * @throws GLException if resize operation failed
+ */
+ void resetSize(GL gl) throws GLException;
+
+ /**
+ * @return the used texture unit
+ */
+ int getTextureUnit();
+
+ /**
+ *
+ * @param unit the texture unit to be used
+ */
+ void setTextureUnit(int unit);
+
+ /**
+ * Set a new sample size
+ * @param gl GL context object bound to this drawable, will be made current during operation.
+ * A prev. current context will be make current after operation.
+ * @param newSamples new sample size
+ * @throws GLException if resetting the FBO failed
+ */
+ void setNumSamples(GL gl, int newSamples) throws GLException;
+
+ /**
+ * @return the number of sample buffers if using MSAA, otherwise 0
+ */
+ int getNumSamples();
+
+ /**
+ * @return the used {@link DoubleBufferMode}
+ */
+ // DoubleBufferMode getDoubleBufferMode(); // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+
+ /**
+ * Sets the {@link DoubleBufferMode}. Must be called before {@link #isInitialized() initialization},
+ * otherwise an exception is thrown.
+ * + * This call has no effect is MSAA is selected, since MSAA always forces the mode to {@link DoubleBufferMode#FBO FBO}. + * Also setting the mode to {@link DoubleBufferMode#NONE NONE} where double buffering is {@link GLCapabilitiesImmutable#getDoubleBuffered() requested} + * or setting a double buffering mode w/o {@link GLCapabilitiesImmutable#getDoubleBuffered() request} will be ignored. + *
+ *+ * Since {@link DoubleBufferMode#TEXTURE TEXTURE} mode is currently not implemented, this method has no effect. + *
+ * @throws GLException if already initialized, see {@link #isInitialized()}. + */ + // void setDoubleBufferMode(DoubleBufferMode mode) throws GLException; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * If MSAA is being used and {@link GL#GL_FRONT} is requested, + * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned. + * + * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link FBObject} + * @throws IllegalArgumentException if an illegal buffer name is being used + */ + FBObject getFBObject(int bufferName) throws IllegalArgumentException; + + /** + * Returns the named texture buffer. + *+ * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible + * and an exception is being thrown if {@link GL#GL_BACK} is being requested. + *
+ * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link TextureAttachment} + * @throws IllegalArgumentException if using MSAA and {@link GL#GL_BACK} is requested or an illegal buffer name is being used + */ + FBObject.TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException; + + /** Resizeable {@link GLFBODrawable} specialization */ + public interface Resizeable extends GLFBODrawable { + /** + * Resize this drawable. + *+ * This drawable is being locked during operation. + *
+ * @param context the {@link GLContext} bound to this drawable, will be made current during operation + * A prev. current context will be make current after operation. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case an error during the resize operation occurred + */ + void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException; + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java new file mode 100644 index 000000000..6fe76a3f4 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java @@ -0,0 +1,63 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; + +/** + * Platform-independent {@link GLAutoDrawable} specialization, + * exposing offscreen functionality. + *+ * This class distinguishes itself from {@link GLAutoDrawable} + * with it's {@link #setSize(int, int)} functionality. + *
+ */ +public interface GLOffscreenAutoDrawable extends GLAutoDrawable { + + /** + * Resize this auto drawable. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case of an error during the resize operation + */ + void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException; + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + void setUpstreamWidget(Object newUpstreamWidget); + + /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */ + public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable { + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java index 273a992cf..de7731a3b 100644 --- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java +++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java @@ -45,7 +45,11 @@ package javax.media.opengl; contains experimental methods for accessing the pbuffer's contents as a texture map and enabling rendering to floating-point frame buffers. These methods are not guaranteed to be supported on all - platforms and may be deprecated in a future release. */ + platforms and may be deprecated in a future release. + + @deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)} + via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}. + */ public interface GLPbuffer extends GLAutoDrawable { /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */ diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 033591fe3..329cf9e3f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -98,6 +98,7 @@ import jogamp.common.awt.AWTEDTExecutor; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; +import jogamp.opengl.GLDrawableImpl; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their // context whenever the displayChanged() function is called on our @@ -109,6 +110,16 @@ import jogamp.opengl.GLDrawableHelper; interfaces when adding a heavyweight doesn't work either because of Z-ordering or LayoutManager problems. * + *
+ * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
+ * is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is false
.
+ *
- - Overrides: -
paint
in class java.awt.Component
Overridden to track when this component is removed from a @@ -620,22 +637,37 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { - super.reshape(x, y, width, height); - final GLDrawable _drawable = drawable; - if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) { - dispose(true); - } else { - sendReshape = true; + synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape + super.reshape(x, y, width, height); + + GLDrawableImpl _drawable = drawable; + if( null != _drawable ) { + if(DEBUG) { + System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, width, height); + if(_drawable != _drawableNew) { + // write back + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } + } + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock + } } } - /** Overrides: -
update
in class java.awt.Component
reshape
in class java.awt.Component
true
if {@link AbstractGraphicsDevice#close()} shall be issued,
- * otherwise pass false
. Closing the device is required in case
- * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
- * and no further lifecycle handling is applied.
+ * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization
+ * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization
+ * @param ownsDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass false
. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
*/
- public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) {
+ public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownsDevice) {
this.drawable = drawable;
this.context = context;
- this.ownDevice = ownDevice;
+ this.ownsDevice = ownsDevice;
resetFPSCounter();
}
+ /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access. */
protected abstract RecursiveLock getLock();
- /** Returns the delegated GLDrawable */
- public final GLDrawable getDelegatedDrawable() { return drawable; }
-
/** Default implementation to handle repaint events from the windowing system */
protected final void defaultWindowRepaintOp() {
final GLDrawable _drawable = drawable;
@@ -103,29 +101,43 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
}
- /** Default implementation to handle resize events from the windowing system */
- protected final void defaultWindowResizedOp() {
- final GLDrawable _drawable = drawable;
+ /** Default implementation to handle resize events from the windowing system. All required locks are being claimed. */
+ protected final void defaultWindowResizedOp(int newWidth, int newHeight) throws NativeWindowException, GLException {
+ GLDrawableImpl _drawable = drawable;
if( null!=_drawable ) {
if(DEBUG) {
- System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+getWidth()+"x"+getHeight()+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ }
+ if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, newWidth, newHeight);
+ if(_drawable != _drawableNew) {
+ // write back
+ _drawable = _drawableNew;
+ drawable = _drawableNew;
+ }
+ } finally {
+ _lock.unlock();
+ }
}
sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
if( _drawable.isRealized() ) {
if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
display();
}
- }
+ }
}
}
-
+
/**
* Default implementation to handle destroy notifications from the windowing system.
*
* * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), - * {@link #defaultDestroy()} is being called. + * a thread safe destruction is being induced. *
*/ protected final void defaultWindowDestroyNotifyOp() { @@ -174,7 +186,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { ctrl.resume(); } } else if (null != ns && ns.isSurfaceLockedByOtherThread()) { - // surface is locked by another thread + // Surface is locked by another thread. // Flag that destroy should be performed on the next // attempt to display. sendDestroy = true; // async, but avoiding deadlock @@ -225,7 +237,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } _drawable.setRealized(false); } - if( ownDevice ) { + if( ownsDevice ) { _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close(); } } @@ -238,7 +250,6 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { _lock.lock(); try { if(drawable!=null && context != null) { - drawable.swapBuffers(); helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction); } } finally { @@ -276,7 +287,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { destroy(); return; } - final RecursiveLock _lock = getLock(); + final RecursiveLock _lock = getLock(); _lock.lock(); try { if( null != context ) { @@ -294,6 +305,11 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { drawable.swapBuffers(); } } ; + @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + @Override public final GLContext getContext() { return context; @@ -305,7 +321,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); @@ -529,4 +545,10 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { final GLDrawable _drawable = drawable; return null != _drawable ? _drawable.getHandle() : 0; } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + /** ", \n\tWindow: "+window+ ", \n\tFactory: "+factory+ */ "]"; + } } diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index e82756022..050c619fd 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -47,6 +47,7 @@ import java.util.Map; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.FunctionAddressResolver; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLNameResolver; @@ -85,6 +86,7 @@ public abstract class GLContextImpl extends GLContext { private String glRenderer; private String glRendererLowerCase; + private String glVersion; // Tracks creation and initialization of buffer objects to avoid // repeated glGet calls upon glMapBuffer operations @@ -126,6 +128,9 @@ public abstract class GLContextImpl extends GLContext { GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this); this.drawable = drawable; + if(null != drawable) { + drawable.associateContext(this, true); + } this.drawableRead = drawable; this.glDebugHandler = new GLDebugMessageHandler(this); @@ -205,8 +210,10 @@ public abstract class GLContextImpl extends GLContext { if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable drawableRead = (GLDrawableImpl) readWrite; } - final GLDrawable old = drawable; + final GLDrawableImpl old = drawable; + old.associateContext(this, false); drawable = (GLDrawableImpl) readWrite ; + drawable.associateContext(this, true); if(lockHeld) { makeCurrent(); } @@ -272,7 +279,7 @@ public abstract class GLContextImpl extends GLContext { if( actualRelease ) { if( !inDestruction ) { try { - drawable.contextMadeCurrent(this, false); + contextMadeCurrent(false); } catch (Throwable t) { drawableContextMadeCurrentException = t; } @@ -331,7 +338,8 @@ public abstract class GLContextImpl extends GLContext { makeCurrent(); } try { - drawable.contextRealized(this, false); + contextRealized(false); + drawable.associateContext(this, false); } catch (Throwable t) { drawableContextRealizedException = t; } @@ -514,19 +522,17 @@ public abstract class GLContextImpl extends GLContext { gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ); } - drawable.contextRealized(this, true); + contextRealized(true); if(DEBUG || TRACE_SWITCH) { System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT_NEW - "+lock); } - } else { - drawable.contextMadeCurrent(this, true); - - if(TRACE_SWITCH) { - System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); - } + } else if(TRACE_SWITCH) { + System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); } + contextMadeCurrent(true); + /* FIXME: refactor dependence on Java 2D / JOGL bridge // Try cleaning up any stale server-side OpenGL objects @@ -608,6 +614,20 @@ public abstract class GLContextImpl extends GLContext { } protected abstract void makeCurrentImpl() throws GLException; + /** + * @see GLDrawableImpl#contextRealized(GLContext, boolean) + */ + protected void contextRealized(boolean realized) { + drawable.contextRealized(this, realized); + } + + /** + * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) + */ + protected void contextMadeCurrent(boolean current) { + drawable.contextMadeCurrent(this, current); + } + /** * Platform dependent entry point for context creation.device
instance is used as-is.
* @param requestedCaps
* @param chooser the custom chooser, may be null for default
- * @param width the initial width
- * @param height the initial height
- * @return the created {@link MutableSurface} instance w/o defined surface handle
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()}, not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()}, not the actual dummy surface height,
+ * The latter is platform specific and small
+ * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}.
*/
public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 090c5fe69..bdf0b6d74 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -43,12 +43,19 @@ package jogamp.opengl;
import java.util.ArrayList;
import java.util.HashSet;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLFBODrawable;
import javax.media.opengl.GLRunnable;
import com.jogamp.opengl.util.Animator;
@@ -108,24 +115,27 @@ public class GLDrawableHelper {
/**
* Associate a new context to the drawable and also propagates the context/drawable switch by
* calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- * - * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - *
** If the old or new context was current on this thread, it is being released before switching the drawable. *
+ *+ * Be aware that the old context is still bound to the drawable, + * and that one context can only bound to one drawable at one time! + *
+ *+ * No locking is being performed on the drawable, caller is required to take care of it. + *
* * @param drawable the drawable which context is changed - * @param newCtx the new context * @param oldCtx the old context - * @return true if the newt context was current, otherwise false + * @param newCtx the new context + * @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)} + * @return true if the new context was current, otherwise false * * @see GLAutoDrawable#setContext(GLContext) */ - public final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int additionalCtxCreationFlags) { - if(null != oldCtx && oldCtx.isCurrent()) { + public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) { + if( null != oldCtx && oldCtx.isCurrent() ) { oldCtx.release(); } final boolean newCtxCurrent; @@ -134,17 +144,135 @@ public class GLDrawableHelper { if(newCtxCurrent) { newCtx.release(); } - newCtx.setContextCreationFlags(additionalCtxCreationFlags); + newCtx.setContextCreationFlags(newCtxCreationFlags); newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch } else { newCtxCurrent = false; } - if(null!=oldCtx && oldCtx.getGLDrawable() instanceof GLAutoDrawable) { - ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null); - } return newCtxCurrent; } + /** + * If the drawable is not realized, OP is a NOP. + *+ * No locking is being performed, caller is required to take care of it. + *
+ * + * @param drawable + * @param context maybe null + * @return the new drawable + */ + public static final GLDrawableImpl recreateGLDrawable(GLDrawableImpl drawable, GLContext context) { + if( ! drawable.isRealized() ) { + return drawable; + } + final boolean contextCurrent = null != context && context.isCurrent(); + final GLDrawableFactory factory = drawable.getFactory(); + final NativeSurface surface = drawable.getNativeSurface(); + final ProxySurface proxySurface = (surface instanceof ProxySurface) ? (ProxySurface)surface : null; + + if(contextCurrent) { + context.release(); + } + + if(null != proxySurface) { + proxySurface.enableUpstreamSurfaceHookLifecycle(false); + } + try { + drawable.setRealized(false); + drawable = (GLDrawableImpl) factory.createGLDrawable(surface); // [2] + drawable.setRealized(true); + } finally { + if(null != proxySurface) { + proxySurface.enableUpstreamSurfaceHookLifecycle(true); + } + } + + if(null != context) { + context.setGLDrawable(drawable, true); // re-association + } + + if(contextCurrent) { + context.makeCurrent(); + } + return drawable; + } + + /** + * Performs resize operation on the given drawable, assuming it is offscreen. + *+ * The {@link GLDrawableImpl}'s {@link NativeSurface} is being locked during operation. + * In case the holder is an auto drawable or similar, it's lock shall be claimed by the caller. + *
+ *+ * May recreate the drawable via {@link #recreateGLDrawable(GLDrawableImpl, GLContext)} + * in case of a a pbuffer- or pixmap-drawable. + *
+ *+ * FBO drawables are resized w/o drawable destruction. + *
+ *+ * Offscreen resize operation is validated w/ drawable size in the end. + * An exception is thrown if not successful. + *
+ * + * @param drawable + * @param context + * @param newWidth the new width, it's minimum is capped to 1 + * @param newHeight the new height, it's minimum is capped to 1 + * @return the new drawable in case of an pbuffer/pixmap drawable, otherwise the passed drawable is being returned. + * @throws NativeWindowException is drawable is not offscreen or it's surface lock couldn't be claimed + * @throws GLException may be thrown a resize operation + */ + public static final GLDrawableImpl resizeOffscreenDrawable(GLDrawableImpl drawable, GLContext context, int newWidth, int newHeight) + throws NativeWindowException, GLException + { + if(drawable.getChosenGLCapabilities().isOnscreen()) { + throw new NativeWindowException("Drawable is not offscreen: "+drawable); + } + final NativeSurface ns = drawable.getNativeSurface(); + final int lockRes = ns.lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + throw new NativeWindowException("Could not lock surface of drawable: "+drawable); + } + try { + if(0>=newWidth) { newWidth = 1; } + if(0>=newHeight) { newHeight = 1; } + // propagate new size + if(ns instanceof ProxySurface) { + final ProxySurface ps = (ProxySurface) ns; + final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight); + } else if(DEBUG) { // we have to assume UpstreamSurfaceHook contains the new size already, hence size check @ bottom + System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen ProxySurface n.a. UpstreamSurfaceHook.MutableSize, but "+ush.getClass().getName()+": "+ush); + } + } else if(DEBUG) { // we have to assume surface contains the new size already, hence size check @ bottom + System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen surface n.a. ProxySurface, but "+ns.getClass().getName()+": "+ns); + } + if(drawable instanceof GLFBODrawable) { + if( null != context && context.isCreated() ) { + ((GLFBODrawable) drawable).resetSize(context.getGL()); + } + } else { + drawable = GLDrawableHelper.recreateGLDrawable(drawable, context); + } + } finally { + ns.unlockSurface(); + } + if(drawable.getWidth() != newWidth || drawable.getHeight() != newHeight) { + throw new InternalError("Incomplete resize operation: expected "+newWidth+"x"+newHeight+", has: "+drawable); + } + return drawable; + } + public final void addGLEventListener(GLEventListener listener) { addGLEventListener(-1, listener); } @@ -196,15 +324,11 @@ public class GLDrawableHelper { } } - private final boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { - if(listenersToBeInit.remove(l)) { - l.init(drawable); - if(sendReshape) { - reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */); - } - return true; + private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { + l.init(drawable); + if(sendReshape) { + reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */); } - return false; } /** The default init action to be called once after ctx is being created @ 1st makeCurrent(). */ @@ -214,14 +338,11 @@ public class GLDrawableHelper { for (int i=0; i < _listeners.size(); i++) { final GLEventListener listener = _listeners.get(i) ; - // If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called. + // If make ctx current, invoked by invokGL(..), results in a new ctx, init gets called. // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window), - // hence the must always be initialized unconditional. - listenersToBeInit.add(listener); - - if ( ! init( listener, drawable, true /* sendReshape */) ) { - throw new GLException("GLEventListener "+listener+" already initialized: "+drawable); - } + // hence it must be called unconditional, always. + listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init + init( listener, drawable, true /* sendReshape */); } } } @@ -239,7 +360,9 @@ public class GLDrawableHelper { final GLEventListener listener = _listeners.get(i) ; // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable - init( listener, drawable, true /* sendReshape */) ; + if( listenersToBeInit.remove(listener) ) { + init( listener, drawable, true /* sendReshape */) ; + } listener.display(drawable); } } @@ -251,7 +374,9 @@ public class GLDrawableHelper { // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable synchronized(listenersLock) { - init( listener, drawable, false /* sendReshape */) ; + if( listenersToBeInit.remove(listener) ) { + init( listener, drawable, false /* sendReshape */) ; + } } } if(setViewport) { diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index abf2bf557..311690f1d 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -43,6 +43,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GL; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -76,31 +77,46 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); - if ( caps.getDoubleBuffered() ) { - if(!surface.surfaceSwap()) { - int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] - if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { - return; + int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] + if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { + return; + } + try { + if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { + updateHandle(); + } + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + if ( caps.getDoubleBuffered() ) { + if(!surface.surfaceSwap()) { + swapBuffersImpl(true); } - try { - if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { - updateHandle(); - } - swapBuffersImpl(); - } finally { - unlockSurface(); + } else { + final GLContext ctx = GLContext.getCurrent(); + if(null!=ctx && ctx.getGLDrawable()==this) { + ctx.getGL().glFlush(); } + swapBuffersImpl(false); } - } else { - GLContext ctx = GLContext.getCurrent(); - if(null!=ctx && ctx.getGLDrawable()==this) { - ctx.getGL().glFinish(); - } - } + } finally { + unlockSurface(); + } surface.surfaceUpdated(this, surface, System.currentTimeMillis()); } - protected abstract void swapBuffersImpl(); + + /** + * Platform and implementation depending surface swap. + *The surface is locked.
+ *
+ * If doubleBuffered
is true
,
+ * an actual platform dependent surface swap shall be executed.
+ *
+ * If doubleBuffered
is false
,
+ * {@link GL#glFlush()} has been called already and
+ * the implementation may execute implementation specific code.
+ *
realized
is true
, the context has just been created and made current.
*
*
- * If realized
is false
, the context is still current and will be release and destroyed after this method returns.
+ * If realized
is false
, the context is still current and will be released and destroyed after this method returns.
*
* @see #contextMadeCurrent(GLContext, boolean)
@@ -199,18 +218,27 @@ public abstract class GLDrawableImpl implements GLDrawable {
/**
* Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent
, release
.
*
- * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. - *
- *
* If current
is true
, the context has just been made current.
*
* If current
is false
, the context is still current and will be release after this method returns.
*
+ * Note: Will also be called after {@link #contextRealized(GLContext, boolean) contextRealized(ctx, true)} + * but not at context destruction, i.e. {@link #contextRealized(GLContext, boolean) contextRealized(ctx, false)}. + *
* @see #contextRealized(GLContext, boolean) */ protected void contextMadeCurrent(GLContext glc, boolean current) { } + /** + * Callback for special implementations, allowing to associate bound context to this drawable (bound == true) + * or to remove such association (bound == false). + * @param ctx the just bounded or unbounded context + * @param bound iftrue
create an association, otherwise remove it
+ */
+ protected void associateContext(GLContext ctx, boolean bound) { }
+
/** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/
protected int getDefaultDrawFramebuffer() { return 0; }
/** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
@@ -245,8 +273,8 @@ public abstract class GLDrawableImpl implements GLDrawable {
public String toString() {
return getClass().getSimpleName()+"[Realized "+isRealized()+
",\n\tFactory "+getFactory()+
- ",\n\thandle "+toHexString(getHandle())+
- ",\n\tWindow "+getNativeSurface()+"]";
+ ",\n\tHandle "+toHexString(getHandle())+
+ ",\n\tSurface "+getNativeSurface()+"]";
}
protected static String getThreadName() {
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index 03bc26cbc..de45466f3 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -1,142 +1,476 @@
package jogamp.opengl;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import javax.media.opengl.GL;
-import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLFBODrawable;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.Colorbuffer;
import com.jogamp.opengl.FBObject.TextureAttachment;
/**
- * Offscreen GLDrawable implementation using framebuffer object (FBO)
- * as it's offscreen rendering mechanism.
+ * {@link FBObject} offscreen GLDrawable implementation, i.e. {@link GLFBODrawable}.
+ * + * It utilizes the context lifecycle hook {@link #contextRealized(GLContext, boolean)} + * to initialize the {@link FBObject} instance. + *
+ *+ * It utilizes the context current hook {@link #contextMadeCurrent(GLContext, boolean) contextMadeCurrent(context, true)} + * to {@link FBObject#bind(GL) bind} the FBO. + *
+ * See {@link GLFBODrawable} for double buffering details. * * @see GLDrawableImpl#contextRealized(GLContext, boolean) * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) * @see GLDrawableImpl#getDefaultDrawFramebuffer() * @see GLDrawableImpl#getDefaultReadFramebuffer() */ -public class GLFBODrawableImpl extends GLDrawableImpl { - final GLDrawableImpl parent; - final FBObject fbo; - int texUnit; - int samplesTexUnit = 0; - int width=0, height=0, samples=0; - - protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, - NativeSurface surface, int initialWidth, int initialHeight, int textureUnit) { +public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { + protected static final boolean DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject"); + + private final GLDrawableImpl parent; + + private boolean initialized; + private int texUnit; + private int samples; + + private FBObject[] fbos; + private int fboIBack; // points to GL_BACK buffer + private int fboIFront; // points to GL_FRONT buffer + private FBObject pendingFBOReset = null; + private boolean fboBound; + private static final int bufferCount = 2; // number of FBOs for double buffering. TODO: Possible to configure! + + // private DoubleBufferMode doubleBufferMode; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + private SwapBufferContext swapBufferContext; + + public static interface SwapBufferContext { + public void swapBuffers(boolean doubleBuffered); + } + + protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, NativeSurface surface, + GLCapabilitiesImmutable fboCaps, int textureUnit) { super(factory, surface, false); + this.initialized = false; + + // Replace the chosen caps of dummy-surface w/ it's clone and copied values of orig FBO caps request. + // The dummy-surface has already been configured, hence value replace is OK + // and due to cloning, the native GLCapability portion is being preserved. + final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration(); + final GLCapabilities fboCapsNative = (GLCapabilities) msConfig.getChosenCapabilities().cloneMutable(); + fboCapsNative.copyFrom(fboCaps); + msConfig.setChosenCapabilities(fboCapsNative); + this.parent = parent; this.texUnit = textureUnit; - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); - this.width = initialWidth; - this.height = initialHeight; - this.samples = caps.getNumSamples(); - this.fbo = new FBObject(); + this.samples = fboCaps.getNumSamples(); + + // default .. // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + // this.doubleBufferMode = ( samples > 0 || fboCaps.getDoubleBuffered() ) ? DoubleBufferMode.FBO : DoubleBufferMode.NONE ; + + this.swapBufferContext = null; } - @Override - protected void contextRealized(GLContext glc, boolean realized) { - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); - final GL gl = glc.getGL(); - if(realized) { - fbo.reset(gl, width, height, samples); - samples = fbo.getNumSamples(); // update, maybe capped + private final void initialize(boolean realize, GL gl) { + if(realize) { + final int maxSamples = gl.getMaxRenderbufferSamples(); + samples = samples <= maxSamples ? samples : maxSamples; + + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); + final int fbosN; if(samples > 0) { - fbo.attachColorbuffer(gl, 0, caps.getAlphaBits()>0); + fbosN = 1; + } else if( caps.getDoubleBuffered() ) { + fbosN = bufferCount; } else { - fbo.attachTexture2D(gl, 0, caps.getAlphaBits()>0); + fbosN = 1; } - if( caps.getStencilBits() > 0 ) { - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24); - } else { - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); + + fbos = new FBObject[fbosN]; + fboIBack = 0; // head + fboIFront = fbos.length - 1; // tail + + for(int i=0; i+ * The implementation may itself apply the swapping, * in which case true shall be returned. + *
* * @return true if this method completed swapping the surface, * otherwise false, in which case eg the GLDrawable diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java index f7dbc6c27..f9800109c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -50,4 +50,7 @@ public interface OffscreenLayerSurface { /** Returns true if a surface layer is attached, otherwise false. */ public boolean isSurfaceLayerAttached(); + /** Sets the capabilities of this instance, allowing upstream API's to refine it, i.e. OpenGL related settings. */ + public void setChosenCapabilities(CapabilitiesImmutable caps); + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 7fc9789c2..395fdc818 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2012 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -29,242 +29,82 @@ package javax.media.nativewindow; import jogamp.nativewindow.Debug; -import jogamp.nativewindow.SurfaceUpdatedHelper; -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -public abstract class ProxySurface implements NativeSurface, MutableSurface { +/** + * Provides a mutable {@link NativeSurface}, i.e. {@link MutableSurface}, while allowing an + * {@link UpstreamSurfaceHook} to influence the lifecycle and information. + * + * @see UpstreamSurfaceHook + * @see MutableSurface + * @see NativeSurface + */ +public interface ProxySurface extends MutableSurface { public static final boolean DEBUG = Debug.debug("ProxySurface"); /** - * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}. - * @see #setImplBitfield(int) - * @see #getImplBitfield() + * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's surface handle + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() */ - public static final int OWN_DEVICE = 1 << 7; + public static final int OPT_PROXY_OWNS_UPSTREAM_SURFACE = 1 << 6; + + /** + * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's {@link AbstractGraphicsDevice}. + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() + */ + public static final int OPT_PROXY_OWNS_UPSTREAM_DEVICE = 1 << 7; /** * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete. - * @see #setImplBitfield(int) - * @see #getImplBitfield() + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() */ - public static final int INVISIBLE_WINDOW = 1 << 8; + public static final int OPT_UPSTREAM_WINDOW_INVISIBLE = 1 << 8; - /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */ - public interface UpstreamSurfaceHook { - /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */ - public void create(ProxySurface s); - /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */ - public void destroy(ProxySurface s); + /** Allow redefining the AbstractGraphicsConfiguration */ + public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg); - /** Returns the width of the upstream surface */ - public int getWidth(ProxySurface s); - /** Returns the height of the upstream surface */ - public int getHeight(ProxySurface s); - } + /** Returns the set {@link UpstreamSurfaceHook}, or null if not set. */ + public UpstreamSurfaceHook getUpstreamSurfaceHook(); - private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - private final AbstractGraphicsConfiguration config; // control access due to delegation - private final UpstreamSurfaceHook upstream; - public final int initialWidth; - public final int initialHeight; - private long surfaceHandle_old; - protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); - protected long displayHandle; - protected int scrnIndex; - protected int implBitfield; - /** - * @param cfg the {@link AbstractGraphicsConfiguration} to be used - * @param initialWidth the initial width - * @param initialHeight the initial height + * Sets the {@link UpstreamSurfaceHook} and returns the previous value. */ - protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { - if(null == cfg) { - throw new IllegalArgumentException("null config"); - } - this.config = cfg; - this.upstream = upstream; - this.initialWidth = initialWidth; - this.initialHeight = initialHeight; - this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - this.surfaceHandle_old = 0; - this.implBitfield = 0; - } - - public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook); + + /** + * Enables or disables the {@link UpstreamSurfaceHook} lifecycle functions + * {@link UpstreamSurfaceHook#create(ProxySurface)} and {@link UpstreamSurfaceHook#destroy(ProxySurface)}. + *+ * Use this for small code blocks where the native resources shall not change, + * i.e. resizing a derived (OpenGL) drawable. + *
+ */ + public void enableUpstreamSurfaceHookLifecycle(boolean enable); /** - * If a valid {@link UpstreamSurfaceHook} instance is passed in the - * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set. */ - public void createNotify() { - if(null != upstream) { - upstream.create(this); - } - this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - this.surfaceHandle_old = 0; - } + public void createNotify(); /** - * If a valid {@link UpstreamSurfaceHook} instance is passed in the - * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, - * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared. + * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all proxy surface/window handles shall be cleared. */ - public void destroyNotify() { - if(null != upstream) { - upstream.destroy(this); - invalidateImpl(); - } - this.displayHandle = 0; - this.surfaceHandle_old = 0; - } + public void destroyNotify(); - /** - * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. - * @see #destroyNotify() - */ - protected void invalidateImpl() { - throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); - } + public StringBuilder getUpstreamOptionBits(StringBuilder sink); + public int getUpstreamOptionBits(); - @Override - public final long getDisplayHandle() { - return displayHandle; - } - - protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() { - return config; - } - - @Override - public final AbstractGraphicsConfiguration getGraphicsConfiguration() { - return config.getNativeGraphicsConfiguration(); - } - - @Override - public final int getScreenIndex() { - return getGraphicsConfiguration().getScreen().getIndex(); - } - - @Override - public abstract long getSurfaceHandle(); - - @Override - public abstract void setSurfaceHandle(long surfaceHandle); + /** Returnstrue
if the give bit-mask v
is set in this instance upstream-option-bits, otherwise false
.*/
+ public boolean containsUpstreamOptionBits(int v);
- @Override
- public final int getWidth() {
- if(null != upstream) {
- return upstream.getWidth(this);
- }
- return initialWidth;
- }
-
- @Override
- public final int getHeight() {
- if(null != upstream) {
- return upstream.getHeight(this);
- }
- return initialHeight;
- }
-
- @Override
- public boolean surfaceSwap() {
- return false;
- }
-
- @Override
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
- }
-
- @Override
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
- }
-
- @Override
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
- }
-
- @Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
- }
-
- @Override
- public int lockSurface() throws NativeWindowException, RuntimeException {
- surfaceLock.lock();
- int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
-
- if ( LOCK_SURFACE_NOT_READY == res ) {
- try {
- final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
- adevice.lock();
- try {
- res = lockSurfaceImpl();
- if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) {
- res = LOCK_SURFACE_CHANGED;
- if(DEBUG) {
- System.err.println("ProxySurface: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle()));
- // Thread.dumpStack();
- }
- }
- } finally {
- if (LOCK_SURFACE_NOT_READY >= res) {
- adevice.unlock();
- }
- }
- } finally {
- if (LOCK_SURFACE_NOT_READY >= res) {
- surfaceLock.unlock();
- }
- }
- }
- return res;
- }
-
- @Override
- public final void unlockSurface() {
- surfaceLock.validateLocked();
- surfaceHandle_old = getSurfaceHandle();
-
- if (surfaceLock.getHoldCount() == 1) {
- final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
- try {
- unlockSurfaceImpl();
- } finally {
- adevice.unlock();
- }
- }
- surfaceLock.unlock();
- }
-
- protected abstract int lockSurfaceImpl();
-
- protected abstract void unlockSurfaceImpl() ;
-
- public final void validateSurfaceLocked() {
- surfaceLock.validateLocked();
- }
-
- @Override
- public final boolean isSurfaceLockedByOtherThread() {
- return surfaceLock.isLockedByOtherThread();
- }
-
- @Override
- public final Thread getSurfaceLockOwner() {
- return surfaceLock.getOwner();
- }
+ /** Add the given bit-mask to this instance upstream-option-bits using bit-or w/ v
.*/
+ public void addUpstreamOptionBits(int v);
- @Override
- public abstract String toString();
+ /** Clear the given bit-mask from this instance upstream-option-bits using bit-and w/ ~v
*/
+ public void clearUpstreamOptionBits(int v);
- public int getImplBitfield() { return implBitfield; }
- public void setImplBitfield(int v) { implBitfield=v; }
+ public StringBuilder toString(StringBuilder sink);
+ public String toString();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java
new file mode 100644
index 000000000..6fe2e5364
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow;
+
+/**
+ * Interface allowing upstream caller to pass lifecycle actions and size info
+ * to a {@link ProxySurface} instance.
+ */
+public interface UpstreamSurfaceHook {
+ /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */
+ public void create(ProxySurface s);
+ /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */
+ public void destroy(ProxySurface s);
+
+ /** Returns the width of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
+ public int getWidth(ProxySurface s);
+ /** Returns the height of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
+ public int getHeight(ProxySurface s);
+
+ /**
+ * {@link UpstreamSurfaceHook} w/ mutable size, allowing it's {@link ProxySurface} user to resize.
+ */
+ public interface MutableSize extends UpstreamSurfaceHook {
+ public void setSize(int width, int height);
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
new file mode 100644
index 000000000..63f56cbae
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
@@ -0,0 +1,326 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.SurfaceUpdatedListener;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+public abstract class ProxySurfaceImpl implements ProxySurface {
+ private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+ protected long displayHandle; // convenient ref of config.screen.device.handle
+ private AbstractGraphicsConfiguration config; // control access due to delegation
+ private UpstreamSurfaceHook upstream;
+ private long surfaceHandle_old;
+ private RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ private int implBitfield;
+ private boolean upstreamSurfaceHookLifecycleEnabled;
+
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param upstream the {@link UpstreamSurfaceHook} to be used
+ * @param ownsDevice true
if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise false
. Owning the device implies closing it at {@link #destroyNotify()}.
+ */
+ protected ProxySurfaceImpl(AbstractGraphicsConfiguration cfg, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ if(null == cfg) {
+ throw new IllegalArgumentException("null AbstractGraphicsConfiguration");
+ }
+ if(null == upstream) {
+ throw new IllegalArgumentException("null UpstreamSurfaceHook");
+ }
+ this.config = cfg;
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.upstream = upstream;
+ this.surfaceHandle_old = 0;
+ this.implBitfield = 0;
+ this.upstreamSurfaceHookLifecycleEnabled = true;
+ if(ownsDevice) {
+ addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ }
+
+ @Override
+ public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
+
+ @Override
+ public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook) {
+ if(null == hook) {
+ throw new IllegalArgumentException("null UpstreamSurfaceHook");
+ }
+ upstream = hook;
+ }
+
+ @Override
+ public final void enableUpstreamSurfaceHookLifecycle(boolean enable) {
+ upstreamSurfaceHookLifecycleEnabled = enable;
+ }
+
+ @Override
+ public void createNotify() {
+ if(upstreamSurfaceHookLifecycleEnabled) {
+ upstream.create(this);
+ }
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.surfaceHandle_old = 0;
+ }
+
+ @Override
+ public void destroyNotify() {
+ if(upstreamSurfaceHookLifecycleEnabled) {
+ upstream.destroy(this);
+ if( containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ) ) {
+ final AbstractGraphicsDevice aDevice = getGraphicsConfiguration().getScreen().getDevice();
+ aDevice.close();
+ clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ invalidateImpl();
+ }
+ this.displayHandle = 0;
+ this.surfaceHandle_old = 0;
+ }
+
+ /**
+ * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed.
+ * @see #destroyNotify()
+ */
+ protected void invalidateImpl() {
+ throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
+ }
+
+ @Override
+ public final long getDisplayHandle() {
+ return displayHandle;
+ }
+
+ protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() {
+ return config;
+ }
+
+ @Override
+ public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
+ return config.getNativeGraphicsConfiguration();
+ }
+
+ @Override
+ public final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
+ config = cfg;
+ }
+
+ @Override
+ public final int getScreenIndex() {
+ return getGraphicsConfiguration().getScreen().getIndex();
+ }
+
+ @Override
+ public abstract long getSurfaceHandle();
+
+ @Override
+ public abstract void setSurfaceHandle(long surfaceHandle);
+
+ @Override
+ public final int getWidth() {
+ return upstream.getWidth(this);
+ }
+
+ @Override
+ public final int getHeight() {
+ return upstream.getHeight(this);
+ }
+
+ @Override
+ public boolean surfaceSwap() {
+ return false;
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ }
+
+ @Override
+ public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+ }
+
+ @Override
+ public int lockSurface() throws NativeWindowException, RuntimeException {
+ surfaceLock.lock();
+ int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
+
+ if ( LOCK_SURFACE_NOT_READY == res ) {
+ try {
+ final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+ adevice.lock();
+ try {
+ res = lockSurfaceImpl();
+ if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) {
+ res = LOCK_SURFACE_CHANGED;
+ if(DEBUG) {
+ System.err.println("ProxySurfaceImpl: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle()));
+ // Thread.dumpStack();
+ }
+ }
+ } finally {
+ if (LOCK_SURFACE_NOT_READY >= res) {
+ adevice.unlock();
+ }
+ }
+ } finally {
+ if (LOCK_SURFACE_NOT_READY >= res) {
+ surfaceLock.unlock();
+ }
+ }
+ }
+ return res;
+ }
+
+ @Override
+ public final void unlockSurface() {
+ surfaceLock.validateLocked();
+ surfaceHandle_old = getSurfaceHandle();
+
+ if (surfaceLock.getHoldCount() == 1) {
+ final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+ try {
+ unlockSurfaceImpl();
+ } finally {
+ adevice.unlock();
+ }
+ }
+ surfaceLock.unlock();
+ }
+
+ protected abstract int lockSurfaceImpl();
+
+ protected abstract void unlockSurfaceImpl() ;
+
+ public final void validateSurfaceLocked() {
+ surfaceLock.validateLocked();
+ }
+
+ @Override
+ public final boolean isSurfaceLockedByOtherThread() {
+ return surfaceLock.isLockedByOtherThread();
+ }
+
+ @Override
+ public final Thread getSurfaceLockOwner() {
+ return surfaceLock.getOwner();
+ }
+
+ public final StringBuilder getUpstreamOptionBits(StringBuilder sink) {
+ if(null == sink) {
+ sink = new StringBuilder();
+ }
+ sink.append("UOB[ ");
+ if(0 == implBitfield) {
+ sink.append("]");
+ return sink;
+ }
+ boolean needsOr = false;
+ if( 0 != ( implBitfield & OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ sink.append("OWNS_SURFACE");
+ needsOr = true;
+ }
+ if( 0 != ( implBitfield & OPT_PROXY_OWNS_UPSTREAM_DEVICE ) ) {
+ if(needsOr) {
+ sink.append(" | ");
+ }
+ sink.append("OWNS_DEVICE");
+ needsOr = true;
+ }
+ if( 0 != ( implBitfield & OPT_UPSTREAM_WINDOW_INVISIBLE ) ) {
+ if(needsOr) {
+ sink.append(" | ");
+ }
+ sink.append("WINDOW_INVISIBLE");
+ needsOr = true;
+ }
+ sink.append(" ]");
+ return sink;
+ }
+
+ @Override
+ public final int getUpstreamOptionBits() { return implBitfield; }
+
+ @Override
+ public final boolean containsUpstreamOptionBits(int v) {
+ return v == ( implBitfield & v ) ;
+ }
+
+ @Override
+ public final void addUpstreamOptionBits(int v) { implBitfield |= v; }
+
+ @Override
+ public final void clearUpstreamOptionBits(int v) { implBitfield &= ~v; }
+
+ @Override
+ public StringBuilder toString(StringBuilder sink) {
+ if(null == sink) {
+ sink = new StringBuilder();
+ }
+ sink.append(getUpstreamSurfaceHook()).
+ append(", displayHandle 0x" + Long.toHexString(getDisplayHandle())).
+ append(", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())).
+ append(", size " + getWidth() + "x" + getHeight()).append(", ");
+ getUpstreamOptionBits(sink);
+ sink.append(", surfaceLock "+surfaceLock);
+ return sink;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder msg = new StringBuilder();
+ msg.append(getClass().getSimpleName()).append("[ ");
+ toString(msg);
+ msg.append(" ]");
+ return msg.toString();
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
new file mode 100644
index 000000000..e544bc61a
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+
+public class WrappedSurface extends ProxySurfaceImpl {
+ protected long surfaceHandle;
+
+ /**
+ * Utilizes a {@link UpstreamSurfaceHook.MutableSize} to hold the size information,
+ * which is being passed to the {@link ProxySurface} instance.
+ *
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
+ * @param initialWidth
+ * @param initialHeight
+ * @param ownsDevice true
if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise false
. Owning the device implies closing it at {@link #destroyNotify()}.
+ */
+ public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, boolean ownsDevice) {
+ super(cfg, new UpstreamSurfaceHookMutableSize(initialWidth, initialHeight), ownsDevice);
+ surfaceHandle=handle;
+ }
+
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
+ * @param upstream the {@link UpstreamSurfaceHook} to be used
+ * @param ownsDevice true
if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise false
.
+ */
+ public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ super(cfg, upstream, ownsDevice);
+ surfaceHandle=handle;
+ }
+
+ @Override
+ protected void invalidateImpl() {
+ surfaceHandle = 0;
+ }
+
+ @Override
+ public final long getSurfaceHandle() {
+ return surfaceHandle;
+ }
+
+ @Override
+ public final void setSurfaceHandle(long surfaceHandle) {
+ this.surfaceHandle=surfaceHandle;
+ }
+
+ @Override
+ protected final int lockSurfaceImpl() {
+ return LOCK_SUCCESS;
+ }
+
+ @Override
+ protected final void unlockSurfaceImpl() {
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index e81d61e0f..5fd242247 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -51,7 +51,6 @@ import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.util.Point;
-import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.nativewindow.awt.JAWTWindow;
import jogamp.nativewindow.jawt.JAWT;
@@ -71,17 +70,18 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
}
protected void invalidateNative() {
- surfaceHandle=0;
+ offscreenSurfaceHandle=0;
+ offscreenSurfaceHandleSet=false;
if(isOffscreenLayerSurfaceEnabled()) {
if(0 != rootSurfaceLayerHandle) {
OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
rootSurfaceLayerHandle = 0;
}
- if(0 != drawable) {
- OSXUtil.DestroyNSWindow(drawable);
- drawable = 0;
+ if(0 != windowHandle) {
+ OSXUtil.DestroyNSWindow(windowHandle);
}
}
+ windowHandle=0;
}
protected void attachSurfaceLayerImpl(final long layerHandle) {
@@ -92,8 +92,14 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle);
}
- public long getSurfaceHandle() {
- return isOffscreenLayerSurfaceEnabled() ? surfaceHandle : super.getSurfaceHandle() ;
+ @Override
+ public final long getWindowHandle() {
+ return windowHandle;
+ }
+
+ @Override
+ public final long getSurfaceHandle() {
+ return offscreenSurfaceHandleSet ? offscreenSurfaceHandle : drawable /* super.getSurfaceHandle() */ ;
}
public void setSurfaceHandle(long surfaceHandle) {
@@ -103,7 +109,8 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
if(DEBUG) {
System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
}
- this.surfaceHandle = surfaceHandle;
+ this.offscreenSurfaceHandle = surfaceHandle;
+ this.offscreenSurfaceHandleSet = true;
}
protected JAWT fetchJAWTImpl() throws NativeWindowException {
@@ -167,6 +174,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
unlockSurfaceImpl();
return NativeWindow.LOCK_SURFACE_NOT_READY;
} else {
+ windowHandle = OSXUtil.GetNSWindow(drawable);
ret = NativeWindow.LOCK_SUCCESS;
}
} else {
@@ -177,36 +185,46 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
* The actual surface/ca-layer shall be created/attached
* by the upper framework (JOGL) since they require more information.
*/
+ String errMsg = null;
if(0 == drawable) {
- drawable = OSXUtil.CreateNSWindow(0, 0, getBounds().getWidth(), getBounds().getHeight());
- if(0 == drawable) {
- unlockSurfaceImpl();
- throw new NativeWindowException("Unable to created dummy NSWindow (layered case)");
+ windowHandle = OSXUtil.CreateNSWindow(0, 0, 64, 64);
+ if(0 == windowHandle) {
+ errMsg = "Unable to create dummy NSWindow (layered case)";
+ } else {
+ drawable = OSXUtil.GetNSView(windowHandle);
+ if(0 == drawable) {
+ errMsg = "Null NSView of NSWindow 0x"+Long.toHexString(windowHandle);
+ }
+ }
+ if(null == errMsg) {
+ // fix caps reflecting offscreen! (no GL available here ..)
+ Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
+ caps.setOnscreen(false);
+ setChosenCapabilities(caps);
}
- // fix caps reflecting offscreen!
- Capabilities caps = (Capabilities) getPrivateGraphicsConfiguration().getChosenCapabilities().cloneMutable();
- caps.setOnscreen(false);
- getPrivateGraphicsConfiguration().setChosenCapabilities(caps);
- caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
- caps.setOnscreen(false);
- ((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps);
}
- if(0 == rootSurfaceLayerHandle) {
- rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
- if(0 == rootSurfaceLayerHandle) {
- OSXUtil.DestroyNSWindow(drawable);
- drawable = 0;
- unlockSurfaceImpl();
- throw new NativeWindowException("Could not create root CALayer: "+this);
+ if(null == errMsg) {
+ if(0 == rootSurfaceLayerHandle) {
+ rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
+ if(0 == rootSurfaceLayerHandle) {
+ errMsg = "Could not create root CALayer";
+ } else if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) {
+ errMsg = "Could not set JAWT rootSurfaceLayerHandle 0x"+Long.toHexString(rootSurfaceLayerHandle);
+ }
}
- if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) {
+ }
+ if(null != errMsg) {
+ if(0 != rootSurfaceLayerHandle) {
OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
rootSurfaceLayerHandle = 0;
- OSXUtil.DestroyNSWindow(drawable);
- drawable = 0;
- unlockSurfaceImpl();
- throw new NativeWindowException("Could not set JAWT rootSurfaceLayerHandle: "+this);
}
+ if(0 != windowHandle) {
+ OSXUtil.DestroyNSWindow(windowHandle);
+ windowHandle = 0;
+ }
+ drawable = 0;
+ unlockSurfaceImpl();
+ throw new NativeWindowException(errMsg+": "+this);
}
ret = NativeWindow.LOCK_SUCCESS;
}
@@ -264,7 +282,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer
- private long surfaceHandle = 0;
+ private long windowHandle = 0;
+ private long offscreenSurfaceHandle = 0;
+ private boolean offscreenSurfaceHandleSet = false;
// Workaround for instance of 4796548
private boolean firstLock = true;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
new file mode 100644
index 000000000..de3206c0c
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
@@ -0,0 +1,56 @@
+package jogamp.nativewindow.macosx;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+
+public class OSXDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
+ long nsWindow;
+
+ /**
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
+ * not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public OSXDummyUpstreamSurfaceHook(int width, int height) {
+ super(width, height);
+ nsWindow = 0;
+ }
+
+ @Override
+ public final void create(ProxySurface s) {
+ if(0 == nsWindow && 0 == s.getSurfaceHandle()) {
+ nsWindow = OSXUtil.CreateNSWindow(0, 0, 64, 64);
+ if(0 == nsWindow) {
+ throw new NativeWindowException("Error NS window 0");
+ }
+ long nsView = OSXUtil.GetNSView(nsWindow);
+ if(0 == nsView) {
+ throw new NativeWindowException("Error NS view 0");
+ }
+ s.setSurfaceHandle(nsView);
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ }
+
+ @Override
+ public final void destroy(ProxySurface s) {
+ if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ if( 0 == nsWindow || 0 == s.getSurfaceHandle() ) {
+ throw new InternalError("Owns upstream surface, but no OSX view/window: "+s+", nsWindow 0x"+Long.toHexString(nsWindow));
+ }
+ OSXUtil.DestroyNSWindow(nsWindow);
+ nsWindow = 0;
+ s.setSurfaceHandle(0);
+ s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index 149ebdf4a..b7a83e133 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -72,6 +72,10 @@ public class OSXUtil {
return isNSView0(object);
}
+ public static boolean isNSWindow(long object) {
+ return isNSWindow0(object);
+ }
+
/**
* In case the windowOrView
is top-level,
* you shall set topLevel
to true where
@@ -114,6 +118,9 @@ public class OSXUtil {
public static long GetNSView(long nsWindow) {
return GetNSView0(nsWindow);
}
+ public static long GetNSWindow(long nsView) {
+ return GetNSWindow0(nsView);
+ }
public static long CreateCALayer(int x, int y, int width, int height) {
return CreateCALayer0(x, y, width, height);
@@ -149,6 +156,11 @@ public class OSXUtil {
return IsMainThread0();
}
+ /** Returns the screen refresh rate in Hz. If unavailable, returns 60Hz. */
+ public static int GetScreenRefreshRate(int scrn_idx) {
+ return GetScreenRefreshRate0(scrn_idx);
+ }
+
/***
private static boolean isAWTEDTMainThreadInit = false;
private static boolean isAWTEDTMainThread;
@@ -172,15 +184,18 @@ public class OSXUtil {
private static native boolean initIDs0();
private static native boolean isNSView0(long object);
+ private static native boolean isNSWindow0(long object);
private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
private static native Object GetInsets0(long windowOrView);
private static native long CreateNSWindow0(int x, int y, int width, int height);
private static native void DestroyNSWindow0(long nsWindow);
private static native long GetNSView0(long nsWindow);
+ private static native long GetNSWindow0(long nsView);
private static native long CreateCALayer0(int x, int y, int width, int height);
private static native void AddCASublayer0(long rootCALayer, long subCALayer);
private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
private static native void DestroyCALayer0(long caLayer);
private static native void RunOnMainThread0(boolean waitUntilDone, Runnable runnable);
private static native boolean IsMainThread0();
+ private static native int GetScreenRefreshRate0(int scrn_idx);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
new file mode 100644
index 000000000..aa5f3dac5
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
@@ -0,0 +1,50 @@
+package jogamp.nativewindow.windows;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+
+public class GDIDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
+ /**
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
+ * not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public GDIDummyUpstreamSurfaceHook(int width, int height) {
+ super(width, height);
+ }
+
+ @Override
+ public final void create(ProxySurface s) {
+ final GDISurface ms = (GDISurface)s;
+ if(0 == ms.getWindowHandle()) {
+ final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, 64, 64);
+ if(0 == windowHandle) {
+ throw new NativeWindowException("Error windowHandle 0, werr: "+GDI.GetLastError());
+ }
+ ms.setWindowHandle(windowHandle);
+ ms.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ }
+
+ @Override
+ public final void destroy(ProxySurface s) {
+ final GDISurface ms = (GDISurface)s;
+ if( ms.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ if( 0 == ms.getWindowHandle() ) {
+ throw new InternalError("Owns upstream surface, but no GDI window: "+ms);
+ }
+ GDI.ShowWindow(ms.getWindowHandle(), GDI.SW_HIDE);
+ GDIUtil.DestroyDummyWindow(ms.getWindowHandle());
+ ms.setWindowHandle(0);
+ ms.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
index e368aa6a1..3db2b5fc9 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
@@ -29,9 +29,13 @@
package jogamp.nativewindow.windows;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import jogamp.nativewindow.ProxySurfaceImpl;
+import jogamp.nativewindow.windows.GDI;
/**
@@ -40,12 +44,20 @@ import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
* The latter will get and release the HDC.
* The size via getWidth()/getHeight() is invalid.
*/
-public class GDISurface extends ProxySurface {
+public class GDISurface extends ProxySurfaceImpl {
protected long windowHandle;
protected long surfaceHandle;
- public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) {
- super(cfg, initialWidth, initialHeight, upstream);
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param windowHandle the wrapped pre-existing native window handle, maybe 0 if not yet determined
+ * @param upstream the {@link UpstreamSurfaceHook} to be used
+ * @param ownsDevice true
if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise false
. Owning the device implies closing it at {@link #destroyNotify()}.
+ */
+ public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ super(cfg, upstream, ownsDevice);
this.windowHandle=windowHandle;
this.surfaceHandle=0;
}
@@ -114,18 +126,4 @@ public class GDISurface extends ProxySurface {
final public long getSurfaceHandle() {
return surfaceHandle;
}
-
- @Override
- final public String toString() {
- final UpstreamSurfaceHook ush = getUpstreamSurfaceHook();
- final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil";
- return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+
- ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+
- ", windowHandle 0x"+Long.toHexString(windowHandle)+
- ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+
- ", size "+getWidth()+"x"+getHeight()+
- ", surfaceLock "+surfaceLock+
- ", upstreamSurfaceHook "+ush_s+"]";
- }
-
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
new file mode 100644
index 000000000..55a29dd5e
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
@@ -0,0 +1,60 @@
+package jogamp.nativewindow.x11;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import jogamp.nativewindow.x11.X11Lib;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+import com.jogamp.nativewindow.x11.X11GraphicsConfiguration;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+
+public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
+ /**
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
+ * not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public X11DummyUpstreamSurfaceHook(int width, int height) {
+ super(width, height);
+ }
+
+ @Override
+ public final void create(ProxySurface s) {
+ final X11GraphicsConfiguration cfg = (X11GraphicsConfiguration) s.getGraphicsConfiguration();
+ final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen();
+ final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
+ if(0 == device.getHandle()) {
+ device.open();
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ if( 0 == s.getSurfaceHandle() ) {
+ final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64);
+ if(0 == windowHandle) {
+ throw new NativeWindowException("Creating dummy window failed w/ "+cfg);
+ }
+ s.setSurfaceHandle(windowHandle);
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ }
+
+ @Override
+ public final void destroy(ProxySurface s) {
+ if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ final X11GraphicsDevice device = (X11GraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
+ if( 0 == s.getSurfaceHandle() ) {
+ throw new InternalError("Owns upstream surface, but no X11 window: "+s);
+ }
+ X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(0);
+ s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ }
+}
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 2c853a43d..d6ae7ed31 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -119,6 +119,12 @@ Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, j
return [nsObj isMemberOfClass:[NSView class]];
}
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ return [nsObj isMemberOfClass:[NSWindow class]];
+}
+
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: getLocationOnScreen0
@@ -238,8 +244,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0
[myWindow setPreservesContentDuringLiveResize: YES];
// Remove animations
NS_DURING
+ if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) {
// Available >= 10.7 - Removes default animations
[myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone];
+ }
NS_HANDLER
NS_ENDHANDLER
@@ -278,11 +286,28 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
- DBG_PRINT( "contentView0 - window: %p (START)\n", win);
-
jlong res = (jlong) ((intptr_t) [win contentView]);
- DBG_PRINT( "contentView0 - window: %p (END)\n", win);
+ DBG_PRINT( "GetNSView(window: %p): %p\n", win, (void*) (intptr_t) res);
+
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetNSWindow0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSWindow0
+ (JNIEnv *env, jclass unused, jlong view)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSView* v = (NSView*) ((intptr_t) view);
+
+ jlong res = (jlong) ((intptr_t) [v window]);
+
+ DBG_PRINT( "GetNSWindow(view: %p): %p\n", v, (void*) (intptr_t) res);
[pool release];
return res;
@@ -314,6 +339,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
// no animations for add/remove/swap sublayers etc
// doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
[layer removeAllAnimations];
+ [layer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [layer setNeedsDisplayOnBoundsChange: YES];
DBG_PRINT("CALayer::CreateCALayer.1: %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height);
DBG_PRINT("CALayer::CreateCALayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
@@ -357,7 +384,11 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0
// no animations for add/remove/swap sublayers etc
// doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
[rootLayer removeAllAnimations];
+ [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [rootLayer setNeedsDisplayOnBoundsChange: YES];
[subLayer removeAllAnimations];
+ [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [subLayer setNeedsDisplayOnBoundsChange: YES];
}];
DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
JNF_COCOA_EXIT(env);
@@ -404,6 +435,63 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0
JNF_COCOA_EXIT(env);
}
+/*
+ * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
+ * Method: SetJAWTRootSurfaceLayer0
+ * Signature: (JJ)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
+ (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+{
+ JNF_COCOA_ENTER(env);
+ JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
+ if (NULL == dsi) {
+ NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
+ return JNI_FALSE;
+ }
+ CALayer* layer = (CALayer*) (intptr_t) caLayer;
+ [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
+ id + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *
+ *+ * Extensive FBO reconfiguration (size and sample buffer count) and validation are performed. + *
+ */ +public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + @Test + public void testGL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(false); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(true); // default + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep, null); + Assert.assertNotNull(glad); + + System.out.println("Realized GLAD: "+glad); + System.out.println("Realized GLAD: "+glad.getChosenGLCapabilities()); + Assert.assertTrue("FBO drawable is initialized before ctx creation", !glad.isInitialized()); + + glad.display(); // initial display incl. init! + { + final GLContext context = glad.getContext(); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized()); + + // + // FBO incl. MSAA is fully initialized now + // + + final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Init GLAD: "+glad); + System.out.println("Init GLAD: "+chosenCaps); + + final FBObject fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject fboBack = glad.getFBObject(GL.GL_BACK); + + System.out.println("Init front FBO: "+fboFront); + System.out.println("Init back FBO: "+fboBack); + + Assert.assertTrue("FBO drawable is not initialized before ctx creation", glad.isInitialized()); + Assert.assertTrue("FBO Front is not initialized before ctx creation", fboFront.isInitialized()); + Assert.assertTrue("FBO Back is not initialized before ctx creation", fboBack.isInitialized()); + + if( chosenCaps.getDoubleBuffered() ) { + Assert.assertTrue("FBO are equal: "+fboFront+" == "+fboBack, !fboFront.equals(fboBack)); + Assert.assertNotSame(fboFront, fboBack); + } else { + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+fboBack, fboFront.equals(fboBack)); + Assert.assertSame(fboFront, fboBack); + } + + final FBObject.TextureAttachment texAttachA, texAttachB; + + texAttachA = glad.getTextureBuffer(GL.GL_FRONT); + if(0==glad.getNumSamples()) { + texAttachB = glad.getTextureBuffer(GL.GL_BACK); + } else { + texAttachB = null; + } + + final FBObject.Colorbuffer colorA, colorB; + final FBObject.RenderAttachment depthA, depthB; + + colorA = fboFront.getColorbuffer(0); + Assert.assertNotNull(colorA); + colorB = fboBack.getColorbuffer(0); + Assert.assertNotNull(colorB); + + depthA = fboFront.getDepthAttachment(); + Assert.assertNotNull(depthA); + depthB = fboBack.getDepthAttachment(); + Assert.assertNotNull(depthB); + + glad.display(); // SWAP_ODD + + if( chosenCaps.getDoubleBuffered() ) { + // double buffer or MSAA + Assert.assertTrue("Color attachments are equal: "+colorB+" == "+colorA, !colorB.equals(colorA)); + Assert.assertNotSame(colorB, colorA); + Assert.assertTrue("Depth attachments are equal: "+depthB+" == "+depthA, !depthB.equals(depthA)); + Assert.assertNotSame(depthB, depthA); + } else { + // single buffer + Assert.assertEquals(colorA, colorB); + Assert.assertSame(colorA, colorB); + Assert.assertEquals(depthA, depthB); + Assert.assertSame(depthA, depthB); + } + + Assert.assertEquals(texAttachA, colorA); + Assert.assertSame(texAttachA, colorA); + if(0==glad.getNumSamples()) { + Assert.assertEquals(texAttachB, colorB); + Assert.assertSame(texAttachB, colorB); + } + + if( chosenCaps.getNumSamples() > 0 ) { + // MSAA + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + } else if( chosenCaps.getDoubleBuffered() ) { + // real double buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } else { + // single buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // - SWAP_EVEN + + // 1 - szStep = 2 + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + glad.display(); // - SWAP_EVEN + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize1.oldFront: "+fboFront); + System.out.println("Resize1.nowFront: "+_fboFront); + System.out.println("Resize1.oldBack : "+fboBack); + System.out.println("Resize1.nowBack : "+_fboBack); + Assert.assertEquals(fboFront, _fboFront); + Assert.assertSame(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + Assert.assertSame(fboBack, _fboBack); + + FBObject.Colorbuffer _color = _fboFront.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + + FBObject.RenderAttachment _depth = _fboFront.getDepthAttachment(); + System.err.println("Resize1.oldDepth "+depthA); + System.err.println("Resize1.newDepth "+_depth); + Assert.assertNotNull(_depth); + + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + _depth = _fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _color = _fboFront.getColorbuffer(colorA); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + } + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_EVEN + glad.display(); // - SWAP_ODD + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize2.oldFront: "+fboFront); + System.out.println("Resize2.nowFront: "+_fboFront); + System.out.println("Resize2.oldBack : "+fboBack); + System.out.println("Resize2.nowBack : "+_fboBack); + if(chosenCaps.getDoubleBuffered() && 0==chosenCaps.getNumSamples()) { + // real double buffer + Assert.assertEquals(fboBack, _fboFront); + Assert.assertEquals(fboFront, _fboBack); + } else { + // single or MSAA + Assert.assertEquals(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + } + + FBObject.Colorbuffer _color = fboBack.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + + FBObject.RenderAttachment _depth = fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); // MSAA back w/ depth + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _depth = fboFront.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + + _color = fboBack.getColorbuffer(colorB); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + } + + // 6 + 7 (samples + display) + glad.setNumSamples(glad.getGL(), chosenCaps.getNumSamples() > 0 ? 0 : 4); // triggers repaint + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // actual screenshot + + // 8, 9 (resize + samples + display) + szStep = 3; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBOAutoDrawableFactoryNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java deleted file mode 100644 index 7977347a7..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java +++ /dev/null @@ -1,272 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import jogamp.opengl.GLFBODrawableImpl; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.opengl.FBObject; -import com.jogamp.opengl.OffscreenAutoDrawable; -import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.GLReadBufferUtil; -import com.jogamp.opengl.util.texture.TextureIO; - -public class TestFBODrawableNEWT extends UITestCase { - - static final int widthStep = 800/4; - static final int heightStep = 600/4; - volatile int szStep = 2; - - @Test - public void testGL2ES2_Demo1Normal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } - - @Test - public void testGL2ES2_Demo1MSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } - - @Test - public void testGL2ES2_Demo2Normal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new MultisampleDemoES2(false)); - } - - @Test - public void testGL2ES2_Demo2MSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); - } - - @Test - public void testGL2ES2_FBODemoNormal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); - demo.setDoRotation(false); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, demo); - } - - @Test - public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); - demo.setDoRotation(false); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, demo); - } - - @Test - public void testEGLES2_Demo0Normal() throws InterruptedException { - if( GLProfile.isAvailable(GLProfile.GLES2) ) { - final GLProfile glp = GLProfile.get(GLProfile.GLES2); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } else { - System.err.println("EGL ES2 n/a"); - } - } - - @Test - public void testEGLES2_Demo0MSAA4() throws InterruptedException { - if( GLProfile.isAvailable(GLProfile.GLES2) ) { - final GLProfile glp = GLProfile.get(GLProfile.GLES2); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } else { - System.err.println("EGL ES2 n/a"); - } - } - - boolean skipShot = false; - - void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { - final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - caps.setFBO(true); - final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); - Assert.assertNotNull(fboDrawable); - Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl); - - fboDrawable.setRealized(true); - Assert.assertTrue(fboDrawable.isRealized()); - - final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject(); - - System.out.println("Realized: "+fboDrawable); - System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities()); - System.out.println("Realized: "+fbo); - - final GLContext context = fboDrawable.createContext(null); - Assert.assertNotNull(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - context.release(); - - System.out.println("Post Create-Ctx: "+fbo); - final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(colorA); - final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(depthA); - - final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, true); - - glad.addGLEventListener(demo); - glad.addGLEventListener(new GLEventListener() { - volatile int displayCount=0; - volatile int reshapeCount=0; - public void init(GLAutoDrawable drawable) {} - public void dispose(GLAutoDrawable drawable) {} - public void display(GLAutoDrawable drawable) { - final GL gl = drawable.getGL(); - // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight()); - // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo); - // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO()); - // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer()); - if(skipShot) { - skipShot=false; - } else { - snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null); - } - Assert.assertEquals(drawable.getWidth(), widthStep*szStep); - Assert.assertEquals(drawable.getHeight(), heightStep*szStep); - displayCount++; - } - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); - Assert.assertEquals(drawable.getWidth(), widthStep*szStep); - Assert.assertEquals(drawable.getHeight(), heightStep*szStep); - reshapeCount++; - } - }); - - // 0 - szStep = 2 - glad.display(); - - // 1, 2 (resize + display) - szStep = 1; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - { - // Check whether the attachment reference are still valid! - FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - Assert.assertTrue(colorA.equals(_colorA)); - FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(_depthA); - Assert.assertTrue(depthA == _depthA); - Assert.assertTrue(depthA.equals(_depthA)); - - _colorA = fbo.getColorbuffer(colorA); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - Assert.assertTrue(colorA.equals(_colorA)); - } - - // 3, 4 (resize + display) - szStep = 4; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - { - // Check whether the attachment reference are still valid! - FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(_depthA); - Assert.assertTrue(depthA == _depthA); - - _colorA = fbo.getColorbuffer(colorA); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - } - - // 5 - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - - // 6, 7 (resize + display) - szStep = 3; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - - glad.destroy(); - System.out.println("Fin: "+fboDrawable); - - // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context); - } - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java index f7c83a03b..077baad43 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -229,7 +229,7 @@ public class TestFBOMRTNEWT01 extends UITestCase { final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface(); if(last_snap_size[0] != ns.getWidth() && last_snap_size[1] != ns.getHeight()) { gl.glFinish(); // sync .. no swap buffers yet! - snapshot(getSimpleTestName("."), step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok + snapshot(step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok last_snap_size[0] = ns.getWidth(); last_snap_size[1] = ns.getHeight(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java index b384c9327..b3c542c63 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java @@ -106,7 +106,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase { if(dw<800) { System.err.println("XXX: "+dw+"x"+dh+", c "+c); if(0 == c%3) { - snapshot(getSimpleTestName("."), i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); + snapshot(i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); } if( 3 == c ) { new Thread() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java new file mode 100644 index 000000000..3ecf89bfc --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java @@ -0,0 +1,298 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.QuitAdapter; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Test; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *+ * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *
+ *+ * This test simulates shared off-thread GL context / texture usage, + * where the producer use FBOs and delivers shared textures. + * The receiver blends the shared textures onscreen. + * In detail the test consist of: + *
+ * This test simulates shared on-thread GL context / texture usage, + * where the producer uses an FBO and delivers a shared texture. + * The receiver draws the shared texture onscreen. + * In detail the test consist of: + *
+ * Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}. + * It is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final Window window = NewtFactory.createWindow(reqGLCaps); + Assert.assertNotNull(window); + window.setSize(widthStep*szStep, heightStep*szStep); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + System.out.println("Window: "+window.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // + drawable.setRealized(true); + Assert.assertTrue(drawable.isRealized()); + + System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities()); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context + window.destroy(); // destroys the actual window, incl. the device + } + }; + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + + @Override + public void windowDestroyNotify(WindowEvent e) { + glad.windowDestroyNotifyOp(); + } + }); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+drawable); + System.out.println("Fin Window: "+window); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java new file mode 100644 index 000000000..544d74aa5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java @@ -0,0 +1,317 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *+ * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep, null); + + Assert.assertNotNull(glad); + System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + Assert.assertTrue(glad.isRealized()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Drawable Caps Pre_GL : "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion()); + + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java new file mode 100644 index 000000000..64a75716b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java @@ -0,0 +1,328 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setGLCanvasSize(final Frame frame, final GLCanvas glc, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + glc.setMinimumSize(new_sz); + glc.setPreferredSize(new_sz); + glc.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(reqGLCaps.isOnscreen() && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(!reqGLCaps.isOnscreen() && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLCanvas glad = new GLCanvas(reqGLCaps); // will implicit trigger offscreen layer - if !onscreen && supported + Assert.assertNotNull(glad); + Dimension glc_sz = new Dimension(widthStep*szStep, heightStep*szStep); + glad.setMinimumSize(glc_sz); + glad.setPreferredSize(glc_sz); + glad.setSize(glc_sz); + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(glad); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glad); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreen() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreen() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java new file mode 100644 index 000000000..37ec44566 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java @@ -0,0 +1,351 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.display(); + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java new file mode 100644 index 000000000..47fc99844 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java @@ -0,0 +1,300 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setComponentSize(final Frame frame, final Component comp, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + comp.setMinimumSize(new_sz); + comp.setPreferredSize(new_sz); + comp.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(boolean offscreenLayer, GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = offscreenLayer ? + GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable) : + GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + + + final NewtCanvasAWT nca = new NewtCanvasAWT(glad); + Assert.assertNotNull(nca); + Dimension size0 = new Dimension(widthStep*szStep, heightStep*szStep); + nca.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + nca.setPreferredSize(size0); + nca.setMinimumSize(size0); + nca.setSize(size0); + + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(nca); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(nca); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glad.destroy(); + System.out.println("Fin: "+nca); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(false, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenLayerAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setFBO(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setPBuffer(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + doTest(true, reqGLCaps, new GearsES2(1)); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java deleted file mode 100644 index cd1107e25..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java +++ /dev/null @@ -1,266 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import jogamp.opengl.GLGraphicsConfigurationUtil; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.Window; -import com.jogamp.opengl.JoglVersion; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; - -public class TestGLCapabilities01NEWT extends UITestCase { - static final int width = 100; - static final int height = 100; - - boolean checkProfile(String profile) { - if( !GLProfile.isAvailable(profile) ) { - System.err.println("Profile "+profile+" n/a"); - return false; - } - return true; - } - - void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { - System.out.println("Requested GL Caps: "+reqGLCaps); - - final GLCapabilitiesImmutable expGLCaps; - if( GLGraphicsConfigurationUtil.isGLCapabilitiesOffscreenAutoSelection(reqGLCaps) ) { - final GLDrawableFactory f = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); - final boolean fboAvailable = true ; // f.canCreateFBO(null, reqGLCaps.getGLProfile()); - final boolean pbufferAvailable = f.canCreateGLPbuffer(null); - expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); - } else { - expGLCaps = reqGLCaps; - } - System.out.println("Expected GL Caps: "+expGLCaps); - // - // Create native windowing resources .. X11/Win/OSX - // - final Window window = NewtFactory.createWindow(reqGLCaps); - Assert.assertNotNull(window); - window.setSize(width, height); - window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); - System.out.println("Window: "+window.getClass().getName()); - - // Check caps of NativeWindow config w/o GL - final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); - System.out.println("Window Caps Pre_GL: "+chosenCaps); - Assert.assertNotNull(chosenCaps); - Assert.assertTrue(chosenCaps.getGreenBits()>5); - Assert.assertTrue(chosenCaps.getBlueBits()>5); - Assert.assertTrue(chosenCaps.getRedBits()>5); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); - - final GLDrawable drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - // - drawable.setRealized(true); - Assert.assertTrue(drawable.isRealized()); - - System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); - System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); - System.out.println("Chosen GL Caps(1): "+chosenGLCaps); - Assert.assertNotNull(chosenGLCaps); - Assert.assertTrue(chosenGLCaps.getGreenBits()>5); - Assert.assertTrue(chosenGLCaps.getBlueBits()>5); - Assert.assertTrue(chosenGLCaps.getRedBits()>5); - Assert.assertTrue(chosenGLCaps.getDepthBits()>4); - Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); - Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); - Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); - Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); - if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { - // dbl buffer may be disabled w/ offscreen pbuffer and bitmap - Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); - } - - GLContext context = drawable.createContext(null); - Assert.assertNotNull(context); - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - context.release(); - - System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities()); - System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - drawable.setRealized(false); - window.destroy(); - } - - @Test - public void testAvailableInfo() { - GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); - if(null != f) { - System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); - } - f = GLDrawableFactory.getEGLFactory(); - if(null != f) { - System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); - } - } - - @Test - public void testGL2OnScreenDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenAutoDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenFBODblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setFBO(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setPBuffer(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setBitmap(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OnScreenDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenAutoDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenFBODblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setFBO(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenPbufferDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setPBuffer(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - /** Not implemented ! - @Test - public void testES2OffScreenBitmapDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setBitmap(true); - doTest(reqGLCaps, new GearsES2(1)); - } */ - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestGLCapabilities01NEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java index cece4c6d5..4c1130498 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java @@ -39,13 +39,14 @@ import com.jogamp.newt.event.WindowUpdateEvent; import com.jogamp.newt.opengl.GLWindow; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLAutoDrawableDelegate; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -81,14 +82,17 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); - GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - GLDrawable drawable = factory.createGLDrawable(window); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable drawable = factory.createGLDrawable(window); Assert.assertNotNull(drawable); drawable.setRealized(true); Assert.assertTrue(drawable.isRealized()); - final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false) { + final GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { @Override protected void destroyImplInLock() { super.destroyImplInLock(); @@ -104,7 +108,7 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { } @Override public void windowResized(WindowEvent e) { - glad.windowResizedOp(); + glad.windowResizedOp(window.getWidth(), window.getHeight()); } @Override public void windowDestroyNotify(WindowEvent e) { @@ -123,9 +127,13 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter); // no GLContext! GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter); // no GLContext! - // create single context using glad1 and assign it to glad1 + // create single context using glad1 and assign it to glad1, + // after destroying the prev. context! { - GLContext singleCtx = glad1.createContext(null); + final GLContext oldCtx = glad1.getContext(); + Assert.assertNotNull(oldCtx); + oldCtx.destroy(); + final GLContext singleCtx = glad1.createContext(null); Assert.assertNotNull(singleCtx); int res = singleCtx.makeCurrent(); Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java deleted file mode 100644 index a6e9cfb07..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.GL; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.Window; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; - -public class TestGLDrawable01NEWT extends UITestCase { - static final int width = 200, height = 200; - - void doTest(String profile, boolean onscreen, boolean fbo, boolean pbuffer) throws InterruptedException { - if( !GLProfile.isAvailable(profile) ) { - System.err.println("Profile "+profile+" n/a"); - return; - } - - final GLProfile glp = GLProfile.get(profile); - final GLCapabilities reqGLCaps = new GLCapabilities(glp); - - reqGLCaps.setOnscreen(onscreen); - reqGLCaps.setPBuffer(!onscreen && pbuffer); - reqGLCaps.setFBO(!onscreen && fbo); - reqGLCaps.setDoubleBuffered(onscreen); - // System.out.println("Requested: "+caps); - - // - // Create native windowing resources .. X11/Win/OSX - // - Window window = NewtFactory.createWindow(reqGLCaps); - Assert.assertNotNull(window); - window.setSize(width, height); - window.setVisible(true); - AWTRobotUtil.waitForVisible(window, true); - AWTRobotUtil.waitForRealized(window, true); - // System.out.println("Created: "+window); - - // Check caps of NativeWindow config w/o GL - final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); - Assert.assertNotNull(chosenCaps); - Assert.assertTrue(chosenCaps.getGreenBits()>5); - Assert.assertTrue(chosenCaps.getBlueBits()>5); - Assert.assertTrue(chosenCaps.getRedBits()>5); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); - - final GLDrawable drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - // System.out.println("Pre: "+drawable); - // - drawable.setRealized(true); - Assert.assertTrue(drawable.isRealized()); - - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); - Assert.assertNotNull(chosenGLCaps); - Assert.assertTrue(chosenGLCaps.getGreenBits()>5); - Assert.assertTrue(chosenGLCaps.getBlueBits()>5); - Assert.assertTrue(chosenGLCaps.getRedBits()>5); - Assert.assertTrue(chosenGLCaps.getDepthBits()>4); - Assert.assertEquals(reqGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); - Assert.assertEquals(reqGLCaps.isOnscreen(), chosenGLCaps.getDoubleBuffered()); // offscreen shall be !dbl-buffer - // System.out.println("Post: "+drawable); - - GLContext context = drawable.createContext(null); - Assert.assertNotNull(context); - // System.out.println(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - - // draw something .. - final GL gl = context.getGL(); - gl.glClearColor(1, 1, 1, 1); - gl.glEnable(GL.GL_DEPTH_TEST); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - gl.glViewport(0, 0, width, height); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - - drawable.swapBuffers(); - context.release(); - - Thread.sleep(50); - - context.destroy(); - drawable.setRealized(false); - window.destroy(); - // System.out.println("Final: "+window); - } - - @Test - public void testGL2OnScreen() throws InterruptedException { - doTest(GLProfile.GL2, true, false, false); - } - - @Test - public void testES2OnScreen() throws InterruptedException { - doTest(GLProfile.GLES2, true, false, false); - } - - @Test - public void testGL2PBuffer() throws InterruptedException { - doTest(GLProfile.GL2, false, false, true); - } - - @Test - public void testES2PBuffer() throws InterruptedException { - doTest(GLProfile.GLES2, false, false, true); - } - - // @Test // TODO: FBO-Drawable via createGLDrawable and pre-exisiting NativeSurface - public void testGL2FBO() throws InterruptedException { - doTest(GLProfile.GL2, false, true, false); - } - - // @Test // TODO: FBO-Drawable via createGLDrawable and pre-exisiting NativeSurface - public void testES2FBO() throws InterruptedException { - doTest(GLProfile.GLES2, false, true, false); - } - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestGLDrawable01NEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java index e4245ef11..d4f3fece5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java @@ -32,14 +32,11 @@ import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import jogamp.opengl.GLDrawableFactoryImpl; @@ -77,13 +74,11 @@ public class TestGLExtensionQueryOffscreen { @Test public void testJogl2ExtensionCheck2() { - GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); - GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); - GLCapabilitiesChooser glCapsChooser = new DefaultGLCapabilitiesChooser(); - AbstractGraphicsDevice agd = factory.getDefaultDevice(); + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable drawable = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); - GLAutoDrawable drawable = factory.createGLPbuffer(agd, caps, glCapsChooser, 256, 256, null); - GLContext context = drawable.getContext(); + final GLContext context = drawable.getContext(); context.makeCurrent(); String extensions; try { @@ -94,8 +89,8 @@ public class TestGLExtensionQueryOffscreen { String[] tabExtensions = extensions.split(" "); SortedSet
+ * + Container is the JFrame's implicit root content pane
+ *
+ * {@link JFrame} . {@link JPanel}+ . {@link Container} . {@link NewtCanvasAWT} . {@link GLWindow} + *
+ *
+ * + JPanel is set as JFrame's root content pane
+ *
- * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png - * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgb_-S00_default-0400x0300.png + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgb_-S00_default-0200x0150.png + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgb_-S00_default-0200x0150.png *- * - * @param simpleTestName will be used as the filename prefix * @param sn sequential number * @param postSNDetail optional detail to be added to the filename after
sn
* @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename.
@@ -137,30 +156,80 @@ public abstract class UITestCase {
* It shall not end with a directory separator, {@link File#separatorChar}.
* If null
the current working directory is being used.
*/
- public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
+ public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
if(null == fileSuffix) {
fileSuffix = TextureIO.PNG;
}
- final StringWriter filenameSW = new StringWriter();
- {
+ final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1;
+ final String simpleTestName = this.getSimpleTestName(".");
+ final String filenameBaseName;
+ {
final GLDrawable drawable = gl.getContext().getGLReadDrawable();
final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ;
+ final String scrnm;
+ if(caps.isOnscreen()) {
+ scrnm = "onscreen";
+ } else if(caps.isFBO()) {
+ scrnm = "fbobject";
+ } else if(caps.isPBuffer()) {
+ scrnm = "pbuffer_";
+ } else if(caps.isBitmap()) {
+ scrnm = "bitmap__";
+ } else {
+ scrnm = "unknown_";
+ }
+ final String dblb = caps.getDoubleBuffered() ? "dbl" : "one";
final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_";
final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_";
- final String aaext = caps.getSampleExtension();
final int samples = caps.getNumSamples() ;
+ final String aaext = caps.getSampleExtension();
postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
- final PrintWriter pw = new PrintWriter(filenameSW);
- pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s",
- simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(),
- drawable.getWidth(), drawable.getHeight(), fileSuffix);
+
+ filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-S%02d_%s-%04dx%04d.%s",
+ simpleTestName, sn, postSNDetail, drawable.getGLProfile().getName(), accel,
+ scrnm, dblb, F_pfmt, pfmt, samples, aaext,
+ drawable.getWidth(), drawable.getHeight(), fileSuffix).replace(' ', '_');
}
- final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString();
- System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename);
+ final String filename = null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename+", maxTestNameLen "+maxSimpleTestNameLen+", <"+simpleTestName+">");
gl.glFinish(); // just make sure rendering finished ..
if(readBufferUtil.readPixels(gl, false)) {
readBufferUtil.write(new File(filename));
}
- }
+ }
+
+ public class SnapshotGLEventListener implements GLEventListener {
+ private final GLReadBufferUtil screenshot;
+ private volatile boolean makeShot = false;
+ private volatile int displayCount=0;
+ private volatile int reshapeCount=0;
+ public SnapshotGLEventListener(GLReadBufferUtil screenshot) {
+ this.screenshot = screenshot;
+ }
+ public SnapshotGLEventListener() {
+ this.screenshot = new GLReadBufferUtil(false, false);
+ }
+
+ public void init(GLAutoDrawable drawable) {}
+ public void dispose(GLAutoDrawable drawable) {}
+ public void display(GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": "+drawable.getWidth()+"x"+drawable.getHeight()+", makeShot "+makeShot);
+ if(makeShot) {
+ makeShot=false;
+ snapshot(displayCount, null, gl, screenshot, TextureIO.PNG, null);
+ }
+ displayCount++;
+ }
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight());
+ reshapeCount++;
+ }
+ public void setMakeSnapshot() {
+ makeShot=true;
+ }
+ };
+
}
--
cgit v1.2.3
From e30c2c7d06847889d961d12b50e77e4dfd6e525f Mon Sep 17 00:00:00 2001
From: Sven Gothel + * Test disabled since showing the Desktop folder will + * disturb the 'desktop' .. if there is another way to show + * the performance bug, pls do so. + *
+ *+ * Since Windows XP is out of life .. we may not care .. + *
+ */ +public class TestBug611AWT extends UITestCase { + + @Test + public void test00() { + // make junit happy + } + + // @Test + public void test01() { + try { + // System.setProperty("jogamp.gluegen.UseTempJarCache", "false"); + GLProfile.initSingleton(); + Desktop desktop; + if (Desktop.isDesktopSupported()) { + desktop = Desktop.getDesktop(); + } else { + desktop = null; + } + if(null != desktop) { + String home = System.getProperty("user.home"); + File homeFolder = null; + if(null != home) { + { + File tst = new File(home + "/Desktop"); + if( tst.canRead() ) { + homeFolder = tst; + } + } + if(null == homeFolder) { + File tst = new File(home); + if( tst.canRead() ) { + homeFolder = tst; + } + } + } + if(null == homeFolder) { + if(Platform.getOSType() == Platform.OSType.WINDOWS) { + homeFolder = new File("c:\\"); + } else { + homeFolder = new File("/"); + } + } + if(null != homeFolder) { + desktop.open(homeFolder); + } + } + } catch(Exception ex) { + ex.printStackTrace(); + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestBug611AWT.class.getName()); + } +} -- cgit v1.2.3 From 646714d3dab87396b9a3119bf90ca26e0b1c97ce Mon Sep 17 00:00:00 2001 From: Sven Gothel+ * Besides regular modifiers like {@link InputEvent##SHIFT_MASK} etc., + * the {@link InputEvent#AUTOREPEAT_MASK} bit is added if repetition is detected. + *
+ */ --- make/scripts/java-win64-dbg.bat | 6 +- make/scripts/tests-x64.bat | 4 +- make/scripts/tests.sh | 6 +- src/newt/classes/com/jogamp/newt/Window.java | 2 + .../classes/com/jogamp/newt/event/InputEvent.java | 82 ++++++++++++++++++---- .../classes/com/jogamp/newt/event/KeyEvent.java | 26 ++++++- .../classes/com/jogamp/newt/event/MouseEvent.java | 12 +++- .../classes/com/jogamp/newt/event/NEWTEvent.java | 10 ++- .../classes/com/jogamp/newt/event/WindowEvent.java | 13 +++- .../com/jogamp/newt/event/WindowUpdateEvent.java | 11 ++- .../jogamp/newt/driver/macosx/WindowDriver.java | 20 ++++++ .../jogamp/newt/driver/windows/WindowDriver.java | 36 ++++++++-- src/newt/native/InputEvent.h | 22 +++--- src/newt/native/X11Display.c | 18 ++++- 14 files changed, 223 insertions(+), 45 deletions(-) (limited to 'make/scripts') diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat index b63438534..07722c78e 100755 --- a/make/scripts/java-win64-dbg.bat +++ b/make/scripts/java-win64-dbg.bat @@ -38,7 +38,8 @@ REM set D_ARGS="-Djogl.debug=all" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.windows.useWGLVersionOf5WGLGDIFuncSet" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" -set D_ARGS="-Dnewt.debug.Window" +REM set D_ARGS="-Dnewt.debug.Window" +set D_ARGS="-Dnewt.debug.Window.KeyEvent" REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode" @@ -53,4 +54,5 @@ REM set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.java2d.opengl=true" "-Dsun.awt REM set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.java2d.d3d=false" "-Dsun.java2d.ddoffscreen=false" "-Dsun.java2d.gdiblit=false" "-Dsun.java2d.opengl=false" "-Dsun.awt.noerasebackground=true" "-Xms512m" "-Xmx1024m" REM set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.java2d.d3d=false" "-Dsun.java2d.ddoffscreen=false" "-Dsun.java2d.gdiblit=false" "-Dsun.java2d.opengl=true" "-Dsun.awt.noerasebackground=true" "-Xms512m" "-Xmx1024m" -%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %* > java-win64-dbg.log 2>&1 +REM %J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %* > java-win64-dbg.log 2>&1 +%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %* diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index a4207b696..9ffbcd6d3 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -19,7 +19,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLPro REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* +scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0 REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 %* @@ -103,7 +103,7 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT -scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $* diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 724b7df97..7b39c3fbd 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -123,7 +123,7 @@ function jrun() { #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext" #D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen" #D_ARGS="-Dnewt.debug.Window" - #D_ARGS="-Dnewt.debug.Window.KeyEvent" + D_ARGS="-Dnewt.debug.Window.KeyEvent" #D_ARGS="-Dnewt.debug.Window.MouseEvent" #D_ARGS="-Dnewt.debug.Window -Dnativewindow.debug=all" #D_ARGS="-Dnewt.debug.Window -Dnativewindow.debug.JAWT -Djogl.debug.Animator" @@ -263,7 +263,7 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT -#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $* #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $* @@ -304,7 +304,7 @@ function testawtswt() { #testawt javax.media.opengl.awt.GLCanvas $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug551AWT $* -testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug611AWT $* +#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug611AWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestAWTCloseX11DisplayBug565 $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListAWT $* diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index e8537fec5..78e2abc6e 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -245,6 +245,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol { String getTitle(); + /** @see #setPointerVisible(boolean) */ boolean isPointerVisible(); /** @@ -256,6 +257,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol { */ void setPointerVisible(boolean pointerVisible); + /** @see #confinePointer(boolean) */ boolean isPointerConfined(); /** diff --git a/src/newt/classes/com/jogamp/newt/event/InputEvent.java b/src/newt/classes/com/jogamp/newt/event/InputEvent.java index 819338ccb..148ac5962 100644 --- a/src/newt/classes/com/jogamp/newt/event/InputEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/InputEvent.java @@ -34,22 +34,31 @@ package com.jogamp.newt.event; +import com.jogamp.newt.Window; + @SuppressWarnings("serial") public abstract class InputEvent extends NEWTEvent { - public static final int SHIFT_MASK = 1 << 0; - public static final int CTRL_MASK = 1 << 1; - public static final int META_MASK = 1 << 2; - public static final int ALT_MASK = 1 << 3; - public static final int ALT_GRAPH_MASK = 1 << 5; - public static final int BUTTON1_MASK = 1 << 6; - public static final int BUTTON2_MASK = 1 << 7; - public static final int BUTTON3_MASK = 1 << 8; - public static final int BUTTON4_MASK = 1 << 9; - public static final int BUTTON5_MASK = 1 << 10; - public static final int BUTTON6_MASK = 1 << 11; - public static final int CONFINED_MASK = 1 << 16; - public static final int INVISIBLE_MASK = 1 << 17; + public static final int SHIFT_MASK = 1 << 0; + public static final int CTRL_MASK = 1 << 1; + public static final int META_MASK = 1 << 2; + public static final int ALT_MASK = 1 << 3; + public static final int ALT_GRAPH_MASK = 1 << 5; + public static final int BUTTON1_MASK = 1 << 6; + public static final int BUTTON2_MASK = 1 << 7; + public static final int BUTTON3_MASK = 1 << 8; + public static final int BUTTON4_MASK = 1 << 9; + public static final int BUTTON5_MASK = 1 << 10; + public static final int BUTTON6_MASK = 1 << 11; + + /** Event is caused by auto-repeat. */ + public static final int AUTOREPEAT_MASK = 1 << 15; + + /** Pointer is confined, see {@link Window#confinePointer(boolean)}. */ + public static final int CONFINED_MASK = 1 << 16; + + /** Pointer is invisible, see {@link Window#setPointerVisible(boolean)}. */ + public static final int INVISIBLE_MASK = 1 << 17; /** * Returns the corresponding button mask for the given button. @@ -76,30 +85,64 @@ public abstract class InputEvent extends NEWTEvent this.modifiers=modifiers; } + /** Return the modifier bits of this event, e.g. see {@link #SHIFT_MASK} .. etc. */ public int getModifiers() { return modifiers; } + /** {@link #getModifiers()} contains {@link #ALT_MASK}. */ public boolean isAltDown() { return (modifiers&ALT_MASK)!=0; } + /** {@link #getModifiers()} contains {@link #ALT_GRAPH_MASK}. */ public boolean isAltGraphDown() { return (modifiers&ALT_GRAPH_MASK)!=0; } + /** {@link #getModifiers()} contains {@link #CTRL_MASK}. */ public boolean isControlDown() { return (modifiers&CTRL_MASK)!=0; } + /** {@link #getModifiers()} contains {@link #META_MASK}. */ public boolean isMetaDown() { return (modifiers&META_MASK)!=0; } + /** {@link #getModifiers()} contains {@link #SHIFT_MASK}. */ public boolean isShiftDown() { return (modifiers&SHIFT_MASK)!=0; } + /** {@link #getModifiers()} contains {@link #AUTOREPEAT_MASK}. */ + public boolean isAutoRepeat() { + return (modifiers&AUTOREPEAT_MASK)!=0; + } + /** {@link #getModifiers()} contains {@link #CONFINED_MASK}. Pointer is confined, see {@link Window#confinePointer(boolean)}. */ public boolean isConfined() { return (modifiers&CONFINED_MASK)!=0; } + /** {@link #getModifiers()} contains {@link #INVISIBLE_MASK}. Pointer is invisible, see {@link Window#setPointerVisible(boolean)}. */ public boolean isInvisible() { return (modifiers&INVISIBLE_MASK)!=0; } + + public StringBuilder getModifiersString(StringBuilder sb) { + if(null == sb) { + sb = new StringBuilder(); + } + sb.append("["); + boolean isFirst = true; + if(isShiftDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("shift"); } + if(isControlDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("ctrl"); } + if(isMetaDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("meta"); } + if(isAltDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("alt"); } + if(isAltGraphDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("altg"); } + if(isAutoRepeat()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("repeat"); } + for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) { + if(isButtonDown(i)) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("button").append(i); } + } + if(isConfined()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("confined"); } + if(isInvisible()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("invisible"); } + sb.append("]"); + + return sb; + } /** * @return Array of pressed mouse buttons [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}]. @@ -124,7 +167,18 @@ public abstract class InputEvent extends NEWTEvent } public String toString() { - return "InputEvent[modifiers: 0x"+Integer.toHexString(modifiers)+", "+super.toString()+"]"; + return toString(null).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if(null == sb) { + sb = new StringBuilder(); + } + sb.append("InputEvent[modifiers: "); + getModifiersString(sb); + sb.append(", "); + super.toString(sb).append("]"); + return sb; } private final int modifiers; diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java index 4db661eeb..bd48981da 100644 --- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java @@ -34,6 +34,21 @@ package com.jogamp.newt.event; +/** + * Key events are delivered in the following order: + *+ * Besides regular modifiers like {@link InputEvent##SHIFT_MASK} etc., + * the {@link InputEvent#AUTOREPEAT_MASK} bit is added if repetition is detected. + *
+ */ @SuppressWarnings("serial") public class KeyEvent extends InputEvent { @@ -54,8 +69,15 @@ public class KeyEvent extends InputEvent } public String toString() { - return "KeyEvent["+getEventTypeString(getEventType())+ - ", code "+keyCode+"("+toHexString(keyCode)+"), char '"+keyChar+"' ("+toHexString((int)keyChar)+"), isActionKey "+isActionKey()+", "+super.toString()+"]"; + return toString(null).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if(null == sb) { + sb = new StringBuilder(); + } + sb.append("KeyEvent[").append(getEventTypeString(getEventType())).append(", code ").append(keyCode).append("(").append(toHexString(keyCode)).append("), char '").append(keyChar).append("' (").append(toHexString((int)keyChar)).append("), isActionKey ").append(isActionKey()).append(", "); + return super.toString(sb).append("]"); } public static String getEventTypeString(int type) { diff --git a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java index ceaf7d47a..d293d2db7 100644 --- a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java @@ -165,7 +165,13 @@ public class MouseEvent extends InputEvent } public String toString() { - StringBuilder sb = new StringBuilder(); + return toString(null).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if(null == sb) { + sb = new StringBuilder(); + } sb.append("MouseEvent[").append(getEventTypeString(getEventType())) .append(", ").append(x).append("/").append(y) .append(", button ").append(button).append(", count ") @@ -182,8 +188,8 @@ public class MouseEvent extends InputEvent } sb.append("]"); } - sb.append(", ").append(super.toString()).append("]"); - return sb.toString(); + sb.append(", "); + return super.toString(sb).append("]"); } public static String getEventTypeString(int type) { diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java index 3f3817b91..fd5b69ccc 100644 --- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java @@ -151,7 +151,14 @@ public class NEWTEvent extends java.util.EventObject { } public String toString() { - return "NEWTEvent[sys:"+isSystemEvent()+", source:"+getSource().getClass().getName()+", when:"+getWhen()+" d "+(System.currentTimeMillis()-getWhen())+"ms]"; + return toString(null).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if(null == sb) { + sb = new StringBuilder(); + } + return sb.append("NEWTEvent[sys:").append(isSystemEvent()).append(", source:").append(getSource().getClass().getName()).append(", when:").append(getWhen()).append(" d ").append((System.currentTimeMillis()-getWhen())).append("ms]"); } public static String toHexString(int hex) { @@ -161,5 +168,4 @@ public class NEWTEvent extends java.util.EventObject { public static String toHexString(long hex) { return "0x" + Long.toHexString(hex); } - } diff --git a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java index f3d62d8c6..163b51439 100644 --- a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java @@ -39,6 +39,7 @@ package com.jogamp.newt.event; * NEWT will automatically handle component moves and resizes internally, regardless of whether a program is receiving these events or not.
+ * Implementation uses the XLib macro DefaultScreen(display)
.
+ *
+ * Using centralized quirk identifier enables us to + * locate code dealing w/ it and hence eases it's maintenance. + *
+ */ +public class GLRendererQuirks { + /** Crashes XServer when using double buffered PBuffer with 'Mesa DRI Intel(R) Sandybridge Desktop' & 'Mesa DRI Intel(R) Ivybridge Mobile - 3.0 Mesa 8.0.4' */ + public static final int NoDoubleBufferedPBuffer = 0; + + /** On Windows no double buffered bitmaps are guaranteed to be available. */ + public static final int NoDoubleBufferedBitmap = 1; + + /** Crashes application when trying to set EGL swap interval on Android 4.0.3 / Pandaboard ES / PowerVR SGX 540 */ + public static final int NoSetSwapInterval = 2; + + /** No offscreen bitmap available, currently true for JOGL's OSX implementation. */ + public static final int NoOffscreenBitmap = 3; + + /** Number of quirks known. */ + public static final int COUNT = 4; + + private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval", + "NoOffscreenBitmap" + }; + + private final int _bitmask; + + /** + * @param quirks an array of valid quirks + * @param offset offset in quirks array to start reading + * @param len number of quirks to read from offset within quirks array + * @throws IllegalArgumentException if one of the quirks is out of range + */ + public GLRendererQuirks(int[] quirks, int offset, int len) throws IllegalArgumentException { + int bitmask = 0; + if( !( 0 <= offset + len && offset + len < quirks.length ) ) { + throw new IllegalArgumentException("offset and len out of bounds: offset "+offset+", len "+len+", array-len "+quirks.length); + } + for(int i=offset; iquirk
exist in {@link #getRendererQuirks()}, otherwise false.
+ * + * Convenience method for: + *
+ * final GLRendererQuirks glrq = ctx.getRendererQuirks(); + * boolean hasQuirk = null != glrq ? glrq.exist(quirk) : false ; + *+ * + * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}. + * @throws IllegalArgumentException if the quirk is out of range + */ + public final boolean hasRendererQuirk(int quirk) throws IllegalArgumentException { + return null != glRendererQuirks ? glRendererQuirks.exist(quirk) : false ; + } + /** * Sets the read/write drawable for framebuffer operations. *
@@ -464,6 +489,12 @@ public abstract class GLContext {
sb.append(toHexString(contextHandle));
sb.append(", ");
sb.append(getGL());
+ sb.append(",\n\t quirks: ");
+ if(null != glRendererQuirks) {
+ glRendererQuirks.toString(sb);
+ } else {
+ sb.append("n/a");
+ }
if(getGLDrawable()!=getGLReadDrawable()) {
sb.append(",\n\tRead Drawable : ");
sb.append(getGLReadDrawable());
@@ -473,8 +504,6 @@ public abstract class GLContext {
sb.append(",\n\tDrawable: ");
sb.append(getGLDrawable());
}
- sb.append(", lock ");
- sb.append(lock.toString());
return sb;
}
@@ -666,13 +695,15 @@ public abstract class GLContext {
if( hasFullFBOSupport() ) {
final GL gl = getGL();
final int[] val = new int[] { 0 } ;
- gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
- final int glerr = gl.glGetError();
- if(GL.GL_NO_ERROR == glerr) {
- return val[0];
- } else if(DEBUG) {
- System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
- }
+ try {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
+ final int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ return val[0];
+ } else if(DEBUG) {
+ System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ } catch (GLException gle) { gle.printStackTrace(); }
}
return 0;
}
@@ -1369,6 +1400,6 @@ public abstract class GLContext {
protected static String getThreadName() {
return Thread.currentThread().getName();
}
-
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index b6e7b0576..ae49eeeff 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -49,6 +49,7 @@ import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.GLRendererQuirks;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -307,6 +308,42 @@ public abstract class GLDrawableFactory {
*/
protected abstract boolean createSharedResource(AbstractGraphicsDevice device);
+ /**
+ * Returns true if the quirk
exist in the shared resource's context {@link GLRendererQuirks}.
+ *
+ * Convenience method for: + *
+ final GLRendererQuirks glrq = factory.getRendererQuirks(device); + return null != glrq ? glrq.exist(quirk) : false; + *+ * + * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be
null
for the platform's default device.
+ * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}.
+ * @throws IllegalArgumentException if the quirk is out of range
+ * @see #getRendererQuirks()
+ * @see GLRendererQuirks
+ */
+ public final boolean hasRendererQuirk(AbstractGraphicsDevice device, int quirk) {
+ final GLRendererQuirks glrq = getRendererQuirks(device);
+ return null != glrq ? glrq.exist(quirk) : false;
+ }
+
+ /**
+ * Returns the shared resource's context {@link GLRendererQuirks}.
+ * + * Implementation calls {@link GLContext#getRendererQuirks()} on the shared resource context. + *
+ *
+ * In case no shared device exist yet or the implementation doesn't support tracking quirks,
+ * the result is always null
.
+ *
null
for the platform's default device.
+ * @see GLContext#getRendererQuirks()
+ * @see GLRendererQuirks
+ */
+ public abstract GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device);
+
/**
* Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null
*/
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index 23d789afd..aabda465e 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -1445,10 +1445,6 @@ public class GLProfile {
}
} else {
defaultDesktopDevice = desktopFactory.getDefaultDevice();
- defaultDevice = defaultDesktopDevice;
- if(DEBUG) {
- System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice);
- }
}
if ( !disableOpenGLES && ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
@@ -1490,7 +1486,7 @@ public class GLProfile {
}
}
- final AbstractGraphicsDevice defaultEGLDevice;
+ final AbstractGraphicsDevice defaultEGLDevice;
if(null == eglFactory) {
hasGLES2Impl = false;
hasGLES1Impl = false;
@@ -1499,25 +1495,33 @@ public class GLProfile {
System.err.println("Info: GLProfile.init - EGL GLDrawable factory not available");
}
} else {
- defaultEGLDevice = eglFactory.getDefaultDevice();
- if(null == defaultDevice) {
- defaultDevice = defaultEGLDevice;
- if(DEBUG) {
- System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice);
- }
- }
+ defaultEGLDevice = eglFactory.getDefaultDevice();
}
- /** Should not be required .. but keep it here if simple probe on defaultDevice ain't enough.
- final boolean addedDesktopProfile = initProfilesForDevice(defaultDesktopDevice);
- final boolean addedEGLProfile = initProfilesForDevice(defaultEGLDevice);
- final boolean addedAnyProfile = addedDesktopProfile || addedEGLProfile ;
- */
- final boolean addedAnyProfile = initProfilesForDevice(defaultDevice);
-
+ if( null != defaultDesktopDevice ) {
+ defaultDevice = defaultDesktopDevice;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice);
+ }
+ } else if ( null != defaultEGLDevice ) {
+ defaultDevice = defaultEGLDevice;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice);
+ }
+ } else {
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device not available");
+ }
+ defaultDevice = null;
+ }
+
+ // we require to initialize the EGL device 1st, if available
+ final boolean addedEGLProfile = null != defaultEGLDevice ? initProfilesForDevice(defaultEGLDevice) : false;
+ final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false;
+ final boolean addedAnyProfile = addedEGLProfile || addedDesktopProfile ;
+
if(DEBUG) {
- // System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
- System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 050c619fd..e164dfe44 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -46,6 +46,7 @@ import java.util.HashMap;
import java.util.Map;
import com.jogamp.common.os.DynamicLookupHelper;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.gluegen.runtime.FunctionAddressResolver;
@@ -53,6 +54,7 @@ import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -162,7 +164,7 @@ public abstract class GLContextImpl extends GLContext {
additionalCtxCreationFlags = 0;
glRenderer = "";
- glRendererLowerCase = glRenderer;
+ glRendererLowerCase = glRenderer;
if (boundFBOTarget != null) { // device
{@link AbstractGraphicsDevice#getConnection()},
* either a pre-existing or newly created, or null
if creation failed or not supported.null
for the platform's default device.
*/
protected final AbstractGraphicsDevice getOrCreateSharedDevice(AbstractGraphicsDevice device) {
- if(null==device) {
- device = getDefaultDevice();
- if(null==device) {
- throw new InternalError("no default device");
- }
- if (GLProfile.DEBUG) {
- System.err.println("Info: GLDrawableFactoryImpl.getOrCreateSharedContext: using default device : "+device);
- }
- } else if( !getIsDeviceCompatible(device) ) {
- if (GLProfile.DEBUG) {
- System.err.println("Info: GLDrawableFactoryImpl.getOrCreateSharedContext: device not compatible : "+device);
- }
- return null;
+ device = validateDevice(device);
+ if( null != device) {
+ return getOrCreateSharedDeviceImpl(device);
}
- return getOrCreateSharedDeviceImpl(device);
+ return null;
}
protected abstract AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device);
+
/**
* Returns the GLDynamicLookupHelper
* @param profile if EGL/ES, profile 1
refers to ES1 and 2
to ES2,
@@ -144,12 +145,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
try {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
+ final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice);
// layered surface -> Offscreen/[FBO|PBuffer]
- final boolean isPbufferAvailable = canCreateGLPbuffer(adevice) ;
- if(!isPbufferAvailable && !isFBOAvailable) {
- throw new GLException("Neither FBO nor Pbuffer is available for "+target);
+ if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) {
+ throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target);
}
- final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, isFBOAvailable, isPbufferAvailable);
config.setChosenCapabilities(chosenCapsMod);
ols.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
@@ -163,7 +163,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
}
- if( chosenCapsMod.isFBO() && isFBOAvailable ) {
+ if( chosenCapsMod.isFBO() ) {
// target surface is already a native one
result = createFBODrawableImpl(target, chosenCapsMod, 0);
} else {
@@ -294,9 +294,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
throw new GLException("No shared device for requested: "+deviceReq);
}
- final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested,
- GLContext.isFBOAvailable(device, capsRequested.getGLProfile()),
- canCreateGLPbuffer(device));
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, this, device);
if( capsChosen.isFBO() ) {
device.lock();
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
index 13c95b0dd..31e52b86c 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
@@ -32,8 +32,9 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
-import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.GLRendererQuirks;
public class GLGraphicsConfigurationUtil {
public static final String NV_coverage_sample = "NV_coverage_sample";
@@ -138,16 +139,25 @@ public class GLGraphicsConfigurationUtil {
return caps;
}
- public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable)
- {
+ /**
+ * Fixes the requested {@link GLCapabilitiesImmutable} according to on- and offscreen usage.
+ * + * No modification will be made for onscreen usage, for offscreen usage see + * {@link #fixOffscreenGLCapabilities(GLCapabilitiesImmutable, GLDrawableFactory, AbstractGraphicsDevice)}. + *
+ * @param capsRequested the requested {@link GLCapabilitiesImmutable} + * @param factory the {@link GLDrawableFactory} used to validate the requested capabilities and later used to create the drawable. + * @param device the device on which the drawable will be created, maybe null for the {@link GLDrawableFactory#getDefaultDevice() default device}. + * @return either the given requested {@link GLCapabilitiesImmutable} instance if no modifications were required, or a modified {@link GLCapabilitiesImmutable} instance. + */ + public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, + GLDrawableFactory factory, AbstractGraphicsDevice device) { if( !capsRequested.isOnscreen() ) { - return fixOffscreenGLCapabilities(capsRequested, fboAvailable, pbufferAvailable); - } /* we maintain the offscreen mode flags in onscreen mode - else { - return fixOnscreenGLCapabilities(capsRequested); - } */ + return fixOffscreenGLCapabilities(capsRequested, factory, device); + } return capsRequested; } - + public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested) { if( !capsRequested.isOnscreen() || capsRequested.isFBO() || capsRequested.isPBuffer() || capsRequested.isBitmap() ) { @@ -162,25 +172,68 @@ public class GLGraphicsConfigurationUtil { return capsRequested; } - public static boolean isGLCapabilitiesOffscreenAutoSelection(GLCapabilitiesImmutable capsRequested) { - return !capsRequested.isOnscreen() && - !capsRequested.isFBO() && !capsRequested.isPBuffer() && !capsRequested.isBitmap() ; + public static GLCapabilitiesImmutable fixOffscreenBitOnly(GLCapabilitiesImmutable capsRequested) + { + if( capsRequested.isOnscreen() ) { + // fix caps .. + final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); + caps2.setOnscreen(false); + return caps2; + } + return capsRequested; } - - public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) { - final boolean auto = !capsRequested.isFBO() && !capsRequested.isPBuffer() && !capsRequested.isBitmap() ; - - final boolean requestedPBuffer = capsRequested.isPBuffer() || Platform.getOSType() == Platform.OSType.MACOS ; // no native bitmap for OSX + + /** + * Fixes the requested {@link GLCapabilitiesImmutable} according to: + *- * We intentionally override a non native EGL device ES profile mapping, - * i.e. this will override/modify an already 'set' X11/WGL/.. mapping. - *
- * - * @param device - */ - protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { - mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); - } - protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) { + /* pp */ void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { + mapStaticGLVersion(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } + /* pp */ int getContextOptions() { return ctxOptions; } + /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) { final GLProfile glp = caps.getGLProfile(); final int[] reqMajorCTP = new int[2]; GLContext.getRequestMajorAndCompat(glp, reqMajorCTP); @@ -309,21 +294,27 @@ public abstract class EGLContext extends GLContextImpl { if(!caps.getHardwareAccelerated()) { reqMajorCTP[1] |= GLContext.CTX_IMPL_ACCEL_SOFT; } - mapCurrentAvailableGLVersionImpl(device, reqMajorCTP[0], 0, reqMajorCTP[1]); - } - protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) { + mapStaticGLVersion(device, reqMajorCTP[0], 0, reqMajorCTP[1]); + } + /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) { int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES ); - mapCurrentAvailableGLVersionImpl(device, major, 0, ctp); + mapStaticGLVersion(device, major, 0, ctp); } - private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) { + /* pp */ static void mapStaticGLVersion(AbstractGraphicsDevice device, int major, int minor, int ctp) { if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) { // ES1 or ES2 final int reqMajor = major; final int reqProfile = GLContext.CTX_PROFILE_ES; - GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, - major, minor, ctp); + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, major, minor, ctp); + if(! ( device instanceof EGLGraphicsDevice ) ) { + final EGLGraphicsDevice eglDevice = new EGLGraphicsDevice(device.getHandle(), EGL.EGL_NO_DISPLAY, device.getConnection(), device.getUnitID(), null); + GLContext.mapAvailableGLVersion(eglDevice, reqMajor, reqProfile, major, minor, ctp); + } } } + protected static String getGLVersion(int major, int minor, int ctp, String gl_version) { + return GLContext.getGLVersion(major, minor, ctp, gl_version); + } protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) { return GLContext.getAvailableGLVersionsSet(device); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index e98d69140..a907c4aff 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -43,6 +43,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -77,11 +78,11 @@ import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLRendererQuirks; public class EGLDrawableFactory extends GLDrawableFactoryImpl { protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; - /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true); /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; @@ -113,36 +114,11 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } catch (JogampRuntimeException jre) { /* n/a .. */ } } - defaultDevice = new EGLGraphicsDevice(); - // FIXME: Probably need to move EGL from a static model // to a dynamic one, where there can be 2 instances // for each ES profile with their own ProcAddressTable. synchronized(EGLDrawableFactory.class) { - /** - * Currently AMD's EGL impl. crashes at eglGetDisplay(EGL_DEFAULT_DISPLAY) - * - // Check Desktop ES2 Availability first (AMD, ..) - if(null==eglES2DynamicLookupHelper) { - GLDynamicLookupHelper tmp=null; - try { - tmp = new GLDynamicLookupHelper(new DesktopES2DynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); - } - } - if(null!=tmp && tmp.isLibComplete()) { - eglES2DynamicLookupHelper = tmp; - EGL.resetProcAddressTable(eglES2DynamicLookupHelper); - if (GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: Desktop ES2 - OK"); - } - } else if (GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: Desktop ES2 - NOPE"); - } - } */ final boolean hasDesktopES2 = null != eglES2DynamicLookupHelper; if(!hasDesktopES2 && null==eglES1DynamicLookupHelper) { @@ -188,8 +164,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } } if(null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper) { - sharedMap = new HashMap- * Workaround is to not close them at all if driver vendor is ATI. + * Workaround is to not close them at all if driver vendor is ATI + * during operation. + *
+ *+ * With ATI X11 drivers all connections must be closed at JVM shutdown, + * otherwise a SIGSEGV (after JVM safepoint) will be caused. *
*/ public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true); @@ -141,6 +146,14 @@ public class X11Util { } } + // not exactly thread safe, but good enough for our purpose, + // which is to tag a NamedDisplay uncloseable after creation. + private static Object globalLock = new Object(); + private static LongObjectHashMap openDisplayMap = new LongObjectHashMap(); // handle -> name + private static List
@@ -156,7 +169,7 @@ public class X11Util {
System.err.println("X11Util.Display: Shutdown (JVM shutdown: "+isJVMShuttingDown+
", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
", reusable (open, marked uncloseable): "+reusableDisplayList.size()+
- ", pending (post closing): "+pendingDisplayList.size()+
+ ", pending (open in creation order): "+pendingDisplayList.size()+
")");
if(DEBUG) {
Thread.dumpStack();
@@ -227,14 +240,6 @@ public class X11Util {
private X11Util() {}
- // not exactly thread safe, but good enough for our purpose,
- // which is to tag a NamedDisplay uncloseable after creation.
- private static Object globalLock = new Object();
- private static LongObjectHashMap openDisplayMap = new LongObjectHashMap(); // handle -> name
- private static List
- * The default implementation is a
* Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 583fde07f..b16b0c75c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -153,6 +153,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
@Override
public boolean close() {
+ toolkitLock.dispose();
if(0 != handle) {
handle = 0;
return true;
@@ -162,7 +163,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
@Override
public String toString() {
- return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+"]";
+ return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", "+toolkitLock+"]";
}
/**
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index 40aaa8a25..4f4bb629b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -33,7 +33,6 @@
package javax.media.nativewindow;
-import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -43,6 +42,7 @@ import java.util.Map;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NativeWindowFactoryImpl;
+import jogamp.nativewindow.ResourceToolkitLock;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
@@ -93,13 +93,6 @@ public abstract class NativeWindowFactory {
private static ToolkitLock jawtUtilJAWTToolkitLock;
- public static final String X11JAWTToolkitLockClassName = "jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock" ;
- public static final String X11ToolkitLockClassName = "jogamp.nativewindow.x11.X11ToolkitLock" ;
-
- private static Class> x11JAWTToolkitLockClass;
- private static Constructor> x11JAWTToolkitLockConstructor;
- private static Class> x11ToolkitLockClass;
- private static Constructor> x11ToolkitLockConstructor;
private static boolean requiresToolkitLock;
private static volatile boolean isJVMShuttingDown = false;
@@ -266,16 +259,6 @@ public abstract class NativeWindowFactory {
// register either our default factory or (if exist) the X11/AWT one -> AWT Component
registerFactory(ReflectionUtil.getClass(ReflectionUtil.AWTNames.ComponentClass, false, cl), factory);
}
-
- if( TYPE_X11 == nativeWindowingTypePure ) {
- // passing through RuntimeException if not exists intended
- x11ToolkitLockClass = ReflectionUtil.getClass(X11ToolkitLockClassName, false, cl);
- x11ToolkitLockConstructor = ReflectionUtil.getConstructor(x11ToolkitLockClass, new Class[] { long.class } );
- if( isAWTAvailable() ) {
- x11JAWTToolkitLockClass = ReflectionUtil.getClass(X11JAWTToolkitLockClassName, false, cl);
- x11JAWTToolkitLockConstructor = ReflectionUtil.getConstructor(x11JAWTToolkitLockClass, new Class[] { long.class } );
- }
- }
if(DEBUG) {
System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock);
@@ -300,6 +283,7 @@ public abstract class NativeWindowFactory {
GraphicsConfigurationFactory.shutdown();
}
shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
+ // SharedResourceToolkitLock.shutdown(DEBUG); // not used yet
if(DEBUG) {
System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
}
@@ -358,16 +342,9 @@ public abstract class NativeWindowFactory {
/**
* Provides the default {@link ToolkitLock} for
+ * Toolkit locks are created solely via {@link NativeWindowFactory}.
+ *
+ * One use case is the AWT locking on X11, see {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}.
+ *
+ * Shall be called when instance is no more required.
+ *
+ * A resource handle maybe used within a unique object
+ * and can be synchronized across threads via an instance of ResourceToolkitLock.
+ *
+ * A resource handle maybe used within many objects
+ * and can be synchronized across threads via an unique instance of SharedResourceToolkitLock.
+ *
+ * Implementation holds a synchronized map from handle to reference counted {@link SharedResourceToolkitLock}.
+ * New elements are added via {@link #get(long)} if new
+ * and removed via {@link #dispose()} if no more referenced.
+ *
@@ -183,11 +192,12 @@ public abstract class Display {
*
* @param type
* @param name
- * @param fromIndex start index, then increasing until found or end of list *
+ * @param fromIndex start index, then increasing until found or end of list
+ * @paran shared if true, only shared instances are found, otherwise also exclusive
* @return
*/
- public static Display getFirstDisplayOf(String type, String name, int fromIndex) {
- return getDisplayOfImpl(type, name, fromIndex, 1);
+ public static Display getFirstDisplayOf(String type, String name, int fromIndex, boolean shared) {
+ return getDisplayOfImpl(type, name, fromIndex, 1, shared);
}
/**
@@ -195,19 +205,22 @@ public abstract class Display {
* @param type
* @param name
* @param fromIndex start index, then decreasing until found or end of list. -1 is interpreted as size - 1.
+ * @paran shared if true, only shared instances are found, otherwise also exclusive
* @return
*/
- public static Display getLastDisplayOf(String type, String name, int fromIndex) {
- return getDisplayOfImpl(type, name, fromIndex, -1);
+ public static Display getLastDisplayOf(String type, String name, int fromIndex, boolean shared) {
+ return getDisplayOfImpl(type, name, fromIndex, -1, shared);
}
- private static Display getDisplayOfImpl(String type, String name, int fromIndex, int incr) {
+ private static Display getDisplayOfImpl(String type, String name, int fromIndex, int incr, boolean shared) {
synchronized(displayList) {
int i = fromIndex >= 0 ? fromIndex : displayList.size() - 1 ;
while( ( incr > 0 ) ? i < displayList.size() : i >= 0 ) {
Display display = (Display) displayList.get(i);
if( display.getType().equals(type) &&
- display.getName().equals(name) ) {
+ display.getName().equals(name) &&
+ ( !shared || shared && !display.isExclusive() )
+ ) {
return display;
}
i+=incr;
diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java
index abae94ab6..1bf47f4aa 100644
--- a/src/newt/classes/com/jogamp/newt/NewtFactory.java
+++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java
@@ -305,7 +305,7 @@ public class NewtFactory {
* Instantiate a Display entity using the native handle.
*/
public static Display createDisplay(String type, long handle, boolean reuse) {
- return DisplayImpl.create(type, null, handle, false);
+ return DisplayImpl.create(type, null, handle, reuse);
}
public static boolean isScreenCompatible(NativeWindow parent, Screen childScreen) {
diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java
index 26f19ad6b..cfbcc988a 100644
--- a/src/newt/classes/com/jogamp/newt/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/Screen.java
@@ -145,7 +145,7 @@ public abstract class Screen {
public abstract Display getDisplay();
/**
- * @return the screen fully qualified Screen name,
+ * @return The screen fully qualified Screen name,
* which is a key of {@link com.jogamp.newt.Display#getFQName()} + {@link #getIndex()}.
*/
public abstract String getFQName();
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index bca7f6e5b..daeb3e886 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -42,6 +42,7 @@ import com.jogamp.newt.event.NEWTEventConsumer;
import jogamp.newt.event.NEWTEventTask;
import com.jogamp.newt.util.EDTUtil;
import java.util.ArrayList;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
@@ -66,7 +67,7 @@ public abstract class DisplayImpl extends Display {
name = display.validateDisplayName(name, handle);
synchronized(displayList) {
if(reuse) {
- Display display0 = Display.getLastDisplayOf(type, name, -1);
+ Display display0 = Display.getLastDisplayOf(type, name, -1, true /* shared only */);
if(null != display0) {
if(DEBUG) {
System.err.println("Display.create() REUSE: "+display0+" "+getThreadName());
@@ -74,9 +75,9 @@ public abstract class DisplayImpl extends Display {
return display0;
}
}
+ display.exclusive = !reuse;
display.name = name;
display.type=type;
- display.destroyWhenUnused=false;
display.refCount=0;
display.id = serialno++;
display.fqname = getFQName(display.type, display.name, display.id);
@@ -94,7 +95,7 @@ public abstract class DisplayImpl extends Display {
throw new RuntimeException(e);
}
}
-
+
@Override
public boolean equals(Object obj) {
if (obj == null) {
@@ -116,10 +117,12 @@ public abstract class DisplayImpl extends Display {
return true;
}
+ @Override
public int hashCode() {
return hashCode;
}
+ @Override
public synchronized final void createNative()
throws NativeWindowException
{
@@ -148,10 +151,6 @@ public abstract class DisplayImpl extends Display {
}
}
- protected boolean shallRunOnEDT() {
- return true;
- }
-
protected EDTUtil createEDTUtil() {
final EDTUtil def;
if(NewtFactory.useEDT()) {
@@ -179,12 +178,7 @@ public abstract class DisplayImpl extends Display {
if(DEBUG) {
System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil);
}
- if(null != oldEDTUtil) {
- stopEDT( new Runnable() { public void run() {} } );
- // ready for restart ..
- oldEDTUtil.waitUntilStopped();
- oldEDTUtil.reset();
- }
+ removeEDT( new Runnable() { public void run() {} } );
edtUtil = newEDTUtil;
return oldEDTUtil;
}
@@ -194,16 +188,19 @@ public abstract class DisplayImpl extends Display {
return edtUtil;
}
- private void stopEDT(final Runnable task) {
- if( shallRunOnEDT() && null!=edtUtil ) {
+ private void removeEDT(final Runnable task) {
+ if(null!=edtUtil) {
edtUtil.invokeStop(task);
+ // ready for restart ..
+ edtUtil.waitUntilStopped();
+ edtUtil.reset();
} else {
task.run();
}
}
public void runOnEDTIfAvail(boolean wait, final Runnable task) {
- if( shallRunOnEDT() && null!=edtUtil && !edtUtil.isCurrentThreadEDT()) {
+ if( null!=edtUtil && !edtUtil.isCurrentThreadEDT()) {
edtUtil.invoke(wait, task);
} else {
task.run();
@@ -212,18 +209,17 @@ public abstract class DisplayImpl extends Display {
public boolean validateEDT() {
if(0==refCount && null==aDevice && null != edtUtil && edtUtil.isRunning()) {
- stopEDT( new Runnable() {
+ removeEDT( new Runnable() {
public void run() {
// nop
}
} );
- edtUtil.waitUntilStopped();
- edtUtil.reset();
return true;
}
return false;
}
+ @Override
public synchronized final void destroy() {
if(DEBUG) {
dumpDisplayList("Display.destroy("+getFQName()+") BEGIN");
@@ -239,17 +235,13 @@ public abstract class DisplayImpl extends Display {
}
final AbstractGraphicsDevice f_aDevice = aDevice;
final DisplayImpl f_dpy = this;
- stopEDT( new Runnable() {
+ removeEDT( new Runnable() {
public void run() {
if ( null != f_aDevice ) {
f_dpy.closeNativeImpl();
}
}
} );
- if(null!=edtUtil) {
- edtUtil.waitUntilStopped();
- edtUtil.reset();
- }
aDevice = null;
refCount=0;
if(DEBUG) {
@@ -290,21 +282,30 @@ public abstract class DisplayImpl extends Display {
protected abstract void createNativeImpl();
protected abstract void closeNativeImpl();
+ @Override
public final int getId() {
return id;
}
+ @Override
public final String getType() {
return type;
}
+ @Override
public final String getName() {
return name;
}
+ @Override
public final String getFQName() {
return fqname;
}
+
+ @Override
+ public final boolean isExclusive() {
+ return exclusive;
+ }
public static final String nilString = "nil" ;
@@ -324,9 +325,10 @@ public abstract class DisplayImpl extends Display {
sb.append(name);
sb.append("-");
sb.append(id);
- return sb.toString().intern();
+ return sb.toString();
}
+ @Override
public final long getHandle() {
if(null!=aDevice) {
return aDevice.getHandle();
@@ -334,14 +336,17 @@ public abstract class DisplayImpl extends Display {
return 0;
}
+ @Override
public final AbstractGraphicsDevice getGraphicsDevice() {
return aDevice;
}
+ @Override
public synchronized final boolean isNativeValid() {
return null != aDevice;
}
+ @Override
public boolean isEDTRunning() {
if(null!=edtUtil) {
return edtUtil.isRunning();
@@ -351,7 +356,7 @@ public abstract class DisplayImpl extends Display {
@Override
public String toString() {
- return "NEWT-Display["+getFQName()+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", edtRunning "+isEDTRunning()+", "+aDevice+"]";
+ return "NEWT-Display["+getFQName()+", excl "+exclusive+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", edtRunning "+isEDTRunning()+", "+aDevice+"]";
}
protected abstract void dispatchMessagesNative();
@@ -403,6 +408,7 @@ public abstract class DisplayImpl extends Display {
eventTask.notifyCaller();
}
+ @Override
public void dispatchMessages() {
// System.err.println("Display.dispatchMessages() 0 "+this+" "+getThreadName());
if(0==refCount || // no screens
@@ -475,20 +481,23 @@ public abstract class DisplayImpl extends Display {
public interface DisplayRunnable
- * In case {@link X11Util#HAS_XLOCKDISPLAY_BUG} and {@link X11Util#XINITTHREADS_ALWAYS_ENABLED},
- * we use null locking. Even though this seems not to be rational, it gives most stable results on all platforms.
- *
- * Otherwise we use basic locking via the constructor {@link X11GraphicsDevice#X11GraphicsDevice(long, int, boolean)},
- * since it is possible to share this device via {@link com.jogamp.newt.NewtFactory#createDisplay(String, boolean)}.
- * null
.
* NOP
, just setting the handle to null
.
+ * The default implementation {@link ToolkitLock#dispose() dispose} it's {@link ToolkitLock} and sets the handle to null
.
* type
, a singleton instance.
- *
*
- *
*/
public static ToolkitLock getDefaultToolkitLock(String type) {
@@ -390,84 +367,36 @@ public abstract class NativeWindowFactory {
/**
* Creates the default {@link ToolkitLock} for
- *
- *
- *
- * type
and deviceHandle
.
- *
*
- *
*/
public static ToolkitLock createDefaultToolkitLock(String type, long deviceHandle) {
if( requiresToolkitLock() ) {
- if( TYPE_X11 == type ) {
- if( 0== deviceHandle ) {
- throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11");
- }
- return createX11ToolkitLock(deviceHandle);
- }
+ return ResourceToolkitLock.create();
}
return NativeWindowFactoryImpl.getNullToolkitLock();
}
/**
* Creates the default {@link ToolkitLock} for
- *
- *
- *
- * type
and deviceHandle
.
- *
*
- *
*/
public static ToolkitLock createDefaultToolkitLock(String type, String sharedType, long deviceHandle) {
if( requiresToolkitLock() ) {
- if( TYPE_X11 == type ) {
- if( 0== deviceHandle ) {
- throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11");
- }
- if( TYPE_AWT == sharedType && isAWTAvailable() ) {
- return createX11AWTToolkitLock(deviceHandle);
- }
- return createX11ToolkitLock(deviceHandle);
+ if( TYPE_AWT == sharedType && isAWTAvailable() ) {
+ return getAWTToolkitLock();
}
+ return ResourceToolkitLock.create();
}
return NativeWindowFactoryImpl.getNullToolkitLock();
}
-
- protected static ToolkitLock createX11AWTToolkitLock(long deviceHandle) {
- try {
- if(DEBUG) {
- System.err.println("NativeWindowFactory.createX11AWTToolkitLock(0x"+Long.toHexString(deviceHandle)+")");
- // Thread.dumpStack();
- }
- return (ToolkitLock) x11JAWTToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)});
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- protected static ToolkitLock createX11ToolkitLock(long deviceHandle) {
- try {
- return (ToolkitLock) x11ToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)});
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
-
+
/** Returns the appropriate NativeWindowFactory to handle window
objects of the given type. The windowClass might be {@link
NativeWindow NativeWindow}, in which case the client has
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
index 30f9660f0..18b7cf5d9 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
@@ -33,12 +33,26 @@ import jogamp.nativewindow.Debug;
/**
* Marker for a singleton global recursive blocking lock implementation,
* optionally locking a native windowing toolkit as well.
- *
- *
- *
- *
- *
- *
- *
- * One use case is the AWT locking on X11, see {@link jogamp.nativewindow.jawt.JAWTToolkitLock}.
+ *
+ */
+ public static int shutdown(boolean verbose) {
+ if(DEBUG || verbose || handle2Lock.size() > 0 ) {
+ System.err.println("SharedResourceToolkitLock: Shutdown (open: "+handle2Lock.size()+")");
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ if( handle2Lock.size() > 0) {
+ dumpOpenDisplayConnections();
+ }
+ }
+ return handle2Lock.size();
+ }
+
+ public static void dumpOpenDisplayConnections() {
+ System.err.println("SharedResourceToolkitLock: Open ResourceToolkitLock's: "+handle2Lock.size());
+ int i=0;
+ for(Iterator
- * This strategy should only be used if AWT is using the underlying native windowing toolkit
- * in a not intrinsic thread safe manner, e.g. under X11 where no XInitThreads() call
- * is issued before any other X11 usage. This is the current situation for e.g. Webstart or Applets.
- */
-public class X11JAWTToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
-
- public X11JAWTToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
- }
-
- public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.lock() - native: "+(null==lock)); }
- JAWTUtil.lockToolkit();
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
- }
- }
-
- public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
- }
- JAWTUtil.unlockToolkit();
- }
-}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
index 736718de8..467809284 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
@@ -127,7 +127,8 @@ public class X11JAWTWindow extends JAWTWindow {
}
protected Point getLocationOnScreenNativeImpl(int x, int y) {
- return X11Lib.GetRelativeLocation( getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ // surface is locked and hence the device
+ return X11Lib.GetRelativeLocation(getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
}
// Variables for lockSurface/unlockSurface
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java
deleted file mode 100644
index 5166ef577..000000000
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.nativewindow.x11;
-
-import javax.media.nativewindow.ToolkitLock;
-
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-
-/**
- * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock}
- * utilizing {@link X11Util#XLockDisplay(long)}.
- *
- * This strategy should not be used in case XInitThreads() is being used,
- * or a higher level toolkit lock is required, ie AWT lock.
- */
-public class X11ToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
-
- public X11ToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
- }
-
- public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.lock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
- }
- }
-
- public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
- }
- }
-}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 2ea75c7fb..60f54eb3c 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -42,8 +42,8 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
-
import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
/**
* Contains a thread safe X11 utility to retrieve display connections.
@@ -80,25 +80,15 @@ public class X11Util {
*/
public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true);
- /** Value is true
, best 'stable' results if always using XInitThreads(). */
- public static final boolean XINITTHREADS_ALWAYS_ENABLED = true;
-
- /** Value is true
, best 'stable' results if not using XLockDisplay/XUnlockDisplay at all. */
- public static final boolean HAS_XLOCKDISPLAY_BUG = true;
-
public static final boolean DEBUG = Debug.debug("X11Util");
public static final boolean XSYNC_ENABLED = Debug.isPropertyDefined("nativewindow.debug.X11Util.XSync", true);
public static final boolean XERROR_STACKDUMP = DEBUG || Debug.isPropertyDefined("nativewindow.debug.X11Util.XErrorStackDump", true);
private static final boolean TRACE_DISPLAY_LIFECYCLE = Debug.isPropertyDefined("nativewindow.debug.X11Util.TraceDisplayLifecycle", true);
private static String nullDisplayName = null;
- private static boolean isX11LockAvailable = false;
- private static boolean requiresX11Lock = true;
private static volatile boolean isInit = false;
private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues
- private static int setX11ErrorHandlerRecCount = 0;
private static Object setX11ErrorHandlerLock = new Object();
-
/**
* Called by {@link NativeWindowFactory#initSingleton()}
@@ -115,9 +105,7 @@ public class X11Util {
throw new NativeWindowException("NativeWindow X11 native library load error.");
}
- final boolean callXInitThreads = XINITTHREADS_ALWAYS_ENABLED ;
- final boolean isXInitThreadsOK = initialize0( callXInitThreads, XERROR_STACKDUMP);
- isX11LockAvailable = isXInitThreadsOK && !HAS_XLOCKDISPLAY_BUG ;
+ final boolean isInitOK = initialize0( XERROR_STACKDUMP );
final long dpy = X11Lib.XOpenDisplay(null);
if(0 != dpy) {
@@ -134,9 +122,7 @@ public class X11Util {
}
if(DEBUG) {
- System.err.println("X11Util requiresX11Lock "+requiresX11Lock+
- ", XInitThreads [called "+callXInitThreads+", OK "+isXInitThreadsOK+"]"+
- ", isX11LockAvailable "+isX11LockAvailable+
+ System.err.println("X11Util init OK "+isInitOK+"]"+
", X11 Display(NULL) <"+nullDisplayName+">"+
", XSynchronize Enabled: "+XSYNC_ENABLED);
// Thread.dumpStack();
@@ -199,31 +185,14 @@ public class X11Util {
}
}
}
-
- public static synchronized boolean isNativeLockAvailable() {
- return isX11LockAvailable;
- }
-
- public static synchronized boolean requiresToolkitLock() {
- return requiresX11Lock;
+
+ public static boolean requiresToolkitLock() {
+ return true; // JAWT locking: yes, instead of native X11 locking w use a recursive lock.
}
-
+
public static void setX11ErrorHandler(boolean onoff, boolean quiet) {
synchronized(setX11ErrorHandlerLock) {
- if(onoff) {
- if(0==setX11ErrorHandlerRecCount) {
- setX11ErrorHandler0(true, quiet);
- }
- setX11ErrorHandlerRecCount++;
- } else {
- if(0 >= setX11ErrorHandlerRecCount) {
- throw new InternalError();
- }
- setX11ErrorHandlerRecCount--;
- if(0==setX11ErrorHandlerRecCount) {
- setX11ErrorHandler0(false, false);
- }
- }
+ setX11ErrorHandler0(onoff, quiet);
}
}
@@ -492,52 +461,50 @@ public class X11Util {
*******************************/
public static long XOpenDisplay(String arg0) {
- NativeWindowFactory.getDefaultToolkitLock().lock();
- try {
- long handle = X11Lib.XOpenDisplay(arg0);
- if(XSYNC_ENABLED && 0 != handle) {
- X11Lib.XSynchronize(handle, true);
- }
- if(TRACE_DISPLAY_LIFECYCLE) {
- System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
- // Thread.dumpStack();
- }
- return handle;
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
+ long handle = X11Lib.XOpenDisplay(arg0);
+ if(XSYNC_ENABLED && 0 != handle) {
+ X11Lib.XSynchronize(handle, true);
+ }
+ if(TRACE_DISPLAY_LIFECYCLE) {
+ System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
+ // Thread.dumpStack();
}
+ return handle;
}
public static int XCloseDisplay(long display) {
- NativeWindowFactory.getDefaultToolkitLock().lock();
+ if(TRACE_DISPLAY_LIFECYCLE) {
+ System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display));
+ // Thread.dumpStack();
+ }
+ int res = -1;
try {
- if(TRACE_DISPLAY_LIFECYCLE) {
- System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display));
- // Thread.dumpStack();
- }
- int res = -1;
- X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
- try {
- res = X11Lib.XCloseDisplay(display);
- } catch (Exception ex) {
- System.err.println("X11Util: Catched Exception:");
- ex.printStackTrace();
- } finally {
- X11Util.setX11ErrorHandler(false, false);
- }
- return res;
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
+ res = X11Lib.XCloseDisplay(display);
+ } catch (Exception ex) {
+ System.err.println("X11Util: Catched Exception:");
+ ex.printStackTrace();
}
+ return res;
}
static volatile boolean XineramaFetched = false;
static long XineramaLibHandle = 0;
static long XineramaQueryFunc = 0;
- public static boolean XineramaIsEnabled(long display) {
- if(0==display) {
- throw new IllegalArgumentException("Display NULL");
+ public static boolean XineramaIsEnabled(X11GraphicsDevice device) {
+ if(null == device) {
+ throw new IllegalArgumentException("X11 Display device is NULL");
+ }
+ device.lock();
+ try {
+ return XineramaIsEnabled(device.getHandle());
+ } finally {
+ device.unlock();
+ }
+ }
+ public static boolean XineramaIsEnabled(long displayHandle) {
+ if( 0 == displayHandle ) {
+ throw new IllegalArgumentException("X11 Display handle is NULL");
}
if(!XineramaFetched) { // volatile: ok
synchronized(X11Util.class) {
@@ -551,9 +518,9 @@ public class X11Util {
}
}
if(0!=XineramaQueryFunc) {
- final boolean res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, display);
+ final boolean res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, displayHandle);
if(DEBUG) {
- System.err.println("XineramaIsEnabled: "+res);
+ System.err.println("XineramaIsEnabled: 0x"+Long.toHexString(displayHandle)+": "+res);
}
return res;
} else if(DEBUG) {
@@ -566,7 +533,7 @@ public class X11Util {
private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
- private static native boolean initialize0(boolean firstUIActionOnProcess, boolean debug);
+ private static native boolean initialize0(boolean debug);
private static native void shutdown0();
private static native void setX11ErrorHandler0(boolean onoff, boolean quiet);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
index 1de03e8be..b152f0f97 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
@@ -91,7 +91,7 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
final long displayHandleAWT = X11SunJDKReflection.graphicsDeviceGetDisplay(device);
final long displayHandle;
- boolean owner = false;
+ final boolean owner;
if(0==displayHandleAWT) {
displayHandle = X11Util.openDisplay(null);
owner = true;
@@ -112,9 +112,8 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
System.err.println(getThreadName()+" - X11AWTGraphicsConfigurationFactory: AWT dpy "+displayName+" / "+toHexString(displayHandleAWT)+", create X11 display "+toHexString(displayHandle));
}
}
- final ToolkitLock lock = owner ?
- NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_AWT) : // own non-shared X11 display connection, no X11 lock
- NativeWindowFactory.createDefaultToolkitLock(NativeWindowFactory.TYPE_X11, NativeWindowFactory.TYPE_AWT, displayHandle);
+ // Global JAWT lock required - No X11 resource locking due to private display connection
+ final ToolkitLock lock = NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_AWT);
final X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, lock, owner);
final X11GraphicsScreen x11Screen = new X11GraphicsScreen(x11Device, awtScreen.getIndex());
if(DEBUG) {
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index fcba8580c..afdd413eb 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -178,11 +178,14 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
char threadName[80];
char errCodeStr[80];
char reqCodeStr[80];
-
int shallBeDetached = 0;
- JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv *jniEnv = NULL;
+ if( errorHandlerDebug || errorHandlerThrowException ) {
+ jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ }
(void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
+
snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
@@ -191,7 +194,7 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
threadName, e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
(int)e->request_code, (int)e->minor_code, reqCodeStr);
- if( errorHandlerDebug ) {
+ if( errorHandlerDebug && NULL != jniEnv ) {
(*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
}
@@ -246,16 +249,17 @@ static int x11IOErrorHandler(Display *dpy)
{
const char * dpyName = XDisplayName(NULL);
const char * errnoStr = strerror(errno);
- char threadName[80];
int shallBeDetached = 0;
- JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
-
- (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
+ JNIEnv *jniEnv = NULL;
- fprintf(stderr, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s\n", threadName, dpy, dpyName, errnoStr);
+ fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errnoStr);
(*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
+ jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
if (NULL != jniEnv) {
+ char threadName[80];
+ (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
+
NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s", threadName, dpy, dpyName, errnoStr);
if (shallBeDetached) {
@@ -305,6 +309,7 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboo
_initClazzAccess(env);
x11IOErrorHandlerEnable(1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 0, 0 /* no dpy, no sync */);
_initialized=1;
if(JNI_TRUE == debug) {
fprintf(stderr, "Info: NativeWindow native init passed\n");
@@ -315,6 +320,7 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboo
JNIEXPORT void JNICALL
Java_jogamp_nativewindow_x11_X11Util_shutdown0(JNIEnv *env, jclass _unused) {
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0 /* no dpy, no sync */);
x11IOErrorHandlerEnable(0, env);
}
@@ -347,7 +353,7 @@ Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Lja
}
NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 1, 0, 0);
_res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0);
count = _ptr3[0];
if (arg3 != NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
@@ -382,7 +388,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
} else {
r = 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
return r;
}
@@ -396,7 +402,7 @@ Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused,
}
NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 1, 0, 0);
r = (jint) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0);
return r;
}
@@ -439,7 +445,7 @@ Java_jogamp_nativewindow_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused
}
NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 0, 0);
_res = XCloseDisplay((Display *) (intptr_t) display);
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0);
return _res;
}
@@ -497,7 +503,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
if (visual==NULL)
{
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NativewindowCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
return 0;
}
@@ -541,7 +547,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
XSelectInput(dpy, window, 0); // no events
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
@@ -569,7 +575,7 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyDummyWindow
XUnmapWindow(dpy, w);
XSync(dpy, False);
XDestroyWindow(dpy, w);
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
}
/*
@@ -597,7 +603,7 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_x11_X11Lib_GetRelativeLocatio
res = XTranslateCoordinates(dpy, src_win, dest_win, src_x, src_y, &dest_x, &dest_y, &child);
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0);
DBG_PRINT( "X11: GetRelativeLocation0: %p %d/%d -> %p %d/%d - ok: %d\n",
(void*)src_win, src_x, src_y, (void*)dest_win, dest_x, dest_y, (int)res);
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 1e9a0e9eb..391bccf3d 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -113,16 +113,22 @@ public abstract class Display {
*/
public abstract int removeReference();
+ /**
+ * Return the {@link AbstractGraphicsDevice} used for depending resources lifecycle,
+ * i.e. {@link Screen} and {@link Window}, as well as the event dispatching (EDT). */
public abstract AbstractGraphicsDevice getGraphicsDevice();
/**
- * @return the fully qualified Display name,
- * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}
+ * Return the handle of the {@link AbstractGraphicsDevice} as returned by {@link #getGraphicsDevice()}.
*/
- public abstract String getFQName();
-
public abstract long getHandle();
+ /**
+ * @return The fully qualified Display name,
+ * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}.
+ */
+ public abstract String getFQName();
+
/**
* @return this display internal serial id
*/
@@ -141,6 +147,9 @@ public abstract class Display {
*/
public abstract String getType();
+ /** Return true if this instance is exclusive, i.e. will not be shared. */
+ public abstract boolean isExclusive();
+
/**
* Sets a new {@link EDTUtil} and returns the previous one.
*