[libjogl2-java] 53/58: Imported Upstream version 2.1.5
Tony Mancill
tmancill at moszumanska.debian.org
Thu Sep 4 03:59:30 UTC 2014
This is an automated email from the git hooks/post-receive script.
tmancill pushed a commit to branch master
in repository libjogl2-java.
commit 5698a919a8fabf1eed536ec27f5228c3fce3e5ef
Author: tony mancill <tmancill at debian.org>
Date: Fri Aug 29 18:47:15 2014 -0700
Imported Upstream version 2.1.5
---
doc/HowToBuild.html | 13 +-
doc/Platforms.txt | 28 ++
make/config/jogl/gl-common-gpubufferonly.cfg | 1 +
make/config/jogl/gl-common.cfg | 1 +
.../jogl/gl4bc-common-cpubufferJavaCode.java | 4 +
make/config/jogl/glx-CustomCCode.c | 69 ++++-
make/config/jogl/glx-CustomJavaCode.java | 19 ++
make/config/jogl/glx-x11.cfg | 2 +
make/config/jogl/glxext.cfg | 2 +-
make/scripts/make.jogl.all.macosx-clang.sh | 1 +
make/scripts/tests-win.bat | 6 +-
make/scripts/tests-x64-dbg.bat | 5 +-
make/scripts/tests.sh | 27 +-
.../com/jogamp/graph/curve/opengl/RenderState.java | 6 +-
.../com/jogamp/graph/curve/opengl/Renderer.java | 8 +
.../com/jogamp/opengl/util/GLDrawableUtil.java | 21 ++
.../com/jogamp/opengl/util/GLPixelBuffer.java | 14 +-
.../jogamp/opengl/util/GLPixelStorageModes.java | 70 ++---
.../com/jogamp/opengl/util/GLReadBufferUtil.java | 35 ++-
.../com/jogamp/opengl/util/PNGPixelRect.java | 80 +++++-
.../com/jogamp/opengl/util/TileRendererBase.java | 15 +-
.../com/jogamp/opengl/util/av/GLMediaPlayer.java | 8 +-
.../opengl/util/awt/AWTGLReadBufferUtil.java | 46 +++-
.../com/jogamp/opengl/util/texture/TextureIO.java | 40 ++-
.../opengl/util/texture/TextureSequence.java | 12 +-
src/jogl/classes/javax/media/opengl/GLBase.java | 14 +-
src/jogl/classes/javax/media/opengl/GLContext.java | 13 +-
src/jogl/classes/javax/media/opengl/GLProfile.java | 141 +++++++---
.../classes/javax/media/opengl/awt/GLCanvas.java | 4 +-
.../classes/javax/media/opengl/awt/GLJPanel.java | 127 ++++++---
.../jogamp/graph/curve/opengl/RenderStateImpl.java | 4 -
.../jogamp/opengl/GLBufferObjectTracker.java | 4 +-
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 14 +-
src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 4 +-
.../classes/jogamp/opengl/GLFBODrawableImpl.java | 4 +-
src/jogl/classes/jogamp/opengl/GLStateTracker.java | 16 +-
.../jogamp/opengl/openal/av/ALAudioSink.java | 286 ++++++++++++++-------
.../jogamp/opengl/util/av/GLMediaPlayerImpl.java | 4 +-
.../jogamp/opengl/util/av/impl/FFMPEGNatives.java | 43 ++--
.../opengl/util/av/impl/FFMPEGv08Natives.java | 34 +--
.../opengl/util/av/impl/FFMPEGv09Natives.java | 34 +--
.../opengl/util/av/impl/FFMPEGv10Natives.java | 34 +--
.../jogamp/opengl/util/jpeg/JPEGDecoder.java | 167 +++++-------
.../x11/glx/X11GLXGraphicsConfiguration.java | 39 ++-
.../glx/X11GLXGraphicsConfigurationFactory.java | 8 +-
src/jogl/native/libav/ffmpeg_impl_template.c | 131 +++++++---
src/jogl/native/libav/ffmpeg_tool.h | 1 -
.../com/jogamp/nativewindow/awt/JAWTWindow.java | 49 ++--
.../media/nativewindow/NativeWindowFactory.java | 23 +-
.../media/nativewindow/util/PixelFormatUtil.java | 3 +-
.../jogamp/nativewindow/SurfaceUpdatedHelper.java | 25 +-
.../classes/jogamp/nativewindow/awt/AWTMisc.java | 19 +-
.../classes/jogamp/nativewindow/jawt/JAWTUtil.java | 95 ++++---
.../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 4 +-
.../classes/com/jogamp/newt/opengl/GLWindow.java | 40 +--
.../classes/com/jogamp/newt/swt/NewtCanvasSWT.java | 32 ++-
src/newt/classes/jogamp/newt/DisplayImpl.java | 3 +-
src/newt/classes/jogamp/newt/WindowImpl.java | 46 ++--
src/newt/native/MacWindow.m | 20 +-
.../opengl/test/android/MovieCubeActivity0.java | 47 ++--
.../test/junit/graph/TextRendererGLELBase.java | 195 ++++++++++++++
.../test/junit/jogl/acore/GLReadBuffer00Base.java | 117 +++++++++
.../jogl/acore/TestGLReadBuffer01GLCanvasAWT.java | 252 ++++++++++++++++++
.../jogl/acore/TestGLReadBuffer01GLJPanelAWT.java | 254 ++++++++++++++++++
.../jogl/acore/TestGLReadBuffer01GLWindowNEWT.java | 195 ++++++++++++++
.../junit/jogl/acore/TestMapBufferRead01NEWT.java | 82 ++++--
.../jogl/demos/es2/TextureSequenceCubeES2.java | 6 +-
.../junit/jogl/demos/es2/av/CrossFadePlayer.java | 211 +++++++++++++++
.../test/junit/jogl/demos/es2/av/MovieCube.java | 127 ++++++++-
.../test/junit/jogl/demos/es2/av/MovieSimple.java | 136 +++++++---
.../junit/newt/parenting/TestParenting01NEWT.java | 83 +++++-
.../jogamp/opengl/test/junit/util/UITestCase.java | 76 +++---
72 files changed, 3008 insertions(+), 791 deletions(-)
diff --git a/doc/HowToBuild.html b/doc/HowToBuild.html
index 1cb3bad..8b5d27e 100644
--- a/doc/HowToBuild.html
+++ b/doc/HowToBuild.html
@@ -94,8 +94,19 @@
<li>libxcursor-dev</li>
<li>Optional: Your card vendor's proprietary driver</li>
</ul>
+ One liner install command:
<pre>
-apt-get install git gcc libgl1-mesa-dev libglu1-mesa-dev xorg-dev libice-dev libsm-dev libx11-dev libxext-dev libxxf86vm-dev libxinerama-dev libxrandr-dev libxrender-dev libxcursor-dev
+apt-get install git-all gcc libgl1-mesa-dev libglu1-mesa-dev xorg-dev libice-dev libsm-dev libx11-dev libxext-dev libxxf86vm-dev libxinerama-dev libxrandr-dev libxrender-dev libxcursor-dev libc6-dev g++ libstdc++6 libstdc++6-4.7-dev
+ </pre>
+ Optional: Add <i>kernel</i> build utilities:
+ <pre>
+apt-get install kernel-package build-essential
+ </pre>
+ Optional: Add <i>multiarch</i> i386 next to amd64, requires Debian 7.00 or later:
+ <pre>
+dpkg --add-architecture i386
+apt-get update
+apt-get install ia32-libs ia32-libs-gtk gcc-multilib lib32gcc1 lib32gomp1 lib32itm1 lib32quadmath0 libc6-i386 libc6-dev-i386 g++-multilib lib32stdc++6
</pre>
</li>
<li> <b>OpenSuSE</b> 10.2 or later
diff --git a/doc/Platforms.txt b/doc/Platforms.txt
index 7fbb65b..00200ae 100644
--- a/doc/Platforms.txt
+++ b/doc/Platforms.txt
@@ -60,3 +60,31 @@
- PowerVR (ES2) 32bit only
(*) Regular tested component / platform
+
+virtualbox-4.3_4.3.8-92456
+ - Host Debian 8 (Jessie)
+ - Host GPU: NV w/ NV proprietary driver
+
+ - Guest Debian 7 (Wheezy)
+ - Mesa 8.0.5 LLVM:
+ - Onscreen: OK
+ - FBO: OK
+ - FBO.MSAA: NO (gl-error, failure)
+ - PBuffer: OK
+ - Bitmap: OK
+
+ - 3D Accel (Chromium 1.9):
+ - Onscreen: OK
+ - FBO: NO
+ - FBO.MSAA: NO (gl-error, failure)
+ - PBuffer: NO
+ - Bitmap: NO
+
+ - Guest Debian 8 (Jessie)
+ - Mesa 9.2.2 Gallium LLVM
+ - Onscreen: OK
+ - FBO: OK
+ - FBO.MSAA: NO (properly reporting: N/A)
+ - PBuffer: OK
+ - Bitmap: OK
+
diff --git a/make/config/jogl/gl-common-gpubufferonly.cfg b/make/config/jogl/gl-common-gpubufferonly.cfg
index 14671f3..9370d95 100644
--- a/make/config/jogl/gl-common-gpubufferonly.cfg
+++ b/make/config/jogl/gl-common-gpubufferonly.cfg
@@ -44,6 +44,7 @@ BufferObjectOnly glDrawElementsInstancedBaseVertex
BufferObjectOnly glDrawElementsInstancedBaseVertexBaseInstance
BufferObjectOnly glDrawRangeElements
BufferObjectOnly glDrawRangeElementsBaseVertex
+BufferObjectOnly glMultiDrawArraysIndirect
BufferObjectOnly glDrawArraysIndirect
BufferObjectOnly glDrawElementsIndirect
diff --git a/make/config/jogl/gl-common.cfg b/make/config/jogl/gl-common.cfg
index 74ead04..d5c4531 100644
--- a/make/config/jogl/gl-common.cfg
+++ b/make/config/jogl/gl-common.cfg
@@ -651,6 +651,7 @@ BufferObjectKind Element glDrawRangeElementsBaseVertex
BufferObjectKind Indirect glDrawArraysIndirect
BufferObjectKind Indirect glDrawElementsIndirect
+BufferObjectKind Indirect glMultiDrawArraysIndirect
# There are no PBOs in the embedded OpenGL variants right now
BufferObjectKind UnpackPixel glBitmap
diff --git a/make/config/jogl/gl4bc-common-cpubufferJavaCode.java b/make/config/jogl/gl4bc-common-cpubufferJavaCode.java
index a29f540..39dc9f6 100644
--- a/make/config/jogl/gl4bc-common-cpubufferJavaCode.java
+++ b/make/config/jogl/gl4bc-common-cpubufferJavaCode.java
@@ -7,6 +7,10 @@
@param indirect a direct or array-backed {@link java.nio.Buffer} */
public void glDrawElementsIndirect(int mode, int type, Buffer indirect);
+ /** Entry point to C language function: <code> void {@native glMultiDrawArraysIndirect}(GLenum mode, const void * indirect, GLsizei drawcount, GLsizei stride); </code> <br>Part of <code>GL_VERSION_4_3</code>, <code>GL_ARB_multi_draw_indirect</code>
+ @param indirect a direct or array-backed {@link java.nio.Buffer} */
+ public void glMultiDrawArraysIndirect(int mode, Buffer indirect, int drawcount, int stride);
+
/** Entry point to C language function: <code> void {@native glDrawElementsInstancedBaseInstance}(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLuint baseinstance); </code> <br>Part of <code>GL_VERSION_4_2</code>, <code>GL_ARB_base_instance</code>
@param indices a direct or array-backed {@link java.nio.Buffer} */
public void glDrawElementsInstancedBaseInstance(int mode, int count, int type, Buffer indices, int instancecount, int baseinstance);
diff --git a/make/config/jogl/glx-CustomCCode.c b/make/config/jogl/glx-CustomCCode.c
index 5c73dfe..b077c65 100644
--- a/make/config/jogl/glx-CustomCCode.c
+++ b/make/config/jogl/glx-CustomCCode.c
@@ -12,6 +12,8 @@
#define RTLD_DEFAULT NULL
#endif
+#include <string.h>
+
/* We expect glXGetProcAddressARB to be defined */
extern void (*glXGetProcAddressARB(const GLubyte *procname))();
@@ -124,7 +126,7 @@ Java_jogamp_opengl_x11_glx_GLX_dispatch_1glXChooseFBConfig(JNIEnv *env, jclass _
int * _attribList_ptr = NULL;
int * _nitems_ptr = NULL;
GLXFBConfig * _res;
- int count;
+ int count, i;
jobject jbyteSource;
jobject jbyteCopy;
if ( NULL != attribList ) {
@@ -139,6 +141,71 @@ Java_jogamp_opengl_x11_glx_GLX_dispatch_1glXChooseFBConfig(JNIEnv *env, jclass _
count = _nitems_ptr[0];
if (NULL == _res) return NULL;
+ /**
+ * Bug 961: Validate returned 'GLXFBConfig *', i.e. remove NULL pointer.
+ * Note: sizeof(GLXFBConfig) == sizeof(void*), a.k.a a pointer
+ */
+ // fprintf(stderr, "glXChooseFBConfig.0: Count %d\n", count);
+ i=0;
+ while( i < count ) {
+ if( NULL == _res[i] ) {
+ if( 0 < count-i-1 ) {
+ memmove(_res+i, _res+i+1, (count-i-1)*sizeof(GLXFBConfig));
+ }
+ count--;
+ } else {
+ i++;
+ }
+ }
+ // fprintf(stderr, "glXChooseFBConfig.X: Count %d\n", count);
+ _initClazzAccess(env);
+
+ jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(GLXFBConfig));
+ jbyteCopy = (*env)->CallStaticObjectMethod(env, clazzBuffers, cstrBuffers, jbyteSource);
+ (*env)->DeleteLocalRef(env, jbyteSource);
+ XFree(_res);
+
+ return jbyteCopy;
+}
+
+/* Java->C glue code:
+ * Java package: jogamp.opengl.x11.glx.GLX
+ * Java method: com.jogamp.common.nio.PointerBuffer dispatch_glXGetFBConfigs(long dpy, int screen, java.nio.IntBuffer nelements)
+ * C function: GLXFBConfig * glXGetFBConfigs(Display * dpy, int screen, int * nelements);
+ */
+JNIEXPORT jobject JNICALL
+Java_jogamp_opengl_x11_glx_GLX_dispatch_1glXGetFBConfigs(JNIEnv *env, jclass _unused, jlong dpy, jint screen, jobject nelements, jint nelements_byte_offset, jlong procAddress) {
+ typedef GLXFBConfig * (APIENTRY*_local_PFNGLXGETFBCONFIGSPROC)(Display * dpy, int screen, int * nelements);
+ _local_PFNGLXGETFBCONFIGSPROC ptr_glXGetFBConfigs;
+ int * _nelements_ptr = NULL;
+ GLXFBConfig * _res;
+ int count, i;
+ jobject jbyteSource;
+ jobject jbyteCopy;
+ if ( NULL != nelements ) {
+ _nelements_ptr = (int *) (((char*) (*env)->GetDirectBufferAddress(env, nelements)) + nelements_byte_offset);
+ }
+ ptr_glXGetFBConfigs = (_local_PFNGLXGETFBCONFIGSPROC) (intptr_t) procAddress;
+ assert(ptr_glXGetFBConfigs != NULL);
+ _res = (* ptr_glXGetFBConfigs) ((Display *) (intptr_t) dpy, (int) screen, (int *) _nelements_ptr);
+ count = _nelements_ptr[0];
+ if (NULL == _res) return NULL;
+
+ /**
+ * Bug 961: Validate returned 'GLXFBConfig *', i.e. remove NULL pointer.
+ * Note: sizeof(GLXFBConfig) == sizeof(void*), a.k.a a pointer
+ */
+ i=0;
+ while( i < count ) {
+ if( NULL == _res[i] ) {
+ if( 0 < count-i-1 ) {
+ memmove(_res+i, _res+i+1, (count-i-1)*sizeof(GLXFBConfig));
+ }
+ count--;
+ } else {
+ i++;
+ }
+ }
_initClazzAccess(env);
jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(GLXFBConfig));
diff --git a/make/config/jogl/glx-CustomJavaCode.java b/make/config/jogl/glx-CustomJavaCode.java
index 4cce05d..5a3ea39 100644
--- a/make/config/jogl/glx-CustomJavaCode.java
+++ b/make/config/jogl/glx-CustomJavaCode.java
@@ -60,6 +60,25 @@
@param nitems a direct only {@link java.nio.IntBuffer} */
private static native ByteBuffer dispatch_glXChooseFBConfig(long dpy, int screen, Object attribList, int attribList_byte_offset, Object nitems, int nitems_byte_offset, long procAddress);
+ /** Entry point to C language function: <code> GLXFBConfig * glXGetFBConfigs(Display * dpy, int screen, int * nelements); </code> <br>Part of <code>GLX_VERSION_1_3</code>
+ @param nelements a direct only {@link java.nio.IntBuffer} */
+ public static PointerBuffer glXGetFBConfigs(long dpy, int screen, IntBuffer nelements) {
+
+ if (!Buffers.isDirect(nelements))
+ throw new GLException("Argument \"nelements\" is not a direct buffer");
+ final long __addr_ = glxProcAddressTable._addressof_glXGetFBConfigs;
+ if (__addr_ == 0) {
+ throw new GLException(String.format("Method \"%s\" not available", "glXGetFBConfigs"));
+ }
+ final ByteBuffer _res = dispatch_glXGetFBConfigs(dpy, screen, nelements, Buffers.getDirectBufferByteOffset(nelements), __addr_);
+ if (_res == null) return null;
+ return PointerBuffer.wrap(Buffers.nativeOrder(_res));
+ }
+
+ /** Entry point to C language function: <code> GLXFBConfig * glXGetFBConfigs(Display * dpy, int screen, int * nelements); </code> <br>Part of <code>GLX_VERSION_1_3</code>
+ @param nelements a direct only {@link java.nio.IntBuffer} */
+ private static native ByteBuffer dispatch_glXGetFBConfigs(long dpy, int screen, Object nelements, int nelements_byte_offset, long procAddress);
+
/** Entry point to C language function: <code> XVisualInfo * glXChooseVisual(Display * dpy, int screen, int * attribList); </code> <br>Part of <code>GLX_VERSION_1_X</code>
@param attribList a direct only {@link java.nio.IntBuffer} */
diff --git a/make/config/jogl/glx-x11.cfg b/make/config/jogl/glx-x11.cfg
index 5955e0a..1c138c8 100644
--- a/make/config/jogl/glx-x11.cfg
+++ b/make/config/jogl/glx-x11.cfg
@@ -44,9 +44,11 @@ Ignore glXCreateContextAttribsARB
Ignore glXGetVisualFromFBConfigSGIX
ManuallyImplement glXGetVisualFromFBConfig
ManuallyImplement glXChooseFBConfig
+ManuallyImplement glXGetFBConfigs
ManuallyImplement glXChooseVisual
ForceProcAddressGen glXGetVisualFromFBConfig
ForceProcAddressGen glXChooseFBConfig
+ForceProcAddressGen glXGetFBConfigs
ForceProcAddressGen glXChooseVisual
# Ignore everything not in the GLX core (up through GLX 1.4)
diff --git a/make/config/jogl/glxext.cfg b/make/config/jogl/glxext.cfg
index c73753e..d158d24 100644
--- a/make/config/jogl/glxext.cfg
+++ b/make/config/jogl/glxext.cfg
@@ -60,6 +60,7 @@ CustomJavaCode GLXExtImpl private X11GLXContext _context;
Ignore glXGetVisualFromFBConfig
Ignore glXGetVisualFromFBConfigSGIX
Ignore glXChooseFBConfig
+Ignore glXGetFBConfigs
Ignore glXChooseVisual
Ignore glXCreateContext
Ignore glXDestroyContext
@@ -81,7 +82,6 @@ Ignore glXQueryExtensionsString
Ignore glXQueryServerString
Ignore glXGetClientString
Ignore glXGetCurrentDisplay
-Ignore glXChooseFBConfig
Ignore glXGetFBConfigAttrib
Ignore glXGetFBConfigs
Ignore glXGetVisualFromFBConfig
diff --git a/make/scripts/make.jogl.all.macosx-clang.sh b/make/scripts/make.jogl.all.macosx-clang.sh
index b5f21c9..6b25396 100755
--- a/make/scripts/make.jogl.all.macosx-clang.sh
+++ b/make/scripts/make.jogl.all.macosx-clang.sh
@@ -25,5 +25,6 @@ export GLUEGEN_PROPERTIES_FILE="../../gluegen/make/lib/gluegen-xcode_clang.prope
export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
ant \
+ -Dc.compiler.debug=true \
-Drootrel.build=build-macosx \
$* 2>&1 | tee make.jogl.all.macosx.log
diff --git a/make/scripts/tests-win.bat b/make/scripts/tests-win.bat
index 5642cca..df5ec49 100755
--- a/make/scripts/tests-win.bat
+++ b/make/scripts/tests-win.bat
@@ -50,7 +50,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedConte
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT0 %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT1 %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 %*
-scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3 %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3 %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2AWT3 %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2AWT3b %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextWithJTabbedPaneAWT %*
@@ -97,6 +97,9 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.anim.TestAnimat
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.anim.TestAWTCardLayoutAnimatorStartStopBug532 %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.anim.Bug898AnimatorFromEDTAWT %*
+scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLJPanelAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLWindowNEWT %*
+
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestSwingAWT01GLn
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock00AWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock02AWT %*
@@ -107,6 +110,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayout
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestJScrollPaneMixHwLw01AWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestIsRealizedConcurrency01AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestGLJPanelResize01AWT %*
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.newt.TestSwingAWTRobotUsageBeforeJOGLInitBug411
REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.glsl.TestTransformFeedbackVaryingsBug407NEWT
diff --git a/make/scripts/tests-x64-dbg.bat b/make/scripts/tests-x64-dbg.bat
index ce2df92..b3ebc03 100755
--- a/make/scripts/tests-x64-dbg.bat
+++ b/make/scripts/tests-x64-dbg.bat
@@ -55,7 +55,7 @@ REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLC
REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.GLJPanel" "-Djogl.debug.TileRenderer" "-Djogl.debug.TileRenderer.PNG"
REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.GLJPanel" "-Djogl.debug.TileRenderer"
REM set D_ARGS="-Djogl.gljpanel.noverticalflip"
-set D_ARGS="-Dnewt.debug=all"
+REM set D_ARGS="-Dnewt.debug=all"
REM set D_ARGS="-Dnewt.debug.Window"
REM set D_ARGS="-Dnewt.debug.Window.KeyEvent"
REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Window.KeyEvent" "-Dnewt.debug.EDT"
@@ -74,6 +74,9 @@ REM set D_ARGS="-Dnewt.debug.Screen"
REM set D_ARGS="-Dnewt.debug.Screen" "-Dnewt.debug.Window"
REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" "-Dnewt.test.Window.reparent.incompatible=true"
+REM set D_ARGS="-Djogamp.debug.ReflectionUtil" "-Djogamp.debug.ReflectionUtil.forNameStats"
+REM set D_ARGS="-Djogamp.debug.ReflectionUtil.forNameStats"
+
REM set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.java2d.opengl=true" "-Dsun.awt.noerasebackground=true"
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"
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 85eb142..18f488b 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -63,6 +63,14 @@ fi
#export INTEL_DEBUG="buf bat"
#export INTEL_STRICT_CONFORMANCE=1
+# export ALSOFT_LOGLEVEL=[0..4]
+# export ALSOFT_LOGLEVEL=3
+# export ALSOFT_LOGLEVEL=3
+#export ALSOFT_TRAP_ERROR=true
+#export ALSOFT_TRAP_AL_ERROR=true
+#export ALSOFT_TRAP_ALC_ERROR=true
+#export ALSOFT_LOGFILE=openal-soft.log
+
which "$javaexe" 2>&1 | tee -a java-run.log
"$javaexe" -version 2>&1 | tee -a java-run.log
echo LD_LIBRARY_PATH $LD_LIBRARY_PATH 2>&1 | tee -a java-run.log
@@ -96,6 +104,9 @@ function jrun() {
#D_ARGS="-Dnativewindow.debug=all -Dnewt.debug.Window"
#D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock"
+ #D_ARGS="-Djogamp.debug.ReflectionUtil -Djogamp.debug.ReflectionUtil.forNameStats"
+ #D_ARGS="-Djogamp.debug.ReflectionUtil.forNameStats"
+
#D_ARGS="-Dnativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG"
#D_ARGS="-Dnativewindow.debug.X11Util.ATI_HAS_NO_MULTITHREADING_BUG"
#D_ARGS="-Djogl.disable.opengles"
@@ -206,6 +217,7 @@ function jrun() {
#D_ARGS="-Dnewt.debug.Window"
#D_ARGS="-Xprof"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel"
+ #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.debug.GLJPanel.Viewport"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.gljpanel.noglsl"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.gljpanel.noglsl -Djogl.gljpanel.awtverticalflip"
#D_ARGS="-Djogl.debug.GLJPanel -Djogl.debug.DebugGL"
@@ -216,6 +228,7 @@ function jrun() {
#D_ARGS="-Dnativewindow.debug.NativeWindow"
#D_ARGS="-Dnativewindow.osx.calayer.bugfree"
#D_ARGS="-Dnativewindow.debug.ToolkitLock"
+ #D_ARGS="-Djogl.debug.graph.curve"
#D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLCode -Djogl.debug.TraceGL"
#D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLState"
#D_ARGS="-Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil -Djogamp.debug.IOUtil"
@@ -232,7 +245,7 @@ function jrun() {
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer -Djogl.debug.TileRenderer.PNG"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer"
#D_ARGS="-Djogl.debug.PNG -Dnewt.debug.Display.PointerIcon"
- #D_ARGS="-Djogl.debug.JPEGImage"
+ #D_ARGS="-Djogl.debug.JPEGImage -Djogamp.debug.Bitstream"
#D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser"
#X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=True -Dsun.java2d.xrender=false"
#X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=false -Dsun.java2d.xrender=false"
@@ -240,9 +253,10 @@ function jrun() {
#X_ARGS="-Xrs"
#X_ARGS="-Dsun.awt.disableMixing=true"
#D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer"
- #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.AudioSink"
+ #D_ARGS="-Djogl.debug.AudioSink"
+ #D_ARGS="-Djogl.debug.AudioSink.trace"
#D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.GLMediaPlayer.Native"
- D_ARGS="-Djogl.debug.GLMediaPlayer"
+ #D_ARGS="-Djogl.debug.GLMediaPlayer"
#D_ARGS="-Djogl.debug.GLMediaPlayer.StreamWorker.delay=25 -Djogl.debug.GLMediaPlayer"
#D_ARGS="-Djogl.debug.GLMediaPlayer.Native"
@@ -355,7 +369,8 @@ function testawtswt() {
#
#testnoawt jogamp.opengl.openal.av.ALDummyUsage $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $*
-testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.CrossFadePlayer $*
#
# performance tests
@@ -482,6 +497,10 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.anim.TestAnimatorGLJPanel01AWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.anim.Bug898AnimatorFromEDTAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLJPanelAWT $*
+testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLCanvasAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLWindowNEWT $*
+
#
# NEWT
#
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
index 6a8fb6a..9b0f32e 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
@@ -42,7 +42,7 @@ public abstract class RenderState {
private static final String thisKey = "jogamp.graph.curve.RenderState" ;
public static RenderState createRenderState(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory) {
- return new RenderStateImpl(st, pointFactory);
+ return new RenderStateImpl(st, pointFactory, null);
}
public static RenderState createRenderState(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory, PMVMatrix pmvMatrix) {
@@ -61,8 +61,8 @@ public abstract class RenderState {
protected RenderState(ShaderState st, Vertex.Factory<? extends Vertex> vertexFactory, PMVMatrix pmvMatrix) {
this.st = st;
this.vertexFactory = vertexFactory;
- this.pmvMatrix = pmvMatrix;
- this.gcu_PMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, pmvMatrix.glGetPMvMatrixf());
+ this.pmvMatrix = null != pmvMatrix ? pmvMatrix : new PMVMatrix();
+ this.gcu_PMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, this.pmvMatrix.glGetPMvMatrixf());
st.ownUniform(gcu_PMVMatrix);
}
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
index 8783906..0292866 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
@@ -241,6 +241,14 @@ public abstract class Renderer {
}
}
+ /** No PMVMatrix operation is performed here. PMVMatrix will be updated if gl is not null. */
+ public boolean reshapeNotify(GL2ES2 gl, int width, int height) {
+ this.vp_width = width;
+ this.vp_height = height;
+ updateMatrix(gl);
+ return true;
+ }
+
public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far) {
this.vp_width = width;
this.vp_height = height;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
index ec6d54d..cf88e7b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -30,6 +30,8 @@ package com.jogamp.opengl.util;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLBase;
+import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLEventListener;
@@ -168,4 +170,23 @@ public class GLDrawableUtil {
if(bIsPaused) { bAnim.resume(); }
}
+ /**
+ * Determines whether the chosen {@link GLCapabilitiesImmutable}
+ * requires a {@link GLDrawable#swapBuffers() swap-buffers}
+ * before reading pixels.
+ * <p>
+ * Usually one uses the {@link GLBase#getDefaultReadBuffer() default-read-buffer}
+ * in which case {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling reading pixels, the default.
+ * </p>
+ * <p>
+ * However, <i>multisampling</i> offscreen {@link javax.media.opengl.GLFBODrawable}s
+ * utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i>
+ * the multisamples into the readable sampling sink.
+ * In this case, we require {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> reading pixels.
+ * </p>
+ * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers()
+ */
+ public static final boolean swapBuffersBeforeRead(final GLCapabilitiesImmutable chosenCaps) {
+ return chosenCaps.isFBO() && chosenCaps.getSampleBuffers();
+ }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
index a921a28..223c23e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -324,9 +324,19 @@ public class GLPixelBuffer {
/** The {@link GLPixelAttributes}. */
public final GLPixelAttributes pixelAttributes;
- /** Width in pixels. */
+ /**
+ * Width in pixels, representing {@link #buffer}'s {@link #byteSize}.
+ * <p>
+ * May not represent actual image width as user may re-use buffer for different dimensions, see {@link #requiresNewBuffer(GL, int, int, int)}.
+ * </p>
+ */
public final int width;
- /** Height in pixels. */
+ /**
+ * Height in pixels, representing {@link #buffer}'s {@link #byteSize}.
+ * <p>
+ * May not represent actual image height as user may re-use buffer for different dimensions, see {@link #requiresNewBuffer(GL, int, int, int)}.
+ * </p>
+ */
public final int height;
/** Depth in pixels. */
public final int depth;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
index 1c6e974..b6cff85 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
@@ -40,8 +40,8 @@ import javax.media.opengl.GLException;
* regardless of the GLProfile.
*/
public class GLPixelStorageModes {
- private int[] savedGL2GL3Modes = new int[8];
- private int[] savedAlignment = new int[2];
+ private final int[] savedGL2GL3Modes = new int[8];
+ private final int[] savedAlignment = new int[2];
private boolean saved = false;
/** Create instance w/o {@link #save(GL)} */
@@ -127,31 +127,35 @@ public class GLPixelStorageModes {
return;
}
- if(gl.isGL2GL3()) {
- if(gl.isGL2()) {
+ if( gl.isGL2ES3() ) {
+ if( gl.isGL2() ) {
gl.getGL2().glPushClientAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT);
} else {
gl.glGetIntegerv(GL2ES2.GL_PACK_ALIGNMENT, savedAlignment, 0);
gl.glGetIntegerv(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment, 1);
- gl.glGetIntegerv(GL2GL3.GL_PACK_ROW_LENGTH, savedGL2GL3Modes, 0);
- gl.glGetIntegerv(GL2GL3.GL_PACK_SKIP_ROWS, savedGL2GL3Modes, 1);
- gl.glGetIntegerv(GL2GL3.GL_PACK_SKIP_PIXELS, savedGL2GL3Modes, 2);
- gl.glGetIntegerv(GL2GL3.GL_PACK_SWAP_BYTES, savedGL2GL3Modes, 3);
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_ROW_LENGTH, savedGL2GL3Modes, 4);
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_ROWS, savedGL2GL3Modes, 5);
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes, 6);
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_SWAP_BYTES, savedGL2GL3Modes, 7);
+ gl.glGetIntegerv(GL2ES3.GL_PACK_ROW_LENGTH, savedGL2GL3Modes, 0);
+ gl.glGetIntegerv(GL2ES3.GL_PACK_SKIP_ROWS, savedGL2GL3Modes, 1);
+ gl.glGetIntegerv(GL2ES3.GL_PACK_SKIP_PIXELS, savedGL2GL3Modes, 2);
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_ROW_LENGTH, savedGL2GL3Modes, 4);
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_ROWS, savedGL2GL3Modes, 5);
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes, 6);
+ if( gl.isGL2GL3() ) {
+ gl.glGetIntegerv(GL2GL3.GL_PACK_SWAP_BYTES, savedGL2GL3Modes, 3);
+ gl.glGetIntegerv(GL2GL3.GL_UNPACK_SWAP_BYTES, savedGL2GL3Modes, 7);
+ }
+ }
+ gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, 0);
+ gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_ROWS, 0);
+ gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_PIXELS, 0);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, 0);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, 0);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, 0);
+ if( gl.isGL2GL3() ) {
+ gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, 0);
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, 0);
}
- gl.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, 0);
- gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_ROWS, 0);
- gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_PIXELS, 0);
- gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, 0);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, 0);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, 0);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, 0);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, 0);
} else {
- // embedded deals with pack/unpack alignment only
+ // ES1 or ES2 deals with pack/unpack alignment only
gl.glGetIntegerv(GL2ES2.GL_PACK_ALIGNMENT, savedAlignment, 0);
gl.glGetIntegerv(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment, 1);
}
@@ -167,23 +171,25 @@ public class GLPixelStorageModes {
throw new GLException("pixel storage modes not saved");
}
- if(gl.isGL2GL3()) {
- if(gl.isGL2()) {
+ if( gl.isGL2ES3() ) {
+ if( gl.isGL2() ) {
gl.getGL2().glPopClientAttrib();
} else {
gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT, savedAlignment[0]);
gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment[1]);
- gl.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, savedGL2GL3Modes[0]);
- gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_ROWS, savedGL2GL3Modes[1]);
- gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_PIXELS, savedGL2GL3Modes[2]);
- gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, savedGL2GL3Modes[3]);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, savedGL2GL3Modes[4]);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, savedGL2GL3Modes[5]);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes[6]);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, savedGL2GL3Modes[7]);
+ gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, savedGL2GL3Modes[0]);
+ gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_ROWS, savedGL2GL3Modes[1]);
+ gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_PIXELS, savedGL2GL3Modes[2]);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, savedGL2GL3Modes[4]);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, savedGL2GL3Modes[5]);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes[6]);
+ if( gl.isGL2GL3() ) {
+ gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, savedGL2GL3Modes[3]);
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, savedGL2GL3Modes[7]);
+ }
}
} else {
- // embedded deals with pack/unpack alignment only
+ // ES1 or ES2 deals with pack/unpack alignment only
gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT, savedAlignment[0]);
gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment[1]);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index b942c9a..25a012b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -32,6 +32,7 @@ import java.io.File;
import java.io.IOException;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLDrawable;
@@ -151,17 +152,6 @@ public class GLReadBufferUtil {
* @see #GLReadBufferUtil(boolean, boolean)
*/
public boolean readPixels(GL gl, int inX, int inY, int inWidth, int inHeight, boolean mustFlipVertically) {
- final int glerr0 = gl.glGetError();
- if(GL.GL_NO_ERROR != glerr0) {
- System.err.println("Info: GLReadBufferUtil.readPixels: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
- }
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
- final int internalFormat;
- if(gl.isGL2GL3() && 3 == componentCount) {
- internalFormat = GL.GL_RGB;
- } else {
- internalFormat = (4 == componentCount) ? GL.GL_RGBA : GL.GL_RGB;
- }
final GLDrawable drawable = gl.getContext().getGLReadDrawable();
final int width, height;
if( 0 >= inWidth || drawable.getWidth() < inWidth ) {
@@ -174,6 +164,23 @@ public class GLReadBufferUtil {
} else {
height= inHeight;
}
+ return readPixelsImpl(drawable, gl, inX, inY, width, height, mustFlipVertically);
+ }
+
+ protected boolean readPixelsImpl(final GLDrawable drawable, final GL gl,
+ final int inX, final int inY, final int width, final int height,
+ final boolean mustFlipVertically) {
+ final int glerr0 = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr0) {
+ System.err.println("Info: GLReadBufferUtil.readPixels: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
+ }
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
+ final int internalFormat;
+ if(gl.isGL2GL3() && 3 == componentCount) {
+ internalFormat = GL.GL_RGB;
+ } else {
+ internalFormat = (4 == componentCount) ? GL.GL_RGBA : GL.GL_RGB;
+ }
final boolean flipVertically;
if( drawable.isGLOriented() ) {
@@ -215,8 +222,10 @@ public class GLReadBufferUtil {
boolean res = null!=readPixelBuffer && readPixelBuffer.isValid();
if(res) {
psm.setAlignment(gl, alignment, alignment);
- if(gl.isGL2GL3()) {
- gl.getGL2GL3().glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, readPixelBuffer.width);
+ if(gl.isGL2ES3()) {
+ final GL2ES3 gl2es3 = gl.getGL2ES3();
+ gl2es3.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, width);
+ gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
}
readPixelBuffer.clear();
try {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
index 1bbc12f..fd8f541 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
@@ -32,6 +32,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import javax.media.nativewindow.util.Dimension;
import javax.media.nativewindow.util.DimensionImmutable;
@@ -248,19 +249,29 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
}
return dOff;
}
- private int setPixelRGBA8(final ImageLine line, final int lineOff, final ByteBuffer d, final int dOff, final int bytesPerPixel, final boolean hasAlpha) {
+ private int setPixelRGBA8(final ImageLine line, final int lineOff, final ByteBuffer src, final int srcOff, final int bytesPerPixel, final boolean hasAlpha) {
final int b = hasAlpha ? 4-1 : 3-1;
- if( d.limit() <= dOff + b ) {
- throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+dOff+".."+(dOff+b)+"]: "+d);
+ if( src.limit() <= srcOff + b ) {
+ throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+srcOff+".."+(srcOff+b)+"]: "+src);
}
- final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, d, dOff);
+ final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, src, srcOff);
+ line.scanline[lineOff ] = 0xff & p; // R
+ line.scanline[lineOff + 1] = 0xff & ( p >>> 8 ); // G
+ line.scanline[lineOff + 2] = 0xff & ( p >>> 16 ); // B
+ if(hasAlpha) {
+ line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
+ }
+ return srcOff + pixelformat.bytesPerPixel();
+ }
+
+ private static void setPixelRGBA8(final PixelFormat pixelformat, final ImageLine line, final int lineOff, final int srcPix, final int bytesPerPixel, final boolean hasAlpha) {
+ final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, srcPix);
line.scanline[lineOff ] = 0xff & p; // R
line.scanline[lineOff + 1] = 0xff & ( p >>> 8 ); // G
line.scanline[lineOff + 2] = 0xff & ( p >>> 16 ); // B
if(hasAlpha) {
line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
}
- return dOff + pixelformat.bytesPerPixel();
}
/**
@@ -304,9 +315,8 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
final PngWriter png = new PngWriter(outstream, imi);
// add some optional metadata (chunks)
png.getMetadata().setDpi(dpi[0], dpi[1]);
- png.getMetadata().setTimeNow(0); // 0 seconds fron now = now
+ png.getMetadata().setTimeNow(0); // 0 seconds from now = now
png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGPixelRect");
- // png.getMetadata().setText("my key", "my text");
final boolean hasAlpha = 4 == bytesPerPixel;
final ImageLine l1 = new ImageLine(imi);
@@ -332,4 +342,60 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
}
}
}
+
+ public static void write(final PixelFormat pixelformat, final DimensionImmutable size,
+ int strideInPixels, final boolean isGLOriented, final IntBuffer pixels,
+ final double dpiX, final double dpiY,
+ final OutputStream outstream, final boolean closeOutstream) throws IOException {
+ final int width = size.getWidth();
+ final int height = size.getHeight();
+ final int bytesPerPixel = pixelformat.bytesPerPixel();
+ final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
+ (4 == bytesPerPixel) ? true : false /* alpha */,
+ (1 == bytesPerPixel) ? true : false /* grayscale */,
+ false /* indexed */);
+ if( 0 != strideInPixels ) {
+ if( strideInPixels < size.getWidth()) {
+ throw new IllegalArgumentException("Invalid stride "+bytesPerPixel+", must be greater than width "+size.getWidth());
+ }
+ } else {
+ strideInPixels = size.getWidth();
+ }
+ final int reqPixels = strideInPixels * size.getHeight();
+ if( pixels.limit() < reqPixels ) {
+ throw new IndexOutOfBoundsException("Dest buffer has insufficient pixels left, needs "+reqPixels+": "+pixels);
+ }
+
+ // open image for writing to a output stream
+ try {
+ final PngWriter png = new PngWriter(outstream, imi);
+ // add some optional metadata (chunks)
+ png.getMetadata().setDpi(dpiX, dpiY);
+ png.getMetadata().setTimeNow(0); // 0 seconds from now = now
+ png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGPixelRect");
+ final boolean hasAlpha = 4 == bytesPerPixel;
+
+ final ImageLine l1 = new ImageLine(imi);
+ for (int row = 0; row < height; row++) {
+ int dataOff = isGLOriented ? ( height - 1 - row ) * strideInPixels : row * strideInPixels;
+ int lineOff = 0;
+ if(1 == bytesPerPixel) {
+ for (int j = width - 1; j >= 0; j--) {
+ l1.scanline[lineOff++] = pixels.get(dataOff++); // // Luminance, 1 bytesPerPixel
+ }
+ } else {
+ for (int j = width - 1; j >= 0; j--) {
+ setPixelRGBA8(pixelformat, l1, lineOff, pixels.get(dataOff++), bytesPerPixel, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ }
+ png.writeRow(l1, row);
+ }
+ png.end();
+ } finally {
+ if( closeOutstream ) {
+ IOUtil.close(outstream, false);
+ }
+ }
+ }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
index 22f5c01..dabde83 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
@@ -412,22 +412,11 @@ public abstract class TileRendererBase {
* requires a <i>pre-{@link GLDrawable#swapBuffers() swap-buffers}</i>
* before accessing the results, i.e. before {@link #endTile(GL)}.
* <p>
- * Usually one uses the {@link GL#getDefaultReadBuffer() default-read-buffer}, i.e.
- * {@link GL#GL_FRONT} for single-buffer and {@link GL#GL_BACK} for double-buffer {@link GLDrawable}s
- * and {@link GL#GL_COLOR_ATTACHMENT0} for offscreen framebuffer objects.<br>
- * Here {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling {@link #endTile(GL)}, the default.
+ * See {@link GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable)}.
* </p>
- * <p>
- * However, <i>multisampling</i> offscreen {@link GLFBODrawable}s
- * utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i>
- * the multisamples into the readable sampling sink.
- * In this case, we require a {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> calling {@link #endTile(GL)}.
- * </p>
- * @param chosenCaps the chosen {@link GLCapabilitiesImmutable}
- * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers()
*/
public final boolean reqPreSwapBuffers(GLCapabilitiesImmutable chosenCaps) {
- return chosenCaps.isFBO() && chosenCaps.getSampleBuffers();
+ return GLDrawableUtil.swapBuffersBeforeRead(chosenCaps);
}
/**
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
index 9957f20..5a455c8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -30,6 +30,7 @@ package com.jogamp.opengl.util.av;
import java.net.URI;
import javax.media.opengl.GL;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import jogamp.opengl.Debug;
@@ -255,7 +256,12 @@ public interface GLMediaPlayer extends TextureSequence {
/**
* {@inheritDoc}
* <p>
- * See {@link TexSeqEventListener} for semantics and usage.
+ * As the contract of {@link TexSeqEventListener} requests,
+ * implementations of {@link GLMediaEventListener} shall also:
+ * <ul>
+ * <li>off-load complex or {@link GLMediaPlayer} commands on another thread, or</li>
+ * <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
+ * </ul>
* </p>
*/
public interface GLMediaEventListener extends TexSeqEventListener<GLMediaPlayer> {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
index f5d31a1..9490e04 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
@@ -30,6 +30,7 @@ package com.jogamp.opengl.util.awt;
import java.awt.image.BufferedImage;
import javax.media.opengl.GL;
+import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.util.GLReadBufferUtil;
@@ -51,12 +52,53 @@ public class AWTGLReadBufferUtil extends GLReadBufferUtil {
public AWTGLPixelBuffer getAWTGLPixelBuffer() { return (AWTGLPixelBuffer)this.getPixelBuffer(); }
+ /**
+ * Read the drawable's pixels to TextureData and Texture, if requested at construction,
+ * and returns an aligned {@link BufferedImage}.
+ *
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source.
+ * @param awtOrientation flips the data vertically if <code>true</code>.
+ * The context's drawable {@link GLDrawable#isGLOriented()} state
+ * is taken into account.
+ * Vertical flipping is propagated to TextureData
+ * and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
+ * @see #AWTGLReadBufferUtil(GLProfile, boolean)
+ */
public BufferedImage readPixelsToBufferedImage(GL gl, boolean awtOrientation) {
return readPixelsToBufferedImage(gl, 0, 0, 0, 0, awtOrientation);
}
+
+ /**
+ * Read the drawable's pixels to TextureData and Texture, if requested at construction,
+ * and returns an aligned {@link BufferedImage}.
+ *
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source.
+ * @param inX readPixel x offset
+ * @param inY readPixel y offset
+ * @param inWidth optional readPixel width value, used if [1 .. drawable.width], otherwise using drawable.width
+ * @param inHeight optional readPixel height, used if [1 .. drawable.height], otherwise using drawable.height
+ * @param awtOrientation flips the data vertically if <code>true</code>.
+ * The context's drawable {@link GLDrawable#isGLOriented()} state
+ * is taken into account.
+ * Vertical flipping is propagated to TextureData
+ * and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
+ * @see #AWTGLReadBufferUtil(GLProfile, boolean)
+ */
public BufferedImage readPixelsToBufferedImage(GL gl, int inX, int inY, int inWidth, int inHeight, boolean awtOrientation) {
- if( readPixels(gl, inX, inY, inWidth, inHeight, awtOrientation) ) {
- final BufferedImage image = getAWTGLPixelBuffer().image;
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final int width, height;
+ if( 0 >= inWidth || drawable.getWidth() < inWidth ) {
+ width = drawable.getWidth();
+ } else {
+ width = inWidth;
+ }
+ if( 0 >= inHeight || drawable.getHeight() < inHeight ) {
+ height = drawable.getHeight();
+ } else {
+ height= inHeight;
+ }
+ if( readPixelsImpl(drawable, gl, inX, inY, width, height, awtOrientation) ) {
+ final BufferedImage image = getAWTGLPixelBuffer().getAlignedImage(width, height);
if( getTextureData().getMustFlipVertically() ) {
ImageUtil.flipImageVertically(image);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
index 0cde24d..0f64fd0 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -50,11 +50,13 @@ import java.io.OutputStream;
import java.net.URL;
import java.nio.Buffer;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
@@ -1400,18 +1402,34 @@ public class TextureIO {
final PixelFormat pixFmt = pixelAttribs.getPixelFormat();
if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) &&
( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) {
- ByteBuffer buf = (ByteBuffer) data.getBuffer();
- if (null == buf) {
- buf = (ByteBuffer) data.getMipmapData()[0];
+ Buffer buf0 = data.getBuffer();
+ if (null == buf0) {
+ buf0 = data.getMipmapData()[0];
+ }
+ if( null == buf0 ) {
+ throw new IOException("Pixel storage buffer is null");
+ }
+ final DimensionImmutable size = new Dimension(data.getWidth(), data.getHeight());
+ if( buf0 instanceof ByteBuffer ) {
+ final ByteBuffer buf = (ByteBuffer) buf0;
+ buf.rewind();
+ final PNGPixelRect image = new PNGPixelRect(pixFmt, size,
+ 0 /* stride */, !data.getMustFlipVertically() /* isGLOriented */, buf /* pixels */,
+ -1f, -1f);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
+ image.write(outs, true /* close */);
+ return true;
+ } else if( buf0 instanceof IntBuffer ) {
+ final IntBuffer buf = (IntBuffer) buf0;
+ buf.rewind();
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
+ PNGPixelRect.write(pixFmt, size,
+ 0 /* stride */, !data.getMustFlipVertically() /* isGLOriented */, buf /* pixels */,
+ -1f, -1f, outs, true /* closeOutstream */);
+ return true;
+ } else {
+ throw new IOException("PNG writer doesn't support pixel storage buffer of type "+buf0.getClass().getName());
}
- buf.rewind();
-
- final PNGPixelRect image = new PNGPixelRect(pixFmt, new Dimension(data.getWidth(), data.getHeight()),
- 0 /* stride */, true /* isGLOriented */, buf /* pixels */,
- -1f, -1f);
- final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
- image.write(outs, true /* close */);
- return true;
}
throw new IOException("PNG writer doesn't support this pixel format 0x"+Integer.toHexString(pixelFormat)+
" / type 0x"+Integer.toHexString(pixelFormat)+" (only GL_RGB/A, GL_BGR/A + bytes)");
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
index 6c2949c..ab9d1f8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -31,6 +31,7 @@ import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLRunnable;
import javax.media.opengl.GLEventListener;
+
import com.jogamp.opengl.util.TimeFrameI;
/**
@@ -133,17 +134,16 @@ public interface TextureSequence {
/**
* Event listener to notify users of updates regarding the {@link TextureSequence}.
* <p>
- * The implementation sending the events, and hence calling down to all listeners,
- * does not necessarily make the user's OpenGL context current.
+ * Implementations sending events down to all listeners,
+ * while not necessarily making the user's OpenGL context current.
* </p>
* <p>
- * Further more, the call may happen off-thread, possibly holding another, possibly shared, OpenGL context current.
- * </p>
+ * Events may be sent from a 3rd-party thread, possibly holding another, maybe shared, OpenGL context current.<br/>
* Hence a user shall not issue <i>any</i> OpenGL, time consuming
- * or {@link TextureSequence} lifecycle operations directly.<br>
+ * or {@link TextureSequence} operations directly.<br>
* Instead, the user shall:
* <ul>
- * <li>issue commands off-thread via spawning off another thread, or</li>
+ * <li>off-load complex or {@link TextureSequence} commands on another thread, or</li>
* <li>injecting {@link GLRunnable} objects via {@link GLAutoDrawable#invoke(boolean, GLRunnable)}, or</li>
* <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
* </ul>
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index 2d6aed1..3f0c779 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -627,14 +627,24 @@ public interface GLBase {
* Returns the default color buffer within the current bound
* {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER,
* which will be used as the source for pixel reading commands,
- * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc.
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc.
* <p>
* For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
* otherwise this is {@link GL#GL_FRONT} for single buffer configurations
* and {@link GL#GL_BACK} for double buffer configurations.
* </p>
+ * <p>
+ * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ * and {@link GL#GL_BACK} is the default.
+ * </p>
+ * <p>
+ * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+ * </p>
+ * <p>
+ * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+ * for read-pixels and swap-buffers implications.
+ * </p>
*/
public int getDefaultReadBuffer();
-
}
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 9245d10..9a43117 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -1277,12 +1277,23 @@ public abstract class GLContext {
* Returns the default color buffer within the current bound
* {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER,
* which will be used as the source for pixel reading commands,
- * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc.
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc.
* <p>
* For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
* otherwise this is {@link GL#GL_FRONT} for single buffer configurations
* and {@link GL#GL_BACK} for double buffer configurations.
* </p>
+ * <p>
+ * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ * and {@link GL#GL_BACK} is the default.
+ * </p>
+ * <p>
+ * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+ * </p>
+ * <p>
+ * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+ * for read-pixels and swap-buffers implications.
+ * </p>
*/
public abstract int getDefaultReadBuffer();
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index a43ddee..80f4695 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -39,7 +39,6 @@ package javax.media.opengl;
import jogamp.nativewindow.NWJNILibLoader;
import jogamp.opengl.Debug;
-import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
@@ -51,6 +50,7 @@ import com.jogamp.common.util.VersionUtil;
import com.jogamp.common.util.cache.TempJarCache;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveThreadGroupLock;
+import com.jogamp.gluegen.runtime.FunctionAddressResolver;
import com.jogamp.nativewindow.NativeWindowVersion;
import com.jogamp.opengl.JoglVersion;
@@ -58,6 +58,7 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.fixedfunc.GLPointerFunc;
+import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
@@ -110,7 +111,7 @@ public class GLProfile {
final boolean justInitialized;
initLock.lock();
try {
- if(!initialized) { // volatile: ok
+ if(!initialized) {
initialized = true;
justInitialized = true;
if(DEBUG) {
@@ -118,6 +119,10 @@ public class GLProfile {
Thread.dumpStack();
}
+ if(ReflectionUtil.DEBUG_STATS_FORNAME) {
+ ReflectionUtil.resetForNameCount();
+ }
+
// run the whole static initialization privileged to speed up,
// since this skips checking further access
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@@ -125,24 +130,6 @@ public class GLProfile {
public Object run() {
Platform.initSingleton();
- // Performance hack to trigger classloading of the GL classes impl, which makes up to 12%, 800ms down to 700ms
- new Thread(new Runnable() {
- @Override
- public void run() {
- final ClassLoader cl = GLProfile.class.getClassLoader();
- try {
- ReflectionUtil.createInstance(getGLImplBaseClassName(GL4bc)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
- } catch (Throwable t) {}
- try {
- ReflectionUtil.createInstance(getGLImplBaseClassName(GLES3)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
- } catch (Throwable t) {}
- try {
- ReflectionUtil.createInstance(getGLImplBaseClassName(GLES1)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
- } catch (Throwable t) {}
- }
- }, "GLProfile-GL_Bootstrapping").start();
-
-
if(TempJarCache.isInitialized()) {
final ClassLoader cl = GLProfile.class.getClassLoader();
final String newtFactoryClassName = "com.jogamp.newt.NewtFactory";
@@ -156,6 +143,11 @@ public class GLProfile {
return null;
}
});
+ if( ReflectionUtil.DEBUG_STATS_FORNAME ) {
+ if( justInitialized ) {
+ System.err.println(ReflectionUtil.getForNameStats(null).toString());
+ }
+ }
} else {
justInitialized = false;
}
@@ -191,7 +183,7 @@ public class GLProfile {
public static void shutdown() {
initLock.lock();
try {
- if(initialized) { // volatile: ok
+ if(initialized) {
initialized = false;
if(DEBUG) {
System.err.println("GLProfile.shutdown() - thread "+Thread.currentThread().getName());
@@ -1045,7 +1037,6 @@ public class GLProfile {
public final String getGLImplBaseClassName() {
return getGLImplBaseClassName(getImplName());
}
-
private static final String getGLImplBaseClassName(String profileImpl) {
if( GLES2 == profileImpl || GLES3 == profileImpl ) {
return "jogamp.opengl.es3.GLES3";
@@ -1062,6 +1053,25 @@ public class GLProfile {
}
}
+ public final Constructor<?> getGLCtor(boolean glObject) {
+ return getGLCtor(getImplName(), glObject);
+ }
+ private static final Constructor<?> getGLCtor(String profileImpl, boolean glObject) {
+ if( GLES2 == profileImpl || GLES3 == profileImpl ) {
+ return glObject ? ctorGLES3Impl : ctorGLES3ProcAddr;
+ } else if( GLES1 == profileImpl ) {
+ return glObject ? ctorGLES1Impl : ctorGLES1ProcAddr;
+ } else if ( GL4bc == profileImpl ||
+ GL4 == profileImpl ||
+ GL3bc == profileImpl ||
+ GL3 == profileImpl ||
+ GL2 == profileImpl ) {
+ return glObject ? ctorGL234Impl : ctorGL234ProcAddr;
+ } else {
+ throw new GLException("unsupported profile \"" + profileImpl + "\"");
+ }
+ }
+
/**
* @param o GLProfile object to compare with
* @return true if given Object is a GLProfile and
@@ -1530,13 +1540,87 @@ public class GLProfile {
private static /*final*/ boolean hasEGLFactory;
private static /*final*/ boolean hasGLES3Impl;
private static /*final*/ boolean hasGLES1Impl;
+ private static /*final*/ Constructor<?> ctorGL234Impl;
+ private static /*final*/ Constructor<?> ctorGLES3Impl;
+ private static /*final*/ Constructor<?> ctorGLES1Impl;
+ private static /*final*/ Constructor<?> ctorGL234ProcAddr;
+ private static /*final*/ Constructor<?> ctorGLES3ProcAddr;
+ private static /*final*/ Constructor<?> ctorGLES1ProcAddr;
private static /*final*/ GLDrawableFactoryImpl eglFactory = null;
private static /*final*/ GLDrawableFactoryImpl desktopFactory = null;
private static /*final*/ AbstractGraphicsDevice defaultDevice = null;
- private static volatile boolean initialized = false;
- private static RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock();
+ private static boolean initialized = false;
+ private static final RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock();
+
+ private static final Class<?>[] ctorGLArgs = new Class<?>[] { GLProfile.class, jogamp.opengl.GLContextImpl.class };
+ private static final Class<?>[] ctorProcArgs = new Class<?>[] { FunctionAddressResolver.class };
+ private static final String GL4bcImplClassName = "jogamp.opengl.gl4.GL4bcImpl";
+ private static final String GL4bcProcClassName = "jogamp.opengl.gl4.GL4bcProcAddressTable";
+ private static final String GLES1ImplClassName = "jogamp.opengl.es1.GLES1Impl";
+ private static final String GLES1ProcClassName = "jogamp.opengl.es1.GLES1ProcAddressTable";
+ private static final String GLES3ImplClassName = "jogamp.opengl.es3.GLES3Impl";
+ private static final String GLES3ProcClassName = "jogamp.opengl.es3.GLES3ProcAddressTable";
+
+ private static final Constructor<?> getCtor(final String clazzName, final boolean glObject, final ClassLoader cl) {
+ try {
+ return ReflectionUtil.getConstructor(clazzName, glObject ? ctorGLArgs : ctorProcArgs, cl);
+ } catch (Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Catched: "+t.getMessage());
+ t.printStackTrace();
+ }
+ return null;
+ }
+ }
+
+ private static final void initGLCtorImpl() {
+ final ClassLoader classloader = GLProfile.class.getClassLoader();
+
+ // depends on hasDesktopGLFactory
+ {
+ final Constructor<?> ctorGL = getCtor(GL4bcImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GL4bcProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGL234Impl = true;
+ ctorGL234Impl = ctorGL;
+ ctorGL234ProcAddr = ctorProc;
+ } else {
+ hasGL234Impl = false;
+ ctorGL234Impl = null;
+ ctorGL234ProcAddr = null;
+ }
+ }
+
+ // depends on hasEGLFactory
+ {
+ final Constructor<?> ctorGL = getCtor(GLES1ImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GLES1ProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGLES1Impl = true;
+ ctorGLES1Impl = ctorGL;
+ ctorGLES1ProcAddr = ctorProc;
+ } else {
+ hasGLES1Impl = false;
+ ctorGLES1Impl = null;
+ ctorGLES1ProcAddr = null;
+ }
+ }
+ {
+ final Constructor<?> ctorGL = getCtor(GLES3ImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GLES3ProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGLES3Impl = true;
+ ctorGLES3Impl = ctorGL;
+ ctorGLES3ProcAddr = ctorProc;
+ } else {
+ hasGLES3Impl = false;
+ ctorGLES3Impl = null;
+ ctorGLES3ProcAddr = null;
+ }
+ }
+ }
/**
* Tries the profiles implementation and native libraries.
@@ -1551,17 +1635,12 @@ public class GLProfile {
System.err.println(JoglVersion.getInstance());
}
- ClassLoader classloader = GLProfile.class.getClassLoader();
+ final ClassLoader classloader = GLProfile.class.getClassLoader();
isAWTAvailable = NativeWindowFactory.isAWTAvailable() &&
ReflectionUtil.isClassAvailable("javax.media.opengl.awt.GLCanvas", classloader) ; // JOGL
- // depends on hasDesktopGLFactory
- hasGL234Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.gl4.GL4bcImpl", classloader);
-
- // depends on hasEGLFactory
- hasGLES1Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es1.GLES1Impl", classloader);
- hasGLES3Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es3.GLES3Impl", classloader);
+ initGLCtorImpl();
//
// Iteration of desktop GL availability detection
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index abf670c..0958908 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -818,9 +818,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
printActive = false;
return; // not yet available ..
}
- if( !isShowing ) {
+ if( !isVisible() ) {
if(DEBUG) {
- System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, drawable valid, canvas not showing");
+ System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, canvas not visible");
}
printActive = false;
return; // not yet available ..
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 522585f..fbd923a 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -60,6 +60,7 @@ import java.util.List;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
@@ -222,7 +223,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
return singleAWTGLPixelBufferProvider;
}
- private final GLDrawableHelper helper = new GLDrawableHelper();
+ private final GLDrawableHelper helper;
+ private boolean autoSwapBufferMode;
+
private volatile boolean isInitialized;
//
@@ -352,9 +355,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
this.glProfile = offscreenCaps.getGLProfile();
this.factory = GLDrawableFactoryImpl.getFactoryImpl(glProfile);
this.chooser = chooser;
+
+ helper = new GLDrawableHelper();
if( null != shareWith ) {
helper.setSharedContext(null, shareWith);
}
+ autoSwapBufferMode = helper.getAutoSwapBufferMode();
+
this.setFocusable(true); // allow keyboard input!
this.addHierarchyListener(hierarchyListener);
this.isShowing = isShowing();
@@ -430,7 +437,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public void display() {
- if( isShowing ) {
+ if( isShowing || ( printActive && isVisible() ) ) {
if (EventQueue.isDispatchThread()) {
// Want display() to be synchronous, so call paintImmediately()
paintImmediately(0, 0, getWidth(), getHeight());
@@ -620,9 +627,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
printActive = false;
return; // not yet available ..
}
- if( !isShowing ) {
+ if( !isVisible() ) {
if(DEBUG) {
- System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, drawable valid, panel not showing");
+ System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, panel not visible");
}
printActive = false;
return; // not yet available ..
@@ -940,35 +947,31 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void setAutoSwapBufferMode(boolean onOrOff) {
- // In the current implementation this is a no-op. Both the pbuffer
- // and pixmap based rendering paths use a single-buffered surface
- // so swapping the buffers doesn't do anything. We also don't
- // currently have the provision to skip copying the data to the
- // Swing portion of the GLJPanel in any of the rendering paths.
+ public void setAutoSwapBufferMode(boolean enable) {
+ this.autoSwapBufferMode = enable;
+ boolean backendHandlesSwapBuffer = false;
+ if( isInitialized ) {
+ final Backend b = backend;
+ if ( null != b ) {
+ backendHandlesSwapBuffer= b.handlesSwapBuffer();
+ }
+ }
+ if( !backendHandlesSwapBuffer ) {
+ helper.setAutoSwapBufferMode(enable);
+ }
}
@Override
public boolean getAutoSwapBufferMode() {
- // In the current implementation this is a no-op. Both the pbuffer
- // and pixmap based rendering paths use a single-buffered surface
- // so swapping the buffers doesn't do anything. We also don't
- // currently have the provision to skip copying the data to the
- // Swing portion of the GLJPanel in any of the rendering paths.
- return true;
+ return autoSwapBufferMode;
}
@Override
public void swapBuffers() {
- // In the current implementation this is a no-op. Both the pbuffer
- // and pixmap based rendering paths use a single-buffered surface
- // so swapping the buffers doesn't do anything. We also don't
- // currently have the provision to skip copying the data to the
- // Swing portion of the GLJPanel in any of the rendering paths.
- if( printActive && isInitialized) {
+ if( isInitialized ) {
final Backend b = backend;
if ( null != b ) {
- b.getDrawable().swapBuffers();
+ b.swapBuffers();
}
}
}
@@ -1366,6 +1369,19 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
public boolean preGL(Graphics g);
/**
+ * Return true if backend handles 'swap buffer' itself
+ * and hence the helper's setAutoSwapBuffer(enable) shall not be called.
+ * In this case {@link GLJPanel#autoSwapBufferMode} is being used
+ * in the backend to determine whether to swap buffers or not.
+ */
+ public boolean handlesSwapBuffer();
+
+ /**
+ * Shall invoke underlying drawable's swapBuffer.
+ */
+ public void swapBuffers();
+
+ /**
* Called after the OpenGL work is done in init() and display().
* The isDisplay argument indicates whether this was called on
* behalf of a call to display() rather than init().
@@ -1400,6 +1416,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private volatile GLContextImpl offscreenContext; // volatile: avoid locking for read-only access
private boolean flipVertical;
+ private int frameCount = 0;
// For saving/restoring of OpenGL state during ReadPixels
private final GLPixelStorageModes psm = new GLPixelStorageModes();
@@ -1423,7 +1440,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public final void initialize() {
if(DEBUG) {
- System.err.println(getThreadName()+": OffscreenBackend: initialize()");
+ System.err.println(getThreadName()+": OffscreenBackend: initialize() - frameCount "+frameCount);
}
try {
final GLContext[] shareWith = { null };
@@ -1436,10 +1453,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
chooser,
panelWidth, panelHeight);
offscreenDrawable.setRealized(true);
+ if( DEBUG ) {
+ offscreenDrawable.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
+ @Override
+ public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ System.err.println(getThreadName()+": OffscreenBackend.swapBuffers - frameCount "+frameCount);
+ } } );
+ }
+
offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith[0]);
offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
isInitialized = true;
+ helper.setAutoSwapBufferMode(false); // we handle swap-buffers, see handlesSwapBuffer()
+
final GL gl = offscreenContext.getGL();
flipVertical = !GLJPanel.this.skipGLOrientationVerticalFlip && offscreenDrawable.isGLOriented();
final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
@@ -1453,8 +1480,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
", isGL2ES2 " + gl.isGL2ES2()+"]");
}
if( useGLSLFlip ) {
- final boolean _autoSwapBufferMode = helper.getAutoSwapBufferMode();
- helper.setAutoSwapBufferMode(false);
final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
fboDrawable.setTextureUnit( GLJPanel.this.requestedTextureUnit );
try {
@@ -1475,7 +1500,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
fboFlipped.destroy(gl);
fboFlipped = null;
}
- helper.setAutoSwapBufferMode(_autoSwapBufferMode);
}
} else {
fboFlipped = null;
@@ -1502,7 +1526,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public final void destroy() {
if(DEBUG) {
- System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable));
+ System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)+" - frameCount "+frameCount);
}
if ( null != offscreenContext && offscreenContext.isCreated() ) {
if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
@@ -1563,8 +1587,29 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public final boolean handlesSwapBuffer() {
+ return true;
+ }
+
+ @Override
+ public final void swapBuffers() {
+ final GLDrawable d = offscreenDrawable;
+ if( null != d ) {
+ d.swapBuffers();
+ }
+ }
+
+ @Override
public final void postGL(Graphics g, boolean isDisplay) {
if (isDisplay) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: - frameCount "+frameCount);
+ }
+ if( autoSwapBufferMode ) {
+ // Since we only use a single-buffer non-MSAA or double-buffered MSAA offscreenDrawable,
+ // we can always swap!
+ offscreenDrawable.swapBuffers();
+ }
final GL gl = offscreenContext.getGL();
final int componentCount;
@@ -1643,6 +1688,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
// Must now copy pixels from offscreen context into surface
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.readPixels: - frameCount "+frameCount);
+ }
// Save current modes
psm.setAlignment(gl, alignment, alignment);
@@ -1652,8 +1700,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
}
- offscreenDrawable.swapBuffers();
-
if(null != glslTextureRaster) { // implies flippedVertical
final boolean viewportChange;
final int[] usrViewport = new int[] { 0, 0, 0, 0 };
@@ -1731,9 +1777,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
if ( null != alignedImage ) {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.doPaintComponent.drawImage: - frameCount "+frameCount);
+ }
// Draw resulting image in one shot
g.drawImage(alignedImage, 0, 0, alignedImage.getWidth(), alignedImage.getHeight(), null); // Null ImageObserver since image data is ready.
}
+ frameCount++;
}
@Override
@@ -1924,13 +1974,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public final GLCapabilitiesImmutable getChosenGLCapabilities() {
- // FIXME: should do better than this; is it possible to using only platform-independent code?
+ // FIXME: should do better than this; is it possible to query J2D Caps ?
return new GLCapabilities(null);
}
@Override
public final GLProfile getGLProfile() {
- // FIXME: should do better than this; is it possible to using only platform-independent code?
+ // FIXME: should do better than this; is it possible to query J2D's Profile ?
return GLProfile.getDefault(GLProfile.getDefaultDevice());
}
@@ -2078,6 +2128,19 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public final boolean handlesSwapBuffer() {
+ return false;
+ }
+
+ @Override
+ public final void swapBuffers() {
+ final GLDrawable d = joglDrawable;
+ if( null != d ) {
+ d.swapBuffers();
+ }
+ }
+
+ @Override
public final void postGL(Graphics g, boolean isDisplay) {
// Cause OpenGL pipeline to flush its results because
// otherwise it's possible we will buffer up multiple frames'
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java b/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java
index fe2dd73..68f926b 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java
@@ -61,10 +61,6 @@ public class RenderStateImpl extends RenderState {
// st.ownUniform(gcu_Strength);
}
- public RenderStateImpl(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory) {
- this(st, pointFactory, new PMVMatrix());
- }
-
@Override
public final GLUniformData getWeight() { return gcu_Weight; }
@Override
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
index 472bfbd..2351826 100644
--- a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
@@ -298,7 +298,7 @@ public class GLBufferObjectTracker {
public synchronized final GLBufferStorage mapBuffer(final GLBufferStateTracker bufferStateTracker,
final GL caller, final int target, final long offset, final long length, final int access,
final MapBufferRangeDispatch dispatch, final long glProcAddress) throws GLException {
- return this.mapBufferImpl(bufferStateTracker, caller, target, true /* useRange */, length, access, access, dispatch, glProcAddress);
+ return this.mapBufferImpl(bufferStateTracker, caller, target, true /* useRange */, offset, length, access, dispatch, glProcAddress);
}
/**
* Must be called when mapping GL buffer objects via {@link GL2#mapNamedBuffer(int, int)}.
@@ -319,7 +319,7 @@ public class GLBufferObjectTracker {
*/
public synchronized final GLBufferStorage mapBuffer(final int bufferName, final long offset, final long length, final int access, final MapBufferRangeDispatch dispatch,
final long glProcAddress) throws GLException {
- return this.mapBufferImpl(0 /* target */, bufferName, true /* isNamedBuffer */, false /* useRange */, 0 /* offset */, 0 /* length */, access, dispatch, glProcAddress);
+ return this.mapBufferImpl(0 /* target */, bufferName, true /* isNamedBuffer */, true /* useRange */, offset, length, access, dispatch, glProcAddress);
}
/**
* @throws GLException if buffer is not bound to target
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 431bba6..9ccd785 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -54,7 +54,6 @@ import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.common.util.VersionNumberString;
import com.jogamp.common.util.locks.RecursiveLock;
-import com.jogamp.gluegen.runtime.FunctionAddressResolver;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
@@ -1127,17 +1126,17 @@ public abstract class GLContextImpl extends GLContext {
// Helpers for various context implementations
//
- private Object createInstance(GLProfile glp, String suffix, Class<?>[] cstrArgTypes, Object[] cstrArgs) {
- return ReflectionUtil.createInstance(glp.getGLImplBaseClassName()+suffix, cstrArgTypes, cstrArgs, getClass().getClassLoader());
+ private Object createInstance(GLProfile glp, boolean glObject, Object[] cstrArgs) {
+ return ReflectionUtil.createInstance(glp.getGLCtor(glObject), cstrArgs);
}
private boolean verifyInstance(GLProfile glp, String suffix, Object instance) {
- return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix);
+ return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix);
}
/** Create the GL for this context. */
protected GL createGL(GLProfile glp) {
- final GL gl = (GL) createInstance(glp, "Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { glp, this } );
+ final GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } );
/* FIXME: refactor dependence on Java 2D / JOGL bridge
if (tracker != null) {
@@ -1585,8 +1584,7 @@ public abstract class GLContextImpl extends GLContext {
System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+toHexString(table.hashCode()));
}
} else {
- glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), "ProcAddressTable",
- new Class[] { FunctionAddressResolver.class } ,
+ glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), false,
new Object[] { new GLProcAddressResolver() } );
resetProcAddressTable(getGLProcAddressTable());
synchronized(mappedContextTypeObjectLock) {
@@ -2233,7 +2231,7 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }
@Override
- public final int getDefaultReadBuffer() { return drawable.getDefaultReadBuffer(gl); }
+ public final int getDefaultReadBuffer() { return drawable.getDefaultReadBuffer(gl, drawableRead != drawable); }
//---------------------------------------------------------------------------
// GL_ARB_debug_output, GL_AMD_debug_output helpers
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index 94d39a4..d112745 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -260,8 +260,8 @@ public abstract class GLDrawableImpl implements GLDrawable {
/** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
protected int getDefaultReadFramebuffer() { return 0; }
/** Callback for special implementations, allowing GLContext to fetch a custom default read buffer of current framebuffer. */
- protected int getDefaultReadBuffer(GL gl) {
- if(gl.isGLES() || getChosenGLCapabilities().getDoubleBuffered()) {
+ protected int getDefaultReadBuffer(GL gl, boolean hasDedicatedDrawableRead) {
+ if( gl.isGLES() || hasDedicatedDrawableRead || getChosenGLCapabilities().getDoubleBuffered() ) {
// Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
// Note-2: ES3 only supports GL_BACK, GL_NONE or GL_COLOR_ATTACHMENT0+i
return GL.GL_BACK;
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index 0e9d142..6f5fa3e 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -325,7 +325,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
protected final int getDefaultReadFramebuffer() { return initialized ? fbos[fboIFront].getReadFramebuffer() : 0; }
@Override
- protected final int getDefaultReadBuffer(GL gl) { return initialized ? fbos[fboIFront].getDefaultReadBuffer() : GL.GL_COLOR_ATTACHMENT0 ; }
+ protected final int getDefaultReadBuffer(GL gl, boolean hasDedicatedDrawableRead) {
+ return initialized ? fbos[fboIFront].getDefaultReadBuffer() : GL.GL_COLOR_ATTACHMENT0 ;
+ }
@Override
protected final void setRealizedImpl() {
diff --git a/src/jogl/classes/jogamp/opengl/GLStateTracker.java b/src/jogl/classes/jogamp/opengl/GLStateTracker.java
index 307fd0a..0e45174 100644
--- a/src/jogl/classes/jogamp/opengl/GLStateTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLStateTracker.java
@@ -177,20 +177,20 @@ public class GLStateTracker {
pixelStateMap.put(GL.GL_PACK_ALIGNMENT, 4);
pixelStateMap.put(GL2GL3.GL_PACK_SWAP_BYTES, GL.GL_FALSE);
pixelStateMap.put(GL2GL3.GL_PACK_LSB_FIRST, GL.GL_FALSE);
- pixelStateMap.put(GL2GL3.GL_PACK_ROW_LENGTH, 0);
- pixelStateMap.put(GL2GL3.GL_PACK_SKIP_ROWS, 0);
- pixelStateMap.put(GL2GL3.GL_PACK_SKIP_PIXELS, 0);
+ pixelStateMap.put(GL2ES3.GL_PACK_ROW_LENGTH, 0);
+ pixelStateMap.put(GL2ES3.GL_PACK_SKIP_ROWS, 0);
+ pixelStateMap.put(GL2ES3.GL_PACK_SKIP_PIXELS, 0);
pixelStateMap.put(GL2GL3.GL_PACK_IMAGE_HEIGHT, 0);
pixelStateMap.put(GL2GL3.GL_PACK_SKIP_IMAGES, 0);
pixelStateMap.put(GL.GL_UNPACK_ALIGNMENT, 4);
pixelStateMap.put(GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE);
pixelStateMap.put(GL2GL3.GL_UNPACK_LSB_FIRST, GL.GL_FALSE);
- pixelStateMap.put(GL2GL3.GL_UNPACK_ROW_LENGTH, 0);
- pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_ROWS, 0);
- pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_PIXELS, 0);
- pixelStateMap.put(GL2GL3.GL_UNPACK_IMAGE_HEIGHT, 0);
- pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_IMAGES, 0);
+ pixelStateMap.put(GL2ES2.GL_UNPACK_ROW_LENGTH, 0);
+ pixelStateMap.put(GL2ES2.GL_UNPACK_SKIP_ROWS, 0);
+ pixelStateMap.put(GL2ES2.GL_UNPACK_SKIP_PIXELS, 0);
+ pixelStateMap.put(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0);
+ pixelStateMap.put(GL2ES3.GL_UNPACK_SKIP_IMAGES, 0);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
index 8b12f8a..eeaaa58 100644
--- a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
+++ b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
@@ -31,6 +31,8 @@ package jogamp.opengl.openal.av;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import jogamp.opengl.Debug;
+
import com.jogamp.common.util.LFRingbuffer;
import com.jogamp.common.util.Ringbuffer;
import com.jogamp.common.util.locks.LockFactory;
@@ -50,6 +52,8 @@ import com.jogamp.opengl.util.av.AudioSink;
public class ALAudioSink implements AudioSink {
private static final String AL_SOFT_buffer_samples = "AL_SOFT_buffer_samples";
+ private static final String ALC_EXT_thread_local_context = "ALC_EXT_thread_local_context";
+ private static final boolean DEBUG_TRACE;
private static final ALC alc;
private static final AL al;
private static final ALExt alExt;
@@ -58,6 +62,7 @@ public class ALAudioSink implements AudioSink {
private String deviceSpecifier;
private ALCdevice device;
private boolean hasSOFTBufferSamples;
+ private boolean hasALC_thread_local_context;
private AudioFormat preferredAudioFormat;
private ALCcontext context;
private final RecursiveLock lock = LockFactory.createRecursiveLock();
@@ -106,6 +111,9 @@ public class ALAudioSink implements AudioSink {
private volatile boolean playRequested = false;
static {
+ Debug.initSingleton();
+ DEBUG_TRACE = Debug.isPropertyDefined("jogl.debug.AudioSink.trace", true);
+
ALC _alc = null;
AL _al = null;
ALExt _alExt = null;
@@ -132,67 +140,71 @@ public class ALAudioSink implements AudioSink {
if( !staticAvailable ) {
return;
}
+ synchronized(ALAudioSink.class) {
+ try {
+ // Get handle to default device.
+ device = alc.alcOpenDevice(null);
+ if (device == null) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error opening default OpenAL device");
+ }
- try {
- // Get handle to default device.
- device = alc.alcOpenDevice(null);
- if (device == null) {
- throw new RuntimeException("ALAudioSink: Error opening default OpenAL device");
- }
+ // Get the device specifier.
+ deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER);
+ if (deviceSpecifier == null) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error getting specifier for default OpenAL device");
+ }
- // Get the device specifier.
- deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER);
- if (deviceSpecifier == null) {
- throw new RuntimeException("ALAudioSink: Error getting specifier for default OpenAL device");
- }
+ // Create audio context.
+ context = alc.alcCreateContext(device, null);
+ if (context == null) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error creating OpenAL context for "+deviceSpecifier);
+ }
- // Create audio context.
- context = alc.alcCreateContext(device, null);
- if (context == null) {
- throw new RuntimeException("ALAudioSink: Error creating OpenAL context for "+deviceSpecifier);
- }
+ lockContext();
+ try {
+ // Check for an error.
+ if ( alc.alcGetError(device) != ALC.ALC_NO_ERROR ) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error making OpenAL context current");
+ }
- lockContext();
- try {
- // Check for an error.
- if ( alc.alcGetError(device) != ALC.ALC_NO_ERROR ) {
- throw new RuntimeException("ALAudioSink: Error making OpenAL context current");
- }
+ hasSOFTBufferSamples = al.alIsExtensionPresent(AL_SOFT_buffer_samples);
+ hasALC_thread_local_context = alc.alcIsExtensionPresent(null, ALC_EXT_thread_local_context) ||
+ alc.alcIsExtensionPresent(device, ALC_EXT_thread_local_context) ;
+ preferredAudioFormat = queryPreferredAudioFormat();
+ if( DEBUG ) {
+ System.out.println("ALAudioSink: OpenAL Extensions:"+al.alGetString(AL.AL_EXTENSIONS));
+ System.out.println("ALAudioSink: Null device OpenAL Extensions:"+alc.alcGetString(null, ALC.ALC_EXTENSIONS));
+ System.out.println("ALAudioSink: Device "+deviceSpecifier+" OpenAL Extensions:"+alc.alcGetString(device, ALC.ALC_EXTENSIONS));
+ System.out.println("ALAudioSink: hasSOFTBufferSamples "+hasSOFTBufferSamples);
+ System.out.println("ALAudioSink: hasALC_thread_local_context "+hasALC_thread_local_context);
+ System.out.println("ALAudioSink: preferredAudioFormat "+preferredAudioFormat);
+ }
- hasSOFTBufferSamples = al.alIsExtensionPresent(AL_SOFT_buffer_samples);
- preferredAudioFormat = queryPreferredAudioFormat();
- if( DEBUG ) {
- System.out.println("ALAudioSink: OpenAL Extensions:"+al.alGetString(AL.AL_EXTENSIONS));
- System.out.println("ALAudioSink: Null device OpenAL Extensions:"+alc.alcGetString(null, ALC.ALC_EXTENSIONS));
- System.out.println("ALAudioSink: Device "+deviceSpecifier+" OpenAL Extensions:"+alc.alcGetString(device, ALC.ALC_EXTENSIONS));
- System.out.println("ALAudioSink: hasSOFTBufferSamples "+hasSOFTBufferSamples);
- System.out.println("ALAudioSink: preferredAudioFormat "+preferredAudioFormat);
- }
+ // Create source
+ {
+ alSource = new int[1];
+ al.alGenSources(1, alSource, 0);
+ final int err = al.alGetError();
+ if( AL.AL_NO_ERROR != err ) {
+ alSource = null;
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error generating Source: 0x"+Integer.toHexString(err));
+ }
+ }
- // Create source
- {
- alSource = new int[1];
- al.alGenSources(1, alSource, 0);
- final int err = al.alGetError();
- if( err != AL.AL_NO_ERROR ) {
- alSource = null;
- throw new RuntimeException("ALAudioSink: Error generating Source: 0x"+Integer.toHexString(err));
+ if( DEBUG ) {
+ System.err.println("ALAudioSink: Using device: " + deviceSpecifier);
}
+ initialized = true;
+ } finally {
+ unlockContext();
}
-
+ return;
+ } catch ( Exception e ) {
if( DEBUG ) {
- System.err.println("ALAudioSink: Using device: " + deviceSpecifier);
+ System.err.println(e.getMessage());
}
- initialized = true;
- } finally {
- unlockContext();
- }
- return;
- } catch ( Exception e ) {
- if( DEBUG ) {
- System.err.println(e.getMessage());
+ destroy();
}
- destroy();
}
}
@@ -208,10 +220,33 @@ public class ALAudioSink implements AudioSink {
private final void lockContext() {
lock.lock();
- alc.alcMakeContextCurrent(context);
+ if( hasALC_thread_local_context ) {
+ alExt.alcSetThreadContext(context);
+ } else {
+ alc.alcMakeContextCurrent(context);
+ }
+ final int alcErr = alc.alcGetError(null);
+ if( ALC.ALC_NO_ERROR != alcErr ) {
+ final String err = getThreadName()+": ALCError "+toHexString(alcErr)+" while makeCurrent. "+this;
+ System.err.println(err);
+ Thread.dumpStack();
+ lock.unlock();
+ throw new RuntimeException(err);
+ }
+ final int alErr = al.alGetError();
+ if( ALC.ALC_NO_ERROR != alErr ) {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": Prev - ALError "+toHexString(alErr)+" @ makeCurrent. "+this);
+ Thread.dumpStack();
+ }
+ }
}
private final void unlockContext() {
- alc.alcMakeContextCurrent(null);
+ if( hasALC_thread_local_context ) {
+ alExt.alcSetThreadContext(null);
+ } else {
+ alc.alcMakeContextCurrent(null);
+ }
lock.unlock();
}
private final void destroyContext() {
@@ -251,6 +286,14 @@ public class ALAudioSink implements AudioSink {
"queue[g "+frameGrowAmount+", l "+frameLimit+"]";
}
+ private final String shortString() {
+ final int alSrcName = null != alSource ? alSource[0] : 0;
+ final int ctxHash = context != null ? context.hashCode() : 0;
+ return "[ctx "+toHexString(ctxHash)+", playReq "+playRequested+", alSrc "+alSrcName+
+ ", queued["+alFramesPlaying.size()+", " + alBufferBytesQueued+" bytes], "+
+ "queue[g "+frameGrowAmount+", l "+frameLimit+"]";
+ }
+
public final String getPerfString() {
final int alBuffersLen = null != alBufferNames ? alBufferNames.length : 0;
return "Play [buffer "+alFramesPlaying.size()+"/"+alBuffersLen+", apts "+getPTS()+", "+getQueuedTime() + " ms, " + alBufferBytesQueued+" bytes]";
@@ -325,9 +368,9 @@ public class ALAudioSink implements AudioSink {
alBufferNames = new int[initialFrameCount];
al.alGenBuffers(initialFrameCount, alBufferNames, 0);
final int err = al.alGetError();
- if( err != AL.AL_NO_ERROR ) {
+ if( AL.AL_NO_ERROR != err ) {
alBufferNames = null;
- throw new RuntimeException("ALAudioSink: Error generating Buffers: 0x"+Integer.toHexString(err));
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error generating Buffers: 0x"+Integer.toHexString(err));
}
final ALAudioFrame[] alFrames = new ALAudioFrame[initialFrameCount];
for(int i=0; i<initialFrameCount; i++) {
@@ -340,6 +383,10 @@ public class ALAudioSink implements AudioSink {
queueGrowAmount > 0 ? queueGrowAmount : AudioSink.DefaultQueueGrowAmount, useFrameDuration);
this.frameLimit = requestedFormat.getFrameCount(
queueLimit > 0 ? queueLimit : AudioSink.DefaultQueueLimitWithVideo, useFrameDuration);
+ if( DEBUG_TRACE ) {
+ alFramesAvail.dump(System.err, "Avail-init");
+ alFramesPlaying.dump(System.err, "Playi-init");
+ }
}
} finally {
unlockContext();
@@ -375,7 +422,7 @@ public class ALAudioSink implements AudioSink {
final int[] newALBufferNames = new int[frameGrowAmount];
al.alGenBuffers(frameGrowAmount, newALBufferNames, 0);
final int err = al.alGetError();
- if( err != AL.AL_NO_ERROR ) {
+ if( AL.AL_NO_ERROR != err ) {
if( DEBUG ) {
System.err.println(getThreadName()+": ALAudioSink.growBuffers: Error generating "+frameGrowAmount+" new Buffers: 0x"+Integer.toHexString(err));
}
@@ -397,6 +444,10 @@ public class ALAudioSink implements AudioSink {
if( DEBUG ) {
System.err.println(getThreadName()+": ALAudioSink: Buffer grown "+frameGrowAmount+": Avail "+alFramesAvail+", playing "+alFramesPlaying);
}
+ if( DEBUG_TRACE ) {
+ alFramesAvail.dump(System.err, "Avail-grow");
+ alFramesPlaying.dump(System.err, "Playi-grow");
+ }
return true;
}
@@ -433,7 +484,7 @@ public class ALAudioSink implements AudioSink {
lockContext();
}
try {
- stopImpl();
+ stopImpl(true);
if( null != alSource ) {
try {
al.alDeleteSources(1, alSource, 0);
@@ -469,7 +520,7 @@ public class ALAudioSink implements AudioSink {
return initialized;
}
- private final int dequeueBuffer(boolean wait) {
+ private final int dequeueBuffer(final boolean wait, final boolean ignoreBufferInconsistency) {
int alErr = AL.AL_NO_ERROR;
final int releaseBufferCount;
if( alBufferBytesQueued > 0 ) {
@@ -480,7 +531,7 @@ public class ALAudioSink implements AudioSink {
al.alGetSourcei(alSource[0], AL.AL_BUFFERS_PROCESSED, val, 0);
alErr = al.alGetError();
if( AL.AL_NO_ERROR != alErr ) {
- throw new RuntimeException("ALError "+toHexString(alErr)+" while quering processed buffers at source. "+this);
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while quering processed buffers at source. "+this);
}
if( wait && val[0] < releaseBufferLimes ) {
i++;
@@ -488,7 +539,7 @@ public class ALAudioSink implements AudioSink {
final int avgBufferDura = chosenFormat.getBytesDuration( alBufferBytesQueued / alFramesPlaying.size() );
final int sleep = Math.max(2, Math.min(100, releaseBufferLimes * avgBufferDura));
if( DEBUG ) {
- System.err.println(getThreadName()+": ALAudioSink: Dequeue.wait["+i+"]: avgBufferDura "+avgBufferDura+", releaseBufferLimes "+releaseBufferLimes+", sleep "+sleep+" ms, playImpl "+(AL.AL_PLAYING == getSourceState())+", processed "+val[0]+", "+this);
+ System.err.println(getThreadName()+": ALAudioSink: Dequeue.wait["+i+"]: avgBufferDura "+avgBufferDura+", releaseBufferLimes "+releaseBufferLimes+", sleep "+sleep+" ms, playImpl "+(AL.AL_PLAYING == getSourceState(false))+", processed "+val[0]+", "+this);
}
unlockContext();
try {
@@ -505,31 +556,51 @@ public class ALAudioSink implements AudioSink {
}
if( releaseBufferCount > 0 ) {
- int[] buffers=new int[releaseBufferCount];
+ final int[] buffers = new int[releaseBufferCount];
al.alSourceUnqueueBuffers(alSource[0], releaseBufferCount, buffers, 0);
alErr = al.alGetError();
if( AL.AL_NO_ERROR != alErr ) {
- throw new RuntimeException("ALError "+toHexString(alErr)+" while dequeueing "+releaseBufferCount+" buffers. "+this);
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while dequeueing "+releaseBufferCount+" buffers. "+this);
}
for ( int i=0; i<releaseBufferCount; i++ ) {
final ALAudioFrame releasedBuffer = alFramesPlaying.get();
if( null == releasedBuffer ) {
- throw new InternalError("Internal Error: "+this);
- }
- if( releasedBuffer.alBuffer != buffers[i] ) {
- alFramesAvail.dump(System.err, "Avail-deq02-post");
- alFramesPlaying.dump(System.err, "Playi-deq02-post");
- throw new InternalError("Buffer name mismatch: dequeued: "+buffers[i]+", released "+releasedBuffer+", "+this);
+ if( !ignoreBufferInconsistency ) {
+ throw new InternalError("Internal Error: "+this);
+ }
+ } else {
+ if(DEBUG_TRACE) {
+ System.err.println("< [al "+buffers[i]+", q "+releasedBuffer.alBuffer+"] <- "+shortString()+" @ "+getThreadName());
+ }
+ if( releasedBuffer.alBuffer != buffers[i] ) {
+ if( !ignoreBufferInconsistency ) {
+ alFramesAvail.dump(System.err, "Avail-deq02-post");
+ alFramesPlaying.dump(System.err, "Playi-deq02-post");
+ throw new InternalError("Buffer name mismatch: dequeued: "+buffers[i]+", released "+releasedBuffer+", "+this);
+ }
+ }
}
alBufferBytesQueued -= releasedBuffer.getByteSize();
if( !alFramesAvail.put(releasedBuffer) ) {
throw new InternalError("Internal Error: "+this);
}
+ if(DEBUG_TRACE) {
+ System.err.println("<< [al "+buffers[i]+", q "+releasedBuffer.alBuffer+"] <- "+shortString()+" @ "+getThreadName());
+ }
}
}
return releaseBufferCount;
}
private final void dequeueForceAll() {
+ if(DEBUG_TRACE) {
+ System.err.println("< _FLUSH_ <- "+shortString()+" @ "+getThreadName());
+ }
+ final int[] val=new int[1];
+ al.alSourcei(alSource[0], AL.AL_BUFFER, 0); // explicit force zero buffer!
+ if(DEBUG_TRACE) {
+ al.alGetSourcei(alSource[0], AL.AL_BUFFERS_PROCESSED, val, 0);
+ }
+ final int alErr = al.alGetError();
while ( !alFramesPlaying.isEmpty() ) {
final ALAudioFrame releasedBuffer = alFramesPlaying.get();
if( null == releasedBuffer ) {
@@ -540,13 +611,15 @@ public class ALAudioSink implements AudioSink {
throw new InternalError("Internal Error: "+this);
}
}
- if( 0 != alBufferBytesQueued ) {
- throw new InternalError("Internal Error: "+this);
+ alBufferBytesQueued = 0;
+ if(DEBUG_TRACE) {
+ System.err.println("<< _FLUSH_ [al "+val[0]+", err "+toHexString(alErr)+"] <- "+shortString()+" @ "+getThreadName());
+ Thread.dumpStack();
}
}
private final int dequeueBuffer(boolean wait, int inPTS, int inDuration) {
- final int dequeuedBufferCount = dequeueBuffer( wait );
+ final int dequeuedBufferCount = dequeueBuffer( wait, false /* ignoreBufferInconsistency */ );
final ALAudioFrame currentBuffer = alFramesPlaying.peek();
if( null != currentBuffer ) {
playingPTS = currentBuffer.getPTS();
@@ -572,18 +645,12 @@ public class ALAudioSink implements AudioSink {
return null;
}
final ALAudioFrame alFrame;
- int alErr = AL.AL_NO_ERROR;
// OpenAL consumes buffers in the background
// we first need to initialize the OpenAL buffers then
// start continuous playback.
lockContext();
try {
- alErr = al.alGetError();
- if(al.alGetError() != AL.AL_NO_ERROR) {
- throw new RuntimeException("ALError "+toHexString(alErr)+" while makeCurrent. "+this);
- }
-
final int duration = chosenFormat.getBytesDuration(byteCount);
final boolean dequeueDone;
if( alFramesAvail.isEmpty() ) {
@@ -612,6 +679,7 @@ public class ALAudioSink implements AudioSink {
if( !alFramesPlaying.put( alFrame ) ) {
throw new InternalError("Internal Error: "+this);
}
+ final int[] alBufferNames = new int[] { alFrame.alBuffer };
if( hasSOFTBufferSamples ) {
final int samplesPerChannel = chosenFormat.getBytesSampleCount(byteCount) / chosenFormat.channelCount;
// final int samplesPerChannel = ALHelpers.bytesToSampleCount(byteCount, alChannelLayout, alSampleType);
@@ -621,15 +689,22 @@ public class ALAudioSink implements AudioSink {
al.alBufferData(alFrame.alBuffer, alFormat, bytes, byteCount, chosenFormat.sampleRate);
}
- final int[] alBufferNames = new int[] { alFrame.alBuffer };
+ if(DEBUG_TRACE) {
+ System.err.println("> "+alFrame.alBuffer+" -> "+shortString()+" @ "+getThreadName());
+ }
+
al.alSourceQueueBuffers(alSource[0], 1, alBufferNames, 0);
- alErr = al.alGetError();
- if(al.alGetError() != AL.AL_NO_ERROR) {
- throw new RuntimeException("ALError "+toHexString(alErr)+" while queueing buffer "+toHexString(alBufferNames[0])+". "+this);
+ final int alErr = al.alGetError();
+ if( AL.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while queueing buffer "+toHexString(alBufferNames[0])+". "+this);
}
alBufferBytesQueued += byteCount;
enqueuedFrameCount++;
+ if(DEBUG_TRACE) {
+ System.err.println(">> "+alFrame.alBuffer+" -> "+shortString()+" @ "+getThreadName());
+ }
+
playImpl(); // continue playing, fixes issue where we ran out of enqueued data!
} finally {
unlockContext();
@@ -655,17 +730,24 @@ public class ALAudioSink implements AudioSink {
}
private final boolean isPlayingImpl0() {
if( playRequested ) {
- return AL.AL_PLAYING == getSourceState();
+ return AL.AL_PLAYING == getSourceState(false);
} else {
return false;
}
}
- private final int getSourceState() {
+ private final int getSourceState(boolean ignoreError) {
final int[] val = new int[1];
al.alGetSourcei(alSource[0], AL.AL_SOURCE_STATE, val, 0);
final int alErr = al.alGetError();
- if(al.alGetError() != AL.AL_NO_ERROR) {
- throw new RuntimeException("ALError "+toHexString(alErr)+" while querying SOURCE_STATE. "+this);
+ if( AL.AL_NO_ERROR != alErr ) {
+ final String msg = getThreadName()+": ALError "+toHexString(alErr)+" while querying SOURCE_STATE. "+this;
+ if( ignoreError ) {
+ if( DEBUG ) {
+ System.err.println(msg);
+ }
+ } else {
+ throw new RuntimeException(msg);
+ }
}
return val[0];
}
@@ -680,18 +762,18 @@ public class ALAudioSink implements AudioSink {
try {
playImpl();
if( DEBUG ) {
- System.err.println(getThreadName()+": ALAudioSink: PLAY playImpl "+(AL.AL_PLAYING == getSourceState())+", "+this);
+ System.err.println(getThreadName()+": ALAudioSink: PLAY playImpl "+(AL.AL_PLAYING == getSourceState(false))+", "+this);
}
} finally {
unlockContext();
}
}
private final void playImpl() {
- if( playRequested && AL.AL_PLAYING != getSourceState() ) {
+ if( playRequested && AL.AL_PLAYING != getSourceState(false) ) {
al.alSourcePlay(alSource[0]);
final int alErr = al.alGetError();
- if(al.alGetError() != AL.AL_NO_ERROR) {
- throw new RuntimeException("ALError "+toHexString(alErr)+" while start playing. "+this);
+ if( AL.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while start playing. "+this);
}
}
}
@@ -706,7 +788,7 @@ public class ALAudioSink implements AudioSink {
try {
pauseImpl();
if( DEBUG ) {
- System.err.println(getThreadName()+": ALAudioSink: PAUSE playImpl "+(AL.AL_PLAYING == getSourceState())+", "+this);
+ System.err.println(getThreadName()+": ALAudioSink: PAUSE playImpl "+(AL.AL_PLAYING == getSourceState(false))+", "+this);
}
} finally {
unlockContext();
@@ -718,18 +800,25 @@ public class ALAudioSink implements AudioSink {
playRequested = false;
al.alSourcePause(alSource[0]);
final int alErr = al.alGetError();
- if(al.alGetError() != AL.AL_NO_ERROR) {
- throw new RuntimeException("ALError "+toHexString(alErr)+" while pausing. "+this);
+ if( AL.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while pausing. "+this);
}
}
}
- private final void stopImpl() {
- if( AL.AL_STOPPED != getSourceState() ) {
+ private final void stopImpl(boolean ignoreError) {
+ if( AL.AL_STOPPED != getSourceState(ignoreError) ) {
playRequested = false;
al.alSourceStop(alSource[0]);
final int alErr = al.alGetError();
- if(al.alGetError() != AL.AL_NO_ERROR) {
- throw new RuntimeException("ALError "+toHexString(alErr)+" while pausing. "+this);
+ if( AL.AL_NO_ERROR != alErr ) {
+ final String msg = "ALError "+toHexString(alErr)+" while stopping. "+this;
+ if( ignoreError ) {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": "+msg);
+ }
+ } else {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while stopping. "+this);
+ }
}
}
}
@@ -794,15 +883,14 @@ public class ALAudioSink implements AudioSink {
lockContext();
try {
// pauseImpl();
- stopImpl();
- al.alSourcei(alSource[0], AL.AL_BUFFER, 0); // explicit force zero buffer!
- dequeueBuffer( false /* wait */ );
+ stopImpl(false);
+ // Redundant: dequeueBuffer( false /* wait */, true /* ignoreBufferInconsistency */);
dequeueForceAll();
if( alBufferNames.length != alFramesAvail.size() || alFramesPlaying.size() != 0 ) {
throw new InternalError("XXX: "+this);
}
if( DEBUG ) {
- System.err.println(getThreadName()+": ALAudioSink: FLUSH playImpl "+(AL.AL_PLAYING == getSourceState())+", "+this);
+ System.err.println(getThreadName()+": ALAudioSink: FLUSH playImpl "+(AL.AL_PLAYING == getSourceState(false))+", "+this);
}
} finally {
unlockContext();
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
index 7cea51d..6a0e006 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
@@ -1127,7 +1127,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
if( isBlocked && isActive ) {
this.interrupt();
}
- while( isActive ) {
+ while( isActive && isRunning ) {
try {
this.wait(); // wait until paused
} catch (InterruptedException e) {
@@ -1141,7 +1141,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
if( isRunning && !isActive ) {
shallPause = false;
if( Thread.currentThread() != this ) {
- while( !isActive ) {
+ while( !isActive && !shallPause && isRunning ) {
this.notifyAll(); // wake-up pause-block
try {
this.wait(); // wait until resumed
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
index bc0865a..b4b887b 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
@@ -29,17 +29,22 @@ package jogamp.opengl.util.av.impl;
import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
-interface FFMPEGNatives {
+/* pp */ abstract class FFMPEGNatives {
- boolean initSymbols0(long[] symbols, int count);
- int getAvUtilMajorVersionCC0();
- int getAvFormatMajorVersionCC0();
- int getAvCodecMajorVersionCC0();
- int getAvResampleMajorVersionCC0();
- int getSwResampleMajorVersionCC0();
+ private static final Object mutex_avcodec_openclose_jni = new Object();
- long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
- void destroyInstance0(long moviePtr);
+ final boolean initSymbols0(long[] symbols, int count) {
+ return initSymbols0(mutex_avcodec_openclose_jni, symbols, count);
+ }
+ abstract boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
+ abstract int getAvUtilMajorVersionCC0();
+ abstract int getAvFormatMajorVersionCC0();
+ abstract int getAvCodecMajorVersionCC0();
+ abstract int getAvResampleMajorVersionCC0();
+ abstract int getSwResampleMajorVersionCC0();
+
+ abstract long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+ abstract void destroyInstance0(long moviePtr);
/**
* Issues {@link #updateAttributes(int, int, int, int, int, int, int, float, int, int, String, String)}
@@ -56,24 +61,24 @@ interface FFMPEGNatives {
* @param aPrefSampleRate
* @param aPrefChannelCount
*/
- void setStream0(long moviePtr, String url, boolean isCameraInput,
- int vid, String sizes, int vWidth, int vHeight,
- int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+ abstract void setStream0(long moviePtr, String url, boolean isCameraInput,
+ int vid, String sizes, int vWidth, int vHeight,
+ int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
- void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+ abstract void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
- int getVideoPTS0(long moviePtr);
+ abstract int getVideoPTS0(long moviePtr);
- int getAudioPTS0(long moviePtr);
+ abstract int getAudioPTS0(long moviePtr);
/**
* @return resulting current video PTS, or {@link TextureFrame#INVALID_PTS}
*/
- int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+ abstract int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
- int play0(long moviePtr);
- int pause0(long moviePtr);
- int seek0(long moviePtr, int position);
+ abstract int play0(long moviePtr);
+ abstract int pause0(long moviePtr);
+ abstract int seek0(long moviePtr, int position);
/** FFMPEG/libAV Audio Sample Format */
public static enum SampleFormat {
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
index 4b013c1..6bab23f 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
@@ -27,52 +27,52 @@
*/
package jogamp.opengl.util.av.impl;
-class FFMPEGv08Natives implements FFMPEGNatives {
+class FFMPEGv08Natives extends FFMPEGNatives {
@Override
- public native boolean initSymbols0(long[] symbols, int count);
+ native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
@Override
- public native int getAvUtilMajorVersionCC0();
+ native int getAvUtilMajorVersionCC0();
@Override
- public native int getAvFormatMajorVersionCC0();
+ native int getAvFormatMajorVersionCC0();
@Override
- public native int getAvCodecMajorVersionCC0();
+ native int getAvCodecMajorVersionCC0();
@Override
- public native int getAvResampleMajorVersionCC0();
+ native int getAvResampleMajorVersionCC0();
@Override
- public native int getSwResampleMajorVersionCC0();
+ native int getSwResampleMajorVersionCC0();
@Override
- public native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+ native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
@Override
- public native void destroyInstance0(long moviePtr);
+ native void destroyInstance0(long moviePtr);
@Override
- public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+ native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
@Override
- public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
@Override
- public native int getVideoPTS0(long moviePtr);
+ native int getVideoPTS0(long moviePtr);
@Override
- public native int getAudioPTS0(long moviePtr);
+ native int getAudioPTS0(long moviePtr);
@Override
- public native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+ native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
@Override
- public native int play0(long moviePtr);
+ native int play0(long moviePtr);
@Override
- public native int pause0(long moviePtr);
+ native int pause0(long moviePtr);
@Override
- public native int seek0(long moviePtr, int position);
+ native int seek0(long moviePtr, int position);
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
index d697632..a48b5f2 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
@@ -27,52 +27,52 @@
*/
package jogamp.opengl.util.av.impl;
-class FFMPEGv09Natives implements FFMPEGNatives {
+class FFMPEGv09Natives extends FFMPEGNatives {
@Override
- public native boolean initSymbols0(long[] symbols, int count);
+ native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
@Override
- public native int getAvUtilMajorVersionCC0();
+ native int getAvUtilMajorVersionCC0();
@Override
- public native int getAvFormatMajorVersionCC0();
+ native int getAvFormatMajorVersionCC0();
@Override
- public native int getAvCodecMajorVersionCC0();
+ native int getAvCodecMajorVersionCC0();
@Override
- public native int getAvResampleMajorVersionCC0();
+ native int getAvResampleMajorVersionCC0();
@Override
- public native int getSwResampleMajorVersionCC0();
+ native int getSwResampleMajorVersionCC0();
@Override
- public native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+ native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
@Override
- public native void destroyInstance0(long moviePtr);
+ native void destroyInstance0(long moviePtr);
@Override
- public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+ native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
@Override
- public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
@Override
- public native int getVideoPTS0(long moviePtr);
+ native int getVideoPTS0(long moviePtr);
@Override
- public native int getAudioPTS0(long moviePtr);
+ native int getAudioPTS0(long moviePtr);
@Override
- public native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+ native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
@Override
- public native int play0(long moviePtr);
+ native int play0(long moviePtr);
@Override
- public native int pause0(long moviePtr);
+ native int pause0(long moviePtr);
@Override
- public native int seek0(long moviePtr, int position);
+ native int seek0(long moviePtr, int position);
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
index 0b5f70d..f35fb29 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
@@ -27,52 +27,52 @@
*/
package jogamp.opengl.util.av.impl;
-class FFMPEGv10Natives implements FFMPEGNatives {
+class FFMPEGv10Natives extends FFMPEGNatives {
@Override
- public native boolean initSymbols0(long[] symbols, int count);
+ native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
@Override
- public native int getAvUtilMajorVersionCC0();
+ native int getAvUtilMajorVersionCC0();
@Override
- public native int getAvFormatMajorVersionCC0();
+ native int getAvFormatMajorVersionCC0();
@Override
- public native int getAvCodecMajorVersionCC0();
+ native int getAvCodecMajorVersionCC0();
@Override
- public native int getAvResampleMajorVersionCC0();
+ native int getAvResampleMajorVersionCC0();
@Override
- public native int getSwResampleMajorVersionCC0();
+ native int getSwResampleMajorVersionCC0();
@Override
- public native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+ native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
@Override
- public native void destroyInstance0(long moviePtr);
+ native void destroyInstance0(long moviePtr);
@Override
- public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+ native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
@Override
- public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
@Override
- public native int getVideoPTS0(long moviePtr);
+ native int getVideoPTS0(long moviePtr);
@Override
- public native int getAudioPTS0(long moviePtr);
+ native int getAudioPTS0(long moviePtr);
@Override
- public native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+ native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
@Override
- public native int play0(long moviePtr);
+ native int play0(long moviePtr);
@Override
- public native int pause0(long moviePtr);
+ native int pause0(long moviePtr);
@Override
- public native int seek0(long moviePtr, int position);
+ native int seek0(long moviePtr, int position);
}
diff --git a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
index d5b01ef..45087ea 100644
--- a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
+++ b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
@@ -56,7 +56,6 @@
package jogamp.opengl.util.jpeg;
-import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -65,6 +64,7 @@ import java.util.Arrays;
import jogamp.opengl.Debug;
import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.Bitstream;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureData.ColorSpace;
@@ -446,9 +446,7 @@ public class JPEGDecoder {
return "JPEG[size "+width+"x"+height+", compOut "+compOuts+", "+jfifS+", "+exifS+", "+adobeS+"]";
}
- private BufferedInputStream istream;
- private int _ipos = 0;
- private int _iposSave = 0;
+ private final Bitstream<InputStream> bstream = new Bitstream<InputStream>(new Bitstream.ByteInputStream(null), false /* outputMode */);
private int width = 0;
private int height = 0;
@@ -463,66 +461,36 @@ public class JPEGDecoder {
public final int getWidth() { return width; }
public final int getHeight() { return height; }
- private final void resetInput(InputStream is) {
- if( is instanceof BufferedInputStream ) {
- istream = (BufferedInputStream) is;
- } else {
- istream = new BufferedInputStream(is);
+ private final void setStream(InputStream is) {
+ try {
+ bstream.setStream(is, false /* outputMode */);
+ } catch (Exception e) {
+ throw new RuntimeException(e); // should not happen, no flush()
}
- _ipos = 0;
}
- private final void markStream(int readLimit) {
- istream.mark(readLimit);
- _iposSave = _ipos;
- }
- private final void rewindStream() throws IOException {
- if(DEBUG_IN) { System.err.println("JPG.rewindStream: "+_ipos+" -> "+_iposSave); }
- istream.reset();
- _ipos = _iposSave;
- _iposSave = 0;
- }
- private final int readUint8() throws IOException {
- final int r = istream.read();
- if( -1 < r ) {
- if(DEBUG_IN) { System.err.println("u8["+_ipos+"]: "+toHexString(r)); }
- _ipos++;
- } else if(DEBUG_IN) {
- System.err.println("u8["+_ipos+"]: EOS");
- }
- return r;
+ private final int readUInt8() throws IOException {
+ return bstream.readUInt8(true /* msbFirst */);
}
- private final int readUint16() throws IOException {
- final int hi = istream.read();
- if( -1 < hi ) {
- _ipos++;
- final int lo = istream.read();
- if( -1 < lo ) {
- _ipos++;
- final int r = hi << 8 | lo ;
- if(DEBUG_IN) { System.err.println("u16["+(_ipos-2)+"]: "+toHexString(r)); }
- return r;
- }
- }
- if(DEBUG_IN) { System.err.println("u16["+_ipos+"]: EOS"); }
- return -1;
+ private final int readUInt16() throws IOException {
+ return bstream.readUInt16(true /* msbFirst */, true /* bigEndian */);
}
private final int readNumber() throws IOException {
- final int len=readUint16();
+ final int len=readUInt16();
if(len!=4){
throw new CodecException("ERROR: Define number format error [Len!=4, but "+len+"]");
}
- return readUint16();
+ return readUInt16();
}
private final byte[] readDataBlock() throws IOException {
int count=0, i=0;
- final int len=readUint16(); count+=2;
+ final int len=readUInt16(); count+=2;
byte[] data = new byte[len-2];
while(count<len){
- data[i++] = (byte)readUint8(); count++;
+ data[i++] = (byte)readUInt8(); count++;
}
if(DEBUG_IN) { System.err.println("JPEG.readDataBlock: net-len "+(len-2)+", "+this); dumpData(data, 0, len-2); }
return data;
@@ -531,14 +499,14 @@ public class JPEGDecoder {
for(int i=0; i<len; ) {
System.err.print(i%8+": ");
for(int j=0; j<8 && i<len; j++, i++) {
- System.err.println(toHexString(0x000000FF & data[offset+i])+", ");
+ System.err.print(toHexString(0x000000FF & data[offset+i])+", ");
}
System.err.println("");
}
}
public synchronized void clear(InputStream inputStream) {
- resetInput(inputStream);
+ setStream(inputStream);
width = 0;
height = 0;
jfif = null;
@@ -556,12 +524,12 @@ public class JPEGDecoder {
Frame frame = null;
int resetInterval = 0;
- int fileMarker = readUint16();
+ int fileMarker = readUInt16();
if ( fileMarker != M_SOI ) {
throw new CodecException("SOI not found, but has marker "+toHexString(fileMarker));
}
- fileMarker = readUint16();
+ fileMarker = readUInt16();
while (fileMarker != M_EOI) {
if(DEBUG) { System.err.println("JPG.parse got marker "+toHexString(fileMarker)); }
switch(fileMarker) {
@@ -599,21 +567,21 @@ public class JPEGDecoder {
case M_QTT: {
int count = 0;
- final int quantizationTablesLength = readUint16(); count+=2;
+ final int quantizationTablesLength = readUInt16(); count+=2;
while( count < quantizationTablesLength ) {
- final int quantizationTableSpec = readUint8(); count++;
+ final int quantizationTableSpec = readUInt8(); count++;
final int precisionID = quantizationTableSpec >> 4;
final int tableIdx = quantizationTableSpec & 0x0F;
final int[] tableData = new int[64];
if ( precisionID == 0 ) { // 8 bit values
for (int j = 0; j < 64; j++) {
final int z = dctZigZag[j];
- tableData[z] = readUint8(); count++;
+ tableData[z] = readUInt8(); count++;
}
} else if ( precisionID == 1) { //16 bit
for (int j = 0; j < 64; j++) {
final int z = dctZigZag[j];
- tableData[z] = readUint16(); count+=2;
+ tableData[z] = readUInt16(); count+=2;
}
} else {
throw new CodecException("DQT: invalid table precision "+precisionID+", quantizationTableSpec "+quantizationTableSpec+", idx "+tableIdx);
@@ -636,24 +604,24 @@ public class JPEGDecoder {
throw new CodecException("only single frame JPEGs supported");
}
int count = 0;
- final int sofLen = readUint16(); count+=2; // header length;
+ final int sofLen = readUInt16(); count+=2; // header length;
final int componentsCount;
{
final boolean progressive = (fileMarker == M_SOF2);
- final int precision = readUint8(); count++;
- final int scanLines = readUint16(); count+=2;
- final int samplesPerLine = readUint16(); count+=2;
- componentsCount = readUint8(); count++;
+ final int precision = readUInt8(); count++;
+ final int scanLines = readUInt16(); count+=2;
+ final int samplesPerLine = readUInt16(); count+=2;
+ componentsCount = readUInt8(); count++;
frame = new Frame(progressive, precision, scanLines, samplesPerLine, componentsCount, quantizationTables);
width = frame.samplesPerLine;
height = frame.scanLines;
}
for (int i = 0; i < componentsCount; i++) {
- final int componentId = readUint8(); count++;
- final int temp = readUint8(); count++;
+ final int componentId = readUInt8(); count++;
+ final int temp = readUInt8(); count++;
final int h = temp >> 4;
final int v = temp & 0x0F;
- final int qttIdx = readUint8(); count++;
+ final int qttIdx = readUInt8(); count++;
final ComponentIn compIn = new ComponentIn(h, v, qttIdx);
frame.putOrdered(componentId, compIn);
}
@@ -669,18 +637,18 @@ public class JPEGDecoder {
case M_DHT: {
int count = 0;
- final int huffmanLength = readUint16(); count+=2;
+ final int huffmanLength = readUInt16(); count+=2;
int i=count, codeLengthTotal = 0;
while( i < huffmanLength ) {
- final int huffmanTableSpec = readUint8(); count++;
+ final int huffmanTableSpec = readUInt8(); count++;
final int[] codeLengths = new int[16];
int codeLengthSum = 0;
for (int j = 0; j < 16; j++) {
- codeLengthSum += (codeLengths[j] = readUint8()); count++;
+ codeLengthSum += (codeLengths[j] = readUInt8()); count++;
}
final byte[] huffmanValues = new byte[codeLengthSum];
for (int j = 0; j < codeLengthSum; j++) {
- huffmanValues[j] = (byte)readUint8(); count++;
+ huffmanValues[j] = (byte)readUInt8(); count++;
}
codeLengthTotal += codeLengthSum;
i += 17 + codeLengthSum;
@@ -703,21 +671,21 @@ public class JPEGDecoder {
case M_SOS: {
int count = 0;
- final int sosLen = readUint16(); count+=2;
- final int selectorsCount = readUint8(); count++;
+ final int sosLen = readUInt16(); count+=2;
+ final int selectorsCount = readUInt8(); count++;
ArrayList<ComponentIn> components = new ArrayList<ComponentIn>();
if(DEBUG) { System.err.println("JPG.parse.SOS: selectorCount [0.."+(selectorsCount-1)+"]: "+frame); }
for (int i = 0; i < selectorsCount; i++) {
- final int compID = readUint8(); count++;
+ final int compID = readUInt8(); count++;
final ComponentIn component = frame.getCompByID(compID);
- final int tableSpec = readUint8(); count++;
+ final int tableSpec = readUInt8(); count++;
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
components.add(component);
}
- final int spectralStart = readUint8(); count++;
- final int spectralEnd = readUint8(); count++;
- final int successiveApproximation = readUint8(); count++;
+ final int spectralStart = readUInt8(); count++;
+ final int spectralEnd = readUInt8(); count++;
+ final int successiveApproximation = readUInt8(); count++;
if(count!=sosLen){
throw new CodecException("ERROR: scan header format error [count!=Length]");
}
@@ -736,10 +704,10 @@ public class JPEGDecoder {
offset -= 3;
break;
} */
- throw new CodecException("unknown JPEG marker " + toHexString(fileMarker));
+ throw new CodecException("unknown JPEG marker " + toHexString(fileMarker) + ", " + bstream);
}
if( 0 == fileMarker ) {
- fileMarker = readUint16();
+ fileMarker = readUInt16();
}
}
if(DEBUG) { System.err.println("JPG.parse.2: End of parsing input "+this); }
@@ -775,13 +743,13 @@ public class JPEGDecoder {
if (maxH < component.h) maxH = component.h;
if (maxV < component.v) maxV = component.v;
}
- int mcusPerLine = (int) Math.ceil((float)frame.samplesPerLine / 8f / (float)maxH);
- int mcusPerColumn = (int) Math.ceil((float)frame.scanLines / 8f / (float)maxV);
+ int mcusPerLine = (int) Math.ceil(frame.samplesPerLine / 8f / maxH);
+ int mcusPerColumn = (int) Math.ceil(frame.scanLines / 8f / maxV);
// for (componentId in frame.components) {
for (int i=0; i<compCount; i++) {
final ComponentIn component = frame.getCompByIndex(i);
- final int blocksPerLine = (int) Math.ceil(Math.ceil((float)frame.samplesPerLine / 8f) * component.h / maxH);
- final int blocksPerColumn = (int) Math.ceil(Math.ceil((float)frame.scanLines / 8f) * component.v / maxV);
+ final int blocksPerLine = (int) Math.ceil(Math.ceil(frame.samplesPerLine / 8f) * component.h / maxH);
+ final int blocksPerColumn = (int) Math.ceil(Math.ceil(frame.scanLines / 8f) * component.v / maxV);
final int blocksPerLineForMcu = mcusPerLine * component.h;
final int blocksPerColumnForMcu = mcusPerColumn * component.v;
component.allocateBlocks(blocksPerColumn, blocksPerColumnForMcu, blocksPerLine, blocksPerLineForMcu);
@@ -1066,7 +1034,6 @@ public class JPEGDecoder {
private int mcusPerLine;
private boolean progressive;
// private int maxH, maxV;
- private int bitsData, bitsCount;
private int spectralStart, spectralEnd;
private int successive;
private int eobrun;
@@ -1081,8 +1048,7 @@ public class JPEGDecoder {
this.progressive = frame.progressive;
// this.maxH = frame.maxH;
// this.maxV = frame.maxV;
- this.bitsData = 0;
- this.bitsCount = 0;
+ bstream.skip( bstream.getBitCount() ); // align to next byte
this.spectralStart = spectralStart;
this.spectralEnd = spectralEnd;
this.successive = successive;
@@ -1149,16 +1115,16 @@ public class JPEGDecoder {
return markerException.getMarker();
} catch (CodecException codecException) {
if(DEBUG) { System.err.println("JPEG.decodeScan: Codec exception: "+codecException.getMessage()); codecException.printStackTrace(); }
- bitsCount = 0;
+ bstream.skip( bstream.getBitCount() ); // align to next byte
return M_EOI; // force end !
}
// find marker
- bitsCount = 0;
- markStream(2);
- marker = readUint16();
+ bstream.skip( bstream.getBitCount() ); // align to next byte
+ bstream.mark(2);
+ marker = readUInt16();
if( marker < 0xFF00 ) {
- rewindStream();
+ bstream.reset();
throw new CodecException("marker not found @ mcu "+mcu+"/"+mcuExpected+", u16: "+toHexString(marker));
}
final boolean isRSTx = 0xFFD0 <= marker && marker <= 0xFFD7; // !RSTx
@@ -1172,28 +1138,25 @@ public class JPEGDecoder {
return marker;
}
- private int readBit() throws MarkerException, IOException {
- if (bitsCount > 0) {
- bitsCount--;
- return (bitsData >> bitsCount) & 1;
- }
- bitsData = readUint8();
- if( -1 == bitsData ) {
- return -1;
+ private final int readBit() throws MarkerException, IOException {
+ final int bit = bstream.readBit(true /* msbFirst */);
+ if( Bitstream.EOS == bit || 7 != bstream.getBitCount() ) {
+ return bit;
}
- if (bitsData == 0xFF) { // marker prefix
- final int nextByte = readUint8(); // marker signature
+ // new byte read, i.e. bitCount == 7
+ final int bitsData = bstream.getBitBuffer(); // peek for marker
+ if ( 0xFF == bitsData ) { // marker prefix
+ final int nextByte = bstream.getStream().read(); // snoop marker signature, will be dropped!
if( -1 == nextByte ) {
throw new CodecException("marked prefix 0xFF, then EOF");
}
if (0 != nextByte) {
final int marker = (bitsData << 8) | nextByte;
- throw new MarkerException(marker, "Marker at readBit file pos " + _ipos);
+ throw new MarkerException(marker, "Marker at readBit pos " + bstream);
}
// unstuff 0
}
- bitsCount = 7;
- return bitsData >>> 7;
+ return bit;
}
private int decodeHuffman(BinObj tree) throws IOException {
@@ -1205,7 +1168,7 @@ public class JPEGDecoder {
return 0x000000FF & node.getValue();
}
}
- throw new CodecException("EOF reached at "+_ipos);
+ throw new CodecException("EOF reached at "+bstream);
}
private int receive(int length) throws IOException {
int n = 0;
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index ee3e1a3..c0a3b46 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
@@ -254,7 +254,13 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
int val = 0;
final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
- int fbtype = glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp);
+ if( !glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp) ) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.FBCfgDrawableTypeBits: FBConfig invalid: fbcfg: "+toHexString(fbcfg));
+ }
+ return 0;
+ }
+ final int fbtype = tmp.get(0);
if ( 0 != ( fbtype & GLX.GLX_WINDOW_BIT ) ) {
val |= GLGraphicsConfigurationUtil.WINDOW_BIT |
@@ -314,8 +320,19 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
final long display = device.getHandle();
final int allDrawableTypeBits = FBCfgDrawableTypeBits(device, fbcfg);
int drawableTypeBits = winattrmask & allDrawableTypeBits;
-
+ if( 0 == allDrawableTypeBits || 0 == drawableTypeBits ) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: zero drawablebits: allDrawableTypeBits: "+toHexString(allDrawableTypeBits)+", drawableTypeBits "+toHexString(drawableTypeBits));
+ }
+ return null;
+ }
final int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
+ if( VisualIDHolder.VID_UNDEFINED == fbcfgid ) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: FBConfig invalid (0): fbcfg: "+toHexString(fbcfg));
+ }
+ return null;
+ }
final XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
if(null == visualInfo) {
if(DEBUG) {
@@ -415,20 +432,26 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
}
- static int glXGetFBConfig(long display, long cfg, int attrib, IntBuffer tmp) {
+ static boolean glXGetFBConfig(long display, long cfg, int attrib, IntBuffer tmp) {
if (display == 0) {
throw new GLException("No display connection");
}
- int res = GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp);
- if (res != 0) {
- throw new GLException("glXGetFBConfig("+toHexString(attrib)+") failed: error code " + glXGetFBConfigErrorCode(res));
+ final boolean res = GLX.GLX_BAD_ATTRIBUTE != GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp);
+ if( !res ) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.glXGetFBConfig: FBConfig invalid: fbcfg: "+toHexString(cfg));
+ }
}
- return tmp.get(tmp.position());
+ return res;
}
static int glXFBConfig2FBConfigID(long display, long cfg) {
final IntBuffer tmpID = Buffers.newDirectIntBuffer(1);
- return glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID);
+ if( glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID) ) {
+ return tmpID.get(0);
+ } else {
+ return VisualIDHolder.VID_UNDEFINED; // error
+ }
}
static long glXFBConfigID2FBConfig(long display, int screen, int id) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
index 1f92960..75771f8 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
@@ -258,13 +258,19 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
final long fbcfg = X11GLXGraphicsConfiguration.glXFBConfigID2FBConfig(display, screen, fbID);
if( 0 == fbcfg || !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfg ) ) {
if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed.0 - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
}
return null;
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glp, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, factory.isGLXMultisampleAvailable(x11Device));
+ if(null==caps) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed.1 - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
+ }
+ return null;
+ }
return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser());
}
diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c
index e86b2a5..a7e9f48 100644
--- a/src/jogl/native/libav/ffmpeg_impl_template.c
+++ b/src/jogl/native/libav/ffmpeg_impl_template.c
@@ -200,11 +200,36 @@ static SWR_FREE sp_swr_free;
static SWR_CONVERT sp_swr_convert;
// count: 65
+// We use JNI Monitor Locking, since this removes the need
+// to statically link-in pthreads on window ..
+// #define USE_PTHREAD_LOCKING 1
+//
+#define USE_JNI_LOCKING 1
+
+#if defined (USE_PTHREAD_LOCKING)
+ #include <pthread.h>
+ #warning USE LOCKING PTHREAD
+ static pthread_mutex_t mutex_avcodec_openclose;
+ #define MY_MUTEX_LOCK(e,s) pthread_mutex_lock(&(s))
+ #define MY_MUTEX_UNLOCK(e,s) pthread_mutex_unlock(&(s))
+#elif defined (USE_JNI_LOCKING)
+ static jobject mutex_avcodec_openclose;
+ #define MY_MUTEX_LOCK(e,s) (*e)->MonitorEnter(e, s)
+ #define MY_MUTEX_UNLOCK(e,s) (*e)->MonitorExit(e, s)
+#else
+ #warning USE LOCKING NONE
+ #define MY_MUTEX_LOCK(e,s)
+ #define MY_MUTEX_UNLOCK(e,s)
+#endif
+
#define SYMBOL_COUNT 65
JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
- (JNIEnv *env, jobject instance, jobject jSymbols, jint count)
+ (JNIEnv *env, jobject instance, jobject jmutex_avcodec_openclose, jobject jSymbols, jint count)
{
+ #ifdef USE_PTHREAD_LOCKING
+ pthread_mutexattr_t renderLockAttr;
+ #endif
int64_t* symbols; // jlong -> int64_t -> intptr_t -> FUNC_PTR
int i;
@@ -315,6 +340,23 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
}
#endif
+ #if defined (USE_PTHREAD_LOCKING)
+ pthread_mutexattr_init(&renderLockAttr);
+ pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mutex_avcodec_openclose, &renderLockAttr); // recursive
+ #elif defined (USE_JNI_LOCKING)
+ mutex_avcodec_openclose = (*env)->NewGlobalRef(env, jmutex_avcodec_openclose);
+ #endif
+
+ /** At static destroy: Never
+ #if defined (USE_PTHREAD_LOCKING)
+ pthread_mutex_unlock(&mutex_avcodec_openclose);
+ pthread_mutex_destroy(&mutex_avcodec_openclose);
+ #elif defined (USE_JNI_LOCKING)
+ (*env)->DeleteGlobalRef(env, mutex_avcodec_openclose);
+ #endif
+ */
+
return JNI_TRUE;
}
@@ -361,19 +403,23 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
pAV->aResampleBuffer = NULL;
}
- // Close the V codec
- if(NULL != pAV->pVCodecCtx) {
- sp_avcodec_close(pAV->pVCodecCtx);
- pAV->pVCodecCtx = NULL;
- }
- pAV->pVCodec=NULL;
+ MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+ {
+ // Close the V codec
+ if(NULL != pAV->pVCodecCtx) {
+ sp_avcodec_close(pAV->pVCodecCtx);
+ pAV->pVCodecCtx = NULL;
+ }
+ pAV->pVCodec=NULL;
- // Close the A codec
- if(NULL != pAV->pACodecCtx) {
- sp_avcodec_close(pAV->pACodecCtx);
- pAV->pACodecCtx = NULL;
+ // Close the A codec
+ if(NULL != pAV->pACodecCtx) {
+ sp_avcodec_close(pAV->pACodecCtx);
+ pAV->pACodecCtx = NULL;
+ }
+ pAV->pACodec=NULL;
}
- pAV->pACodec=NULL;
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
// Close the frames
if(NULL != pAV->pVFrame) {
@@ -421,6 +467,7 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
(*env)->DeleteGlobalRef(env, pAV->ffmpegMediaPlayer);
pAV->ffmpegMediaPlayer = NULL;
}
+
free(pAV);
}
}
@@ -709,22 +756,29 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
sp_av_dict_set(&inOpts, "framerate", buffer, 0);
}
}
- res = sp_avformat_open_input(&pAV->pFormatCtx, filename, inFmt, NULL != inOpts ? &inOpts : NULL);
- if( NULL != inOpts ) {
- sp_av_dict_free(&inOpts);
- }
- if(res != 0) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't open URI: %s [%dx%d @ %d hz], err %d", filename, vWidth, vHeight, vRate, res);
- (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
- return;
- }
- // Retrieve detailed stream information
- if(sp_avformat_find_stream_info(pAV->pFormatCtx, NULL)<0) {
- (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
- JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information");
- return;
+ MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+ {
+ res = sp_avformat_open_input(&pAV->pFormatCtx, filename, inFmt, NULL != inOpts ? &inOpts : NULL);
+ if( NULL != inOpts ) {
+ sp_av_dict_free(&inOpts);
+ }
+ if(res != 0) {
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+ JoglCommon_throwNewRuntimeException(env, "Couldn't open URI: %s [%dx%d @ %d hz], err %d", filename, vWidth, vHeight, vRate, res);
+ (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+ return;
+ }
+
+ // Retrieve detailed stream information
+ if(sp_avformat_find_stream_info(pAV->pFormatCtx, NULL)<0) {
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+ (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+ JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information");
+ return;
+ }
}
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
if(pAV->verbose) {
// Dump information about file onto standard error
@@ -732,7 +786,6 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
}
(*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
-
// FIXME: Libav Binary compatibility! JAU01
if (pAV->pFormatCtx->duration != AV_NOPTS_VALUE) {
pAV->duration = pAV->pFormatCtx->duration / AV_TIME_BASE_MSEC;
@@ -824,10 +877,14 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
}
// Open codec
- #if LIBAVCODEC_VERSION_MAJOR >= 55
- pAV->pACodecCtx->refcounted_frames = pAV->useRefCountedFrames;
- #endif
- res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL);
+ MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+ {
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ pAV->pACodecCtx->refcounted_frames = pAV->useRefCountedFrames;
+ #endif
+ res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL);
+ }
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
if(res<0) {
JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec);
return;
@@ -982,10 +1039,14 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
}
// Open codec
- #if LIBAVCODEC_VERSION_MAJOR >= 55
- pAV->pVCodecCtx->refcounted_frames = pAV->useRefCountedFrames;
- #endif
- res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL);
+ MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+ {
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ pAV->pVCodecCtx->refcounted_frames = pAV->useRefCountedFrames;
+ #endif
+ res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL);
+ }
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
if(res<0) {
JoglCommon_throwNewRuntimeException(env, "Couldn't open video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec);
return;
diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h
index 97e60af..136be2e 100644
--- a/src/jogl/native/libav/ffmpeg_tool.h
+++ b/src/jogl/native/libav/ffmpeg_tool.h
@@ -130,7 +130,6 @@ typedef struct {
int64_t dtsLast; // DTS of the last frame
} PTSStats;
-
typedef struct {
jobject ffmpegMediaPlayer;
int32_t verbose;
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index a57dafc..bb7b447 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -432,36 +432,15 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
public final boolean hideCursor() {
AWTEDTExecutor.singleton.invoke(false, new Runnable() {
public void run() {
- component.setCursor(AWTMisc.getNullCursor());
+ final Cursor cursor = AWTMisc.getNullCursor();
+ if( null != cursor ) {
+ component.setCursor(cursor);
+ }
} } );
return true;
}
//
- // SurfaceUpdateListener
- //
-
- @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);
- }
-
- //
// NativeSurface
//
@@ -572,6 +551,26 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
@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 long getSurfaceHandle() {
return drawable;
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index 15a43cf..034bf24 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -43,7 +43,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.util.PointImmutable;
import jogamp.nativewindow.Debug;
@@ -462,7 +461,7 @@ public abstract class NativeWindowFactory {
* @see #getDefaultToolkitLock(java.lang.String)
*/
public static ToolkitLock getDefaultToolkitLock() {
- return getDefaultToolkitLock(getNativeWindowType(false));
+ return getDefaultToolkitLock(nativeWindowingTypePure);
}
/**
@@ -655,8 +654,16 @@ public abstract class NativeWindowFactory {
return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
} else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ /**
+ * FIXME: Needs service provider interface (SPI) for TK dependent implementation
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_ANDROID== nwt ) {
+ } else if( NativeWindowFactory.TYPE_EGL == nwt ) {
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_AWT == nwt ) {
+ */
}
- throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+ throw new UnsupportedOperationException("n/a for windowing system: "+nwt);
}
/**
@@ -687,8 +694,16 @@ public abstract class NativeWindowFactory {
return GDIUtil.GetRelativeLocation(nw.getWindowHandle(), 0, 0, 0);
} else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
return OSXUtil.GetLocationOnScreen(nw.getWindowHandle(), null == nw.getParent(), 0, 0);
+ /**
+ * FIXME: Needs service provider interface (SPI) for TK dependent implementation
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_ANDROID== nwt ) {
+ } else if( NativeWindowFactory.TYPE_EGL == nwt ) {
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_AWT == nwt ) {
+ */
}
- throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+ throw new UnsupportedOperationException("n/a for windowing system: "+nwt);
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
index 361d034..87a9ca4 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
@@ -208,7 +208,6 @@ public class PixelFormatUtil {
return convertToInt32(dest_fmt, r, g, b, a);
}
- /**
public static int convertToInt32(PixelFormat dest_fmt, PixelFormat src_fmt, final int src_pixel) {
final byte r, g, b, a;
switch(src_fmt) {
@@ -258,7 +257,7 @@ public class PixelFormatUtil {
throw new InternalError("Unhandled format "+src_fmt);
}
return convertToInt32(dest_fmt, r, g, b, a);
- } */
+ }
public static PixelRectangle convert32(final PixelRectangle src,
final PixelFormat destFmt, int ddestStride, final boolean isGLOriented,
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
index 1e83232..0b03395 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
@@ -36,22 +36,23 @@ import javax.media.nativewindow.SurfaceUpdatedListener;
public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
private final Object surfaceUpdatedListenersLock = new Object();
private final ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>();
+ private volatile boolean isEmpty = true;
//
// Management Utils
//
- public int size() { return surfaceUpdatedListeners.size(); }
- public SurfaceUpdatedListener get(int i) { return surfaceUpdatedListeners.get(i); }
+ public final int size() { return surfaceUpdatedListeners.size(); }
+ public final SurfaceUpdatedListener get(int i) { return surfaceUpdatedListeners.get(i); }
//
// Implementation of NativeSurface SurfaceUpdatedListener methods
//
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
addSurfaceUpdatedListener(-1, l);
}
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l)
+ public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l)
throws IndexOutOfBoundsException
{
if(l == null) {
@@ -62,23 +63,29 @@ public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
index = surfaceUpdatedListeners.size();
}
surfaceUpdatedListeners.add(index, l);
+ isEmpty = false;
}
}
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ public final boolean removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
if (l == null) {
- return;
+ return false;
}
synchronized(surfaceUpdatedListenersLock) {
- surfaceUpdatedListeners.remove(l);
+ final boolean res = surfaceUpdatedListeners.remove(l);
+ isEmpty = 0 == surfaceUpdatedListeners.size();
+ return res;
}
}
@Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ if( isEmpty ) {
+ return;
+ }
synchronized(surfaceUpdatedListenersLock) {
for(int i = 0; i < surfaceUpdatedListeners.size(); i++ ) {
- SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i);
+ final SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i);
l.surfaceUpdated(updater, ns, when);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
index 069cffe..7389360 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
@@ -50,6 +50,8 @@ import javax.media.nativewindow.util.PixelFormat;
import javax.media.nativewindow.util.PixelFormatUtil;
import javax.swing.MenuSelectionManager;
+import jogamp.nativewindow.jawt.JAWTUtil;
+
public class AWTMisc {
public static JFrame getJFrame(Component c) {
@@ -174,9 +176,20 @@ public class AWTMisc {
static final HashMap<Integer, Cursor> cursorMap = new HashMap<Integer, Cursor>();
static final Cursor nulCursor;
static {
- final Toolkit toolkit = Toolkit.getDefaultToolkit();
- final BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
- nulCursor = toolkit.createCustomCursor(img, new Point(0,0), "nullCursor");
+ Cursor _nulCursor = null;
+ if( !JAWTUtil.isHeadlessMode() ) {
+ try {
+ final Toolkit toolkit = Toolkit.getDefaultToolkit();
+ final BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
+ _nulCursor = toolkit.createCustomCursor(img, new Point(0,0), "nullCursor");
+ } catch (Exception he) {
+ if( JAWTUtil.DEBUG ) {
+ System.err.println("Catched exception: "+he.getMessage());
+ he.printStackTrace();
+ }
+ }
+ }
+ nulCursor = _nulCursor;
}
public static synchronized Cursor getNullCursor() { return nulCursor; }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
index 5a1d915..d4edf2b 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
@@ -296,60 +296,71 @@ public class JAWTUtil {
System.err.println("JAWTUtil initialization (JAWT/JNI/...");
// Thread.dumpStack();
}
- JAWTJNILibLoader.initSingleton();
- if(!JAWTJNILibLoader.loadNativeWindow("awt")) {
- throw new NativeWindowException("NativeWindow AWT native library load error.");
- }
headlessMode = GraphicsEnvironment.isHeadless();
- boolean ok = false;
- Class<?> jC = null;
- Method m = null;
- if (!headlessMode) {
+
+ if( headlessMode ) {
+ // Headless case
+ jawtLockObject = null;
+ isQueueFlusherThread = null;
+ j2dExist = false;
+ sunToolkitAWTLockMethod = null;
+ sunToolkitAWTUnlockMethod = null;
+ hasSunToolkitAWTLock = false;
+ // hasSunToolkitAWTLock = false;
+ } else {
+ // Non-headless case
+ JAWTJNILibLoader.initSingleton(); // load libjawt.so
+ if(!JAWTJNILibLoader.loadNativeWindow("awt")) { // load libnativewindow_awt.so
+ throw new NativeWindowException("NativeWindow AWT native library load error.");
+ }
jawtLockObject = getJAWT(false); // don't care for offscreen layer here
+
+ boolean j2dExistTmp = false;
+ Class<?> java2DClass = null;
+ Method isQueueFlusherThreadTmp = null;
try {
- jC = Class.forName("jogamp.opengl.awt.Java2D");
- m = jC.getMethod("isQueueFlusherThread", (Class[])null);
- ok = true;
+ java2DClass = Class.forName("jogamp.opengl.awt.Java2D");
+ isQueueFlusherThreadTmp = java2DClass.getMethod("isQueueFlusherThread", (Class[])null);
+ j2dExistTmp = true;
} catch (Exception e) {
}
- } else {
- jawtLockObject = null; // headless !
- }
- isQueueFlusherThread = m;
- j2dExist = ok;
+ isQueueFlusherThread = isQueueFlusherThreadTmp;
+ j2dExist = j2dExistTmp;
- PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- PrivilegedDataBlob1 d = new PrivilegedDataBlob1();
+ PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ PrivilegedDataBlob1 d = new PrivilegedDataBlob1();
+ try {
+ final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit");
+ d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{});
+ d.sunToolkitAWTLockMethod.setAccessible(true);
+ d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{});
+ d.sunToolkitAWTUnlockMethod.setAccessible(true);
+ d.ok=true;
+ } catch (Exception e) {
+ // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
+ }
+ return d;
+ }
+ });
+ sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
+ sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
+
+ boolean _hasSunToolkitAWTLock = false;
+ if ( pdb1.ok ) {
try {
- final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit");
- d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{});
- d.sunToolkitAWTLockMethod.setAccessible(true);
- d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{});
- d.sunToolkitAWTUnlockMethod.setAccessible(true);
- d.ok=true;
+ sunToolkitAWTLockMethod.invoke(null, (Object[])null);
+ sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
+ _hasSunToolkitAWTLock = true;
} catch (Exception e) {
- // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
}
- return d;
- }
- });
- sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
- sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
-
- boolean _hasSunToolkitAWTLock = false;
- if ( pdb1.ok ) {
- try {
- sunToolkitAWTLockMethod.invoke(null, (Object[])null);
- sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
- _hasSunToolkitAWTLock = true;
- } catch (Exception e) {
}
+ hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
+ // hasSunToolkitAWTLock = false;
}
- hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
- // hasSunToolkitAWTLock = false;
+
jawtLock = LockFactory.createRecursiveLock();
jawtToolkitLock = new ToolkitLock() {
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 1ed6284..f0cc689 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -621,9 +621,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
printActive = false;
return; // not yet available ..
}
- if( !isShowing() ) {
+ if( !isVisible() ) {
if(DEBUG) {
- System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable valid, canvas not showing");
+ System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, canvas not visible");
}
printActive = false;
return; // not yet available ..
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index ca8ab67..4b74092 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -683,21 +683,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- window.removeSurfaceUpdatedListener(l);
- }
-
- @Override
- public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- window.addSurfaceUpdatedListener(l);
- }
-
- @Override
- public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- window.addSurfaceUpdatedListener(index, l);
- }
-
- @Override
public void sendWindowEvent(int eventType) {
window.sendWindowEvent(eventType);
}
@@ -851,6 +836,26 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
+ public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ window.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ window.addSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ window.addSurfaceUpdatedListener(index, l);
+ }
+
+ @Override
+ public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ window.surfaceUpdated(updater, ns, when);
+ }
+
+ @Override
public final long getWindowHandle() {
return window.getWindowHandle();
@@ -877,11 +882,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
return window.getScreenIndex();
}
- @Override
- public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- window.surfaceUpdated(updater, ns, when);
- }
-
/**
* A most simple JOGL AWT test entry
*/
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
index 43e56c8..6f4be75 100644
--- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -146,9 +146,6 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
newtChild.setSize(clientArea.width, clientArea.height);
postSetSize = false;
}
- if( SWTAccessor.isOSX ) {
- newtChild.setPosition(parent.getLocation().x,parent.getLocation().y);
- }
newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
}
}
@@ -166,7 +163,18 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
addListener (SWT.Paint, listener);
addListener (SWT.Dispose, listener);
}
-
+ @Override
+ public void setBounds(int x, int y, int w, int h) {
+ // propagate the setBounds method coming from parent elements to this element
+ // and force newtChild to update its position in OSX
+ super.setBounds(x,y,w,h);
+ if(SWTAccessor.isOSX) {
+ newtChild.setPosition(x, y);
+ clientArea.width = w;
+ clientArea.height = h;
+ updateSizeCheck();
+ }
+ }
/** assumes nativeWindow == null ! */
protected final boolean validateNative() {
updateSizeCheck();
@@ -199,6 +207,10 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
nativeWindow = new SWTNativeWindow(config, nativeWindowHandle);
reparentWindow( true );
+ if(SWTAccessor.isOSX) {
+ // initial positioning for OSX, called when the window is created
+ newtChild.setPosition(getLocation().x, getLocation().y);
+ }
}
return null != nativeWindow;
@@ -256,8 +268,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
super.dispose();
}
- private Rectangle getSWTCanvasPosition() {
- return super.getBounds();
+ private Point getParentLocationOnScreen() {
+ org.eclipse.swt.graphics.Point parentLoc = getParent().toDisplay(0,0);
+ return new Point(parentLoc.x,parentLoc.y);
}
/** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */
public NativeWindow getNativeWindow() { return nativeWindow; }
@@ -506,10 +519,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
public Point getLocationOnScreen(Point point) {
final Point los; // client window location on screen
if( SWTAccessor.isOSX ) {
- los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0);
- // top-level position -> client window position: OSX needs to add SWT parent position incl. insets
- final Rectangle swtCanvasPosition = getSWTCanvasPosition();
- los.translate(swtCanvasPosition.x + insets.getLeftWidth(), swtCanvasPosition.y + insets.getTopHeight());
+ // let getLOS provide the point where the child window may be placed
+ // from, as taken from SWT Control.toDisplay();
+ los = getParentLocationOnScreen();
} else if (SWTAccessor.isX11) {
final AbstractGraphicsScreen s = config.getScreen();
los = X11Lib.GetRelativeLocation(s.getDevice().getHandle(), s.getIndex(), nativeWindowHandle, 0 /*root win*/, 0, 0);
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index b485a47..952e611 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -76,8 +76,7 @@ public abstract class DisplayImpl extends Display {
});
final ClassLoader cl = DisplayImpl.class.getClassLoader();
- pngUtilAvail = ReflectionUtil.isClassAvailable("jogamp.opengl.util.pngj.PngReader", cl) &&
- ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl);
+ pngUtilAvail = ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl);
}
public static final boolean isPNGUtilAvailable() { return pngUtilAvail; }
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 1e2291c..9593d4f 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -811,6 +811,26 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
@Override
+ public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ }
+
+ @Override
+ public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+ }
+
+ @Override
public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
return config.getNativeGraphicsConfiguration();
}
@@ -2087,7 +2107,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle));
}
- if ( !isFullscreen() && ( getX() != x || getY() != y ) ) {
+ // Let the window be positioned if !fullscreen and position changed or being a child window.
+ if ( !isFullscreen() && ( getX() != x || getY() != y || null != getParent()) ) {
if(isNativeValid()) {
// this.x/this.y will be set by sizeChanged, triggered by windowing event system
reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureFlags(0, isVisible()));
@@ -2507,29 +2528,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
//
- // SurfaceUpdatedListener Support
- //
- @Override
- public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
- }
-
- @Override
- public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
- }
-
- @Override
- public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
- }
-
- @Override
- public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
- }
-
- //
// MouseListener/Event Support
//
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index 130b2e3..25ea47c 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -1133,13 +1133,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0
(JNIEnv *env, jobject unused, jlong window)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSWindow* mWin = (NSWindow*) ((intptr_t) window);
+ NSWindow* pWin = [mWin parentWindow];
- DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
- [win orderFrontRegardless];
+ if( NULL == pWin ) {
+ [mWin orderFrontRegardless];
+ } else {
+ [mWin orderWindow: NSWindowAbove relativeTo: [pWin windowNumber]];
+ }
- DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin);
[pool release];
}
@@ -1155,14 +1160,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) window);
NSWindow* pWin = [mWin parentWindow];
- BOOL pWinVisible = NULL != pWin ? [pWin isVisible] : 0;
- DBG_PRINT( "orderOut0 - window: (parent %p visible %d) %p visible %d (START)\n", pWin, pWinVisible, mWin, [mWin isVisible]);
+ DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
- if( NULL == pWin || !pWinVisible ) {
+ if( NULL == pWin ) {
[mWin orderOut: mWin];
} else {
- [mWin orderBack: mWin];
+ [mWin orderWindow: NSWindowOut relativeTo: [pWin windowNumber]];
}
DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
index ec8fa10..1de0951 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,7 +20,7 @@
* 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.
@@ -57,7 +57,7 @@ import android.util.Log;
public class MovieCubeActivity0 extends NewtBaseActivity {
static String TAG = "MovieCubeActivity0";
-
+
MouseAdapter showKeyboardMouseListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
@@ -66,18 +66,18 @@ public class MovieCubeActivity0 extends NewtBaseActivity {
}
}
};
-
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- String[] streamLocs = new String[] {
+
+ String[] streamLocs = new String[] {
System.getProperty("jnlp.media0_url2"),
System.getProperty("jnlp.media0_url1"),
- System.getProperty("jnlp.media0_url0") };
+ System.getProperty("jnlp.media0_url0") };
final URI streamLoc = getURI(streamLocs, 0, false);
if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); }
-
+
// also initializes JOGL
final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2());
capsMain.setBackgroundOpaque(false);
@@ -86,53 +86,56 @@ public class MovieCubeActivity0 extends NewtBaseActivity {
final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null);
final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0);
scrn.addReference();
-
+
try {
final Animator anim = new Animator();
-
- // Main
+
+ // Main
final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
glWindowMain.setFullscreen(true);
setContentView(getWindow(), glWindowMain);
anim.add(glWindowMain);
glWindowMain.setVisible(true);
glWindowMain.addMouseListener(showKeyboardMouseListener);
-
- final MovieCube demoMain = new MovieCube(-2.3f, 0f, 0f);
+
+ final MovieCube demoMain = new MovieCube(MovieCube.zoom_def, 0f, 0f);
final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer();
mPlayer.addEventListener(new GLMediaEventListener() {
@Override
public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) {
}
-
+
@Override
public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) {
System.err.println("MovieCubeActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
System.err.println("MovieCubeActivity0 State: "+mp);
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
glWindowMain.addGLEventListener(demoMain);
- anim.setUpdateFPSFrames(60, System.err);
+ anim.setUpdateFPSFrames(60, null);
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
anim.resetFPSCounter();
}
if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
final StreamException se = mPlayer.getStreamException();
if( null != se ) {
- se.printStackTrace();
+ se.printStackTrace();
}
getActivity().finish();
}
- }
- });
+ }
+ });
demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0);
} catch (IOException e) {
e.printStackTrace();
}
-
+
scrn.removeReference();
Log.d(TAG, "onCreate - X");
}
-
+
static URI getURI(String path[], int off, boolean checkAvail) {
URI uri = null;
for(int i=off; null==uri && i<path.length; i++) {
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
new file mode 100644
index 0000000..1282d5d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2014 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.graph;
+
+import java.io.IOException;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.curve.opengl.TextRenderer;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+public abstract class TextRendererGLELBase implements GLEventListener {
+ protected final float[] textPosition = new float[] {0,0,0};
+ protected final int[] texSize = new int[] { 0 };
+ protected final float[] staticRGBAColor = new float[] { 1f, 1f, 1f, 1f };
+
+ protected final Font font;
+ protected final int usrRenderModes;
+
+ /**
+ * In exclusive mode, impl. uses a pixelScale of 1f and orthogonal PMV on window dimensions
+ * and renderString uses 'height' for '1'.
+ * <p>
+ * In non-exclusive mode, i.e. shared w/ custom PMV (within another 3d scene),
+ * it uses the custom pixelScale and renderString uses normalized 'height', i.e. '1'.
+ * </p>
+ */
+ protected boolean exclusivePMVMatrix = true;
+ protected PMVMatrix usrPMVMatrix = null;
+ protected RenderState rs = null;
+ protected TextRenderer renderer = null;
+
+ /** font size in pixels, default is 24 */
+ protected int fontSize = 24;
+ /** scale pixel, default is 1f */
+ protected float pixelScale = 1.0f;
+ protected int texSizeScale = 2;
+
+ boolean flipVerticalInGLOrientation = false;
+
+ public TextRendererGLELBase(final int renderModes) {
+ usrRenderModes = renderModes;
+ {
+ Font _font = null;
+ try {
+ _font = FontFactory.get(FontFactory.UBUNTU).getDefault();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ this.font = _font;
+ }
+ }
+
+ public void setFlipVerticalInGLOrientation(boolean v) { flipVerticalInGLOrientation=v; }
+ public final TextRenderer getRenderer() { return renderer; }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ if( null != font ) {
+ exclusivePMVMatrix = null == usrPMVMatrix;
+ this.rs = RenderState.createRenderState(new ShaderState(), SVertex.factory(), usrPMVMatrix);
+ this.renderer = TextRenderer.create(rs, usrRenderModes);
+ if( 0 == usrRenderModes ) {
+ texSizeScale = 0;
+ }
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ renderer.init(gl);
+ renderer.setAlpha(gl, staticRGBAColor[3]);
+ renderer.setColorStatic(gl, staticRGBAColor[0], staticRGBAColor[1], staticRGBAColor[2]);
+ final ShaderState st = rs.getShaderState();
+ st.useProgram(gl, false);
+ } else {
+ this.rs = null;
+ this.renderer = null;
+ }
+ }
+
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final ShaderState st = rs.getShaderState();
+ st.useProgram(gl, true);
+ if( exclusivePMVMatrix ) {
+ // renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 1000.0f);
+ renderer.reshapeOrtho(gl, width, height, 0.1f, 1000.0f);
+ pixelScale = 1.0f;
+ } else {
+ renderer.reshapeNotify(gl, width, height);
+ }
+ st.useProgram(gl, false);
+ texSize[0] = width * texSizeScale;
+ }
+ }
+
+ @Override
+ public abstract void display(GLAutoDrawable drawable);
+
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ renderer.destroy(gl);
+ }
+ }
+
+ int lastRow = -1;
+
+ public void renderString(GLAutoDrawable drawable, String text, int column, float tx, float ty, float tz) {
+ final int row = lastRow + 1;
+ renderString(drawable, text, column, row, tx, ty, tz);
+ lastRow = row;
+ }
+
+ public void renderString(GLAutoDrawable drawable, String text, int column, int row, float tx, float ty, float tz) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ float dx = tx;
+ float dy;
+
+ if( !exclusivePMVMatrix ) {
+ dy = 1f-ty;
+ } else {
+ final int height = drawable.getHeight();
+ dy = height-ty;
+ }
+
+ final AABBox textBox = font.getStringBounds(text, fontSize);
+ dx += pixelScale * font.getAdvanceWidth('X', fontSize) * column;
+ dy -= pixelScale * (int)textBox.getHeight() * ( row + 1 );
+
+ final ShaderState st = rs.getShaderState();
+ final PMVMatrix pmvMatrix = rs.pmvMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ if( !exclusivePMVMatrix ) {
+ pmvMatrix.glPushMatrix();
+ } else {
+ pmvMatrix.glLoadIdentity();
+ }
+
+ st.useProgram(gl, true);
+ gl.glEnable(GL2ES2.GL_BLEND);
+ pmvMatrix.glTranslatef(dx, dy, tz);
+ if( flipVerticalInGLOrientation && drawable.isGLOriented() ) {
+ pmvMatrix.glScalef(pixelScale, -1f*pixelScale, 1f);
+ } else if( 1f != pixelScale ) {
+ pmvMatrix.glScalef(pixelScale, pixelScale, 1f);
+ }
+ renderer.updateMatrix(gl);
+ renderer.drawString3D(gl, font, text, textPosition, fontSize, texSize);
+ st.useProgram(gl, false);
+ gl.glDisable(GL2ES2.GL_BLEND);
+
+ if( !exclusivePMVMatrix ) {
+ pmvMatrix.glPopMatrix();
+ }
+ lastRow = -1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
new file mode 100644
index 0000000..43f8b89
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2014 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 java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+ at FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class GLReadBuffer00Base extends UITestCase {
+
+ public static class TextRendererGLEL extends TextRendererGLELBase {
+ public int frameNo = 0;
+ public int userCounter = 0;
+
+ public TextRendererGLEL() {
+ // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+ super(Region.VBAA_RENDERING_BIT);
+ texSizeScale = 2;
+
+ fontSize = 24;
+
+ staticRGBAColor[0] = 1.0f;
+ staticRGBAColor[1] = 1.0f;
+ staticRGBAColor[2] = 1.0f;
+ staticRGBAColor[3] = 0.99f;
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ final String text = String.format("Frame %04d (%03d): %04dx%04d", frameNo, userCounter, drawable.getWidth(), drawable.getHeight());
+ System.err.println("TextRendererGLEL.display: "+text);
+ if( null != renderer ) {
+ renderString(drawable, text, 0 /* col */, 0 /* row */, 0, 0, -1);
+ } else {
+ System.err.println(text);
+ }
+ frameNo++;
+ }
+ }
+
+ @BeforeClass
+ public static void initClass() throws IOException {
+ GLProfile.initSingleton();
+ }
+
+ protected abstract void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip);
+
+ @Test
+ public void test00_MSAA0_DefFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */);
+ }
+
+ @Test
+ public void test01_MSAA0_UsrFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */);
+ }
+
+ @Test
+ public void test10_MSAA8_DefFlip() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ caps.setNumSamples(8);
+ caps.setSampleBuffers(true);
+ test(caps, false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */);
+ }
+
+ @Test
+ public void test11_MSAA8_UsrFlip() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ caps.setNumSamples(8);
+ caps.setSampleBuffers(true);
+ test(caps, false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */);
+ }
+
+ static long duration = 500; // ms
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java
new file mode 100644
index 0000000..0f77aff
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java
@@ -0,0 +1,252 @@
+/**
+ * Copyright 2014 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.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+ at FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLCanvasAWT extends GLReadBuffer00Base {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ @Override
+ public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+ if( skipGLOrientationVerticalFlip || useSwingDoubleBuffer ) {
+ return; // NOP
+ }
+ final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
+ final Frame frame = new Frame();
+ final Dimension d = new Dimension(320, 240);
+ final GLCanvas glad = createGLCanvas(caps, d);
+ final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+ final SnapshotGLELAWT snapshotGLEL = doSnapshot ? new SnapshotGLELAWT(textRendererGLEL, awtGLReadBufferUtil) : null;
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLocation(64, 64);
+ frame.setLayout(new BorderLayout());
+ // final JPanel panel = new JPanel();
+ // panel.setLayout(new BorderLayout());
+ // panel.setDoubleBuffered(useSwingDoubleBuffer);
+ // frame.getContentPane().add(panel);
+
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ glad.addGLEventListener(gears);
+ glad.addGLEventListener(textRendererGLEL);
+ if( doSnapshot ) {
+ glad.addGLEventListener(snapshotGLEL);
+ }
+ // panel.add(glad);
+ frame.add(glad, BorderLayout.CENTER);
+ frame.pack();
+ frame.setVisible(true);
+ } } );
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glad.display(); // trigger initialization to get chosen-caps!
+ final Dimension size0 = frame.getSize();
+ final Dimension size1 = new Dimension(size0.width+100, size0.height+100);
+ final Dimension size2 = new Dimension(size0.width-100, size0.height-100);
+ try {
+ for(int i=0; i<3; i++) {
+ final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+ System.err.println(str);
+ if( keyFrame ) {
+ waitForKey(str);
+ }
+ textRendererGLEL.userCounter = i + 1;
+ glad.display();
+ }
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size1);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size2);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size0);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+
+ if( doSnapshot ) {
+ glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+ }
+ final Animator anim = new Animator(glad);
+ anim.start();
+ try { Thread.sleep(2*duration); } catch (InterruptedException e) { }
+ anim.stop();
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ } } );
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ private GLCanvas createGLCanvas(final GLCapabilitiesImmutable caps, final Dimension size) {
+ final GLCanvas canvas = new GLCanvas(caps);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ canvas.setMinimumSize(size);
+ return canvas;
+ }
+
+ private class SnapshotGLELAWT implements GLEventListener {
+ final TextRendererGLEL textRendererGLEL;
+ final AWTGLReadBufferUtil glReadBufferUtil;
+ boolean defAutoSwapMode;
+ boolean swapBuffersBeforeRead;
+ int i;
+
+ SnapshotGLELAWT(final TextRendererGLEL textRendererGLEL, final AWTGLReadBufferUtil glReadBufferUtil) {
+ this.textRendererGLEL = textRendererGLEL;
+ this.glReadBufferUtil = glReadBufferUtil;
+ this.defAutoSwapMode = true;
+ this.swapBuffersBeforeRead = false;
+ i = 0;
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ defAutoSwapMode = drawable.getAutoSwapBufferMode();
+ swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+ drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+ }
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ drawable.setAutoSwapBufferMode( defAutoSwapMode );
+ }
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ snapshot(i++, drawable.getGL(), TextureIO.PNG, null);
+ }
+ public void snapshot(int sn, GL gl, String fileSuffix, String destPath) {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final String postSNDetail = String.format("awt-usr%03d", textRendererGLEL.userCounter);
+ final String filenameAWT = getSnapshotFilename(sn, postSNDetail,
+ drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+ glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+ if( swapBuffersBeforeRead ) {
+ drawable.swapBuffers();
+ // Just to test whether we use the right buffer,
+ // i.e. back-buffer shall no more be required ..
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ } else {
+ gl.glFinish(); // just make sure rendering finished ..
+ }
+
+ final boolean awtOrientation = drawable.isGLOriented();
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameAWT);
+
+ final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, awtOrientation);
+ final File fout = new File(filenameAWT);
+ try {
+ ImageIO.write(image, "png", fout);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ /**
+ final String filenameJGL = getSnapshotFilename(sn, "jgl",
+ drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+ glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+ glReadBufferUtil.write(new File(filenameJGL));
+ */
+ }
+ };
+
+ static GLCapabilitiesImmutable caps = null;
+ static boolean doSnapshot = true;
+ static boolean keyFrame = false;
+
+ public static void main(String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-keyFrame")) {
+ keyFrame = true;
+ } else if(args[i].equals("-noSnapshot")) {
+ doSnapshot = false;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLCanvasAWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
new file mode 100644
index 0000000..e93356d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
@@ -0,0 +1,254 @@
+/**
+ * Copyright 2014 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.BorderLayout;
+import java.awt.Dimension;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+ at FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ @Override
+ public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+ final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
+ final JFrame frame = new JFrame();
+ final Dimension d = new Dimension(320, 240);
+ final GLJPanel glad = createGLJPanel(skipGLOrientationVerticalFlip, useSwingDoubleBuffer, caps, d);
+ final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+ final SnapshotGLELAWT snapshotGLEL = doSnapshot ? new SnapshotGLELAWT(textRendererGLEL, awtGLReadBufferUtil, skipGLOrientationVerticalFlip) : null;
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLocation(64, 64);
+ final JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.setDoubleBuffered(useSwingDoubleBuffer);
+ frame.getContentPane().add(panel);
+
+ final GearsES2 gears = new GearsES2(1);
+ gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ gears.setVerbose(false);
+ glad.addGLEventListener(gears);
+ textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glad.addGLEventListener(textRendererGLEL);
+ if( doSnapshot ) {
+ glad.addGLEventListener(snapshotGLEL);
+ }
+ panel.add(glad);
+ frame.pack();
+ frame.setVisible(true);
+ } } );
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glad.display(); // trigger initialization to get chosen-caps!
+ final Dimension size0 = frame.getSize();
+ final Dimension size1 = new Dimension(size0.width+100, size0.height+100);
+ final Dimension size2 = new Dimension(size0.width-100, size0.height-100);
+ try {
+ for(int i=0; i<3; i++) {
+ final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+ System.err.println(str);
+ if( keyFrame ) {
+ waitForKey(str);
+ }
+ textRendererGLEL.userCounter = i + 1;
+ glad.display();
+ }
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size1);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size2);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size0);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+
+ if( doSnapshot ) {
+ glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+ }
+ final Animator anim = new Animator(glad);
+ anim.start();
+ try { Thread.sleep(2*duration); } catch (InterruptedException e) { }
+ anim.stop();
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ } } );
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ private GLJPanel createGLJPanel(final boolean skipGLOrientationVerticalFlip, final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final Dimension size) {
+ final GLJPanel canvas = new GLJPanel(caps);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ canvas.setMinimumSize(size);
+ canvas.setDoubleBuffered(useSwingDoubleBuffer);
+ canvas.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip);
+ return canvas;
+ }
+
+ private class SnapshotGLELAWT implements GLEventListener {
+ final TextRendererGLEL textRendererGLEL;
+ final AWTGLReadBufferUtil glReadBufferUtil;
+ final boolean skipGLOrientationVerticalFlip;
+ boolean defAutoSwapMode;
+ boolean swapBuffersBeforeRead;
+ int i;
+
+ SnapshotGLELAWT(final TextRendererGLEL textRendererGLEL, final AWTGLReadBufferUtil glReadBufferUtil, final boolean skipGLOrientationVerticalFlip) {
+ this.textRendererGLEL = textRendererGLEL;
+ this.glReadBufferUtil = glReadBufferUtil;
+ this.skipGLOrientationVerticalFlip = skipGLOrientationVerticalFlip;
+ this.defAutoSwapMode = true;
+ this.swapBuffersBeforeRead = false;
+ i = 0;
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ defAutoSwapMode = drawable.getAutoSwapBufferMode();
+ swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+ drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+ }
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ drawable.setAutoSwapBufferMode( defAutoSwapMode );
+ }
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ snapshot(i++, drawable.getGL(), TextureIO.PNG, null);
+ }
+ public void snapshot(int sn, GL gl, String fileSuffix, String destPath) {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final String postSNDetail = String.format("awt-usr%03d", textRendererGLEL.userCounter);
+ final String filenameAWT = getSnapshotFilename(sn, postSNDetail,
+ drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+ glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+ if( swapBuffersBeforeRead ) {
+ drawable.swapBuffers();
+ // Just to test whether we use the right buffer,
+ // i.e. back-buffer shall no more be required ..
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ } else {
+ gl.glFinish(); // just make sure rendering finished ..
+ }
+
+ final boolean awtOrientation = !( drawable.isGLOriented() && skipGLOrientationVerticalFlip );
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameAWT);
+
+ final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, awtOrientation);
+ final File fout = new File(filenameAWT);
+ try {
+ ImageIO.write(image, "png", fout);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ /**
+ final String filenameJGL = getSnapshotFilename(sn, "jgl",
+ drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+ glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+ glReadBufferUtil.write(new File(filenameJGL));
+ */
+ }
+ };
+
+ static GLCapabilitiesImmutable caps = null;
+ static boolean doSnapshot = true;
+ static boolean keyFrame = false;
+
+ public static void main(String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-keyFrame")) {
+ keyFrame = true;
+ } else if(args[i].equals("-noSnapshot")) {
+ doSnapshot = false;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLJPanelAWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java
new file mode 100644
index 0000000..a170d9b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2014 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.File;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+ at FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ @Override
+ public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+ if( skipGLOrientationVerticalFlip || useSwingDoubleBuffer ) {
+ return; // NOP
+ }
+ final GLReadBufferUtil glReadBufferUtil = new GLReadBufferUtil(false, false);
+ final GLWindow glad= GLWindow.create(caps);
+ final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+ final SnapshotGLEL snapshotGLEL = doSnapshot ? new SnapshotGLEL(textRendererGLEL, glReadBufferUtil) : null;
+ try {
+ glad.setPosition(64, 64);
+ glad.setSize(320, 240);
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ glad.addGLEventListener(gears);
+ textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glad.addGLEventListener(textRendererGLEL);
+ if( doSnapshot ) {
+ glad.addGLEventListener(snapshotGLEL);
+ }
+ glad.setVisible(true);
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ final DimensionImmutable size0 = new Dimension(glad.getWidth(), glad.getHeight());
+ final DimensionImmutable size1 = new Dimension(size0.getWidth()+100, size0.getHeight()+100);
+ final DimensionImmutable size2 = new Dimension(size0.getWidth()-100, size0.getHeight()-100);
+ try {
+ for(int i=0; i<3; i++) {
+ final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+ System.err.println(str);
+ if( keyFrame ) {
+ waitForKey(str);
+ }
+ textRendererGLEL.userCounter = i + 1;
+ glad.display();
+ }
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ glad.setSize(size1.getWidth(), size1.getHeight());
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ glad.setSize(size2.getWidth(), size2.getHeight());
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+ glad.setSize(size0.getWidth(), size0.getHeight());
+ try { Thread.sleep(duration); } catch (InterruptedException e) { }
+
+ if( doSnapshot ) {
+ glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+ }
+ final Animator anim = new Animator(glad);
+ anim.start();
+ try { Thread.sleep(2*duration); } catch (InterruptedException e) { }
+ anim.stop();
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ glad.destroy();
+ }
+
+ private class SnapshotGLEL implements GLEventListener {
+ final TextRendererGLEL textRendererGLEL;
+ final GLReadBufferUtil glReadBufferUtil;
+ boolean defAutoSwapMode;
+ boolean swapBuffersBeforeRead;
+ int i;
+
+ SnapshotGLEL(final TextRendererGLEL textRendererGLEL, final GLReadBufferUtil glReadBufferUtil) {
+ this.textRendererGLEL = textRendererGLEL;
+ this.glReadBufferUtil = glReadBufferUtil;
+ this.defAutoSwapMode = true;
+ this.swapBuffersBeforeRead = false;
+ i = 0;
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ defAutoSwapMode = drawable.getAutoSwapBufferMode();
+ swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+ drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+ }
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ drawable.setAutoSwapBufferMode( defAutoSwapMode );
+ }
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ snapshot(i++, drawable, TextureIO.PNG, null);
+ }
+ public void snapshot(int sn, GLAutoDrawable drawable, String fileSuffix, String destPath) {
+ final GL gl = drawable.getGL();
+ final String postSNDetail = String.format("jgl-usr%03d", textRendererGLEL.userCounter);
+ final String filenameJGL = getSnapshotFilename(sn, postSNDetail,
+ drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+ glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+ if( swapBuffersBeforeRead ) {
+ drawable.swapBuffers();
+ // Just to test whether we use the right buffer,
+ // i.e. back-buffer shall no more be required ..
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ } else {
+ gl.glFinish(); // just make sure rendering finished ..
+ }
+ final boolean mustFlipVertically = !drawable.isGLOriented();
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: v-flip "+mustFlipVertically+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameJGL);
+
+ if(glReadBufferUtil.readPixels(gl, mustFlipVertically)) {
+ glReadBufferUtil.write(new File(filenameJGL));
+ }
+ }
+ };
+
+ static GLCapabilitiesImmutable caps = null;
+ static boolean doSnapshot = true;
+ static boolean keyFrame = false;
+
+ public static void main(String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-keyFrame")) {
+ keyFrame = true;
+ } else if(args[i].equals("-noSnapshot")) {
+ doSnapshot = false;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLWindowNEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
index ac82c74..23778ec 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
@@ -36,6 +36,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLBufferStorage;
import javax.media.opengl.GLCapabilities;
@@ -57,44 +58,65 @@ public class TestMapBufferRead01NEWT extends UITestCase {
static final boolean DEBUG = false;
@Test
- public void testWriteRead01a() throws InterruptedException {
+ public void testWriteRead01aMap() throws InterruptedException {
if(!GLProfile.isAvailable(GLProfile.GL2GL3)) {
System.err.println("Test requires GL2/GL3 profile.");
return;
}
ByteBuffer verticiesBB = ByteBuffer.allocate(4*9);
verticiesBB.order(ByteOrder.nativeOrder());
- testWriteRead01(verticiesBB);
+ testWriteRead01(verticiesBB, false /* useRange */);
}
@Test
- public void testWriteRead01b() throws InterruptedException {
+ public void testWriteRead01bMap() throws InterruptedException {
if(!GLProfile.isAvailable(GLProfile.GL2GL3)) {
System.err.println("Test requires GL2/GL3 profile.");
return;
}
ByteBuffer verticiesBB = Buffers.newDirectByteBuffer(4*9);
- testWriteRead01(verticiesBB);
+ testWriteRead01(verticiesBB, false /* useRange */);
}
- private void testWriteRead01(ByteBuffer verticiesBB) throws InterruptedException {
+ @Test
+ public void testWriteRead02aMapRange() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL3) && !!GLProfile.isAvailable(GLProfile.GLES3)) {
+ System.err.println("Test requires GL3 or GLES3 profile.");
+ return;
+ }
+ ByteBuffer verticiesBB = ByteBuffer.allocate(4*9);
+ verticiesBB.order(ByteOrder.nativeOrder());
+ testWriteRead01(verticiesBB, true/* useRange */);
+ }
+ @Test
+ public void testWriteRead02bMapRange() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL3) && !!GLProfile.isAvailable(GLProfile.GLES3)) {
+ System.err.println("Test requires GL3 or GLES3 profile.");
+ return;
+ }
+ ByteBuffer verticiesBB = Buffers.newDirectByteBuffer(4*9);
+ testWriteRead01(verticiesBB, true /* useRange */);
+ }
+
+ private void testWriteRead01(ByteBuffer verticiesBB, boolean useRange) throws InterruptedException {
+ final GLProfile glp = GLProfile.getMaxProgrammable(true);
final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOffscreenWindow(
- new GLCapabilities(GLProfile.getGL2GL3()), 800, 600, true);
+ new GLCapabilities(glp), 800, 600, true);
try {
final GL gl = winctx.context.getGL();
int[] vertexBuffer = new int[1];
- verticiesBB.putFloat(0);
- verticiesBB.putFloat(0.5f);
- verticiesBB.putFloat(0);
+ verticiesBB.putFloat(-0.3f);
+ verticiesBB.putFloat(-0.2f);
+ verticiesBB.putFloat(-0.1f);
- verticiesBB.putFloat(0.5f);
- verticiesBB.putFloat(-0.5f);
- verticiesBB.putFloat(0);
+ verticiesBB.putFloat(0.1f);
+ verticiesBB.putFloat(0.2f);
+ verticiesBB.putFloat(0.3f);
- verticiesBB.putFloat(-0.5f);
- verticiesBB.putFloat(-0.5f);
- verticiesBB.putFloat(0);
+ verticiesBB.putFloat(0.4f);
+ verticiesBB.putFloat(0.5f);
+ verticiesBB.putFloat(0.6f);
verticiesBB.rewind();
if(DEBUG) {
for(int i=0; i < verticiesBB.capacity(); i+=4) {
@@ -106,28 +128,42 @@ public class TestMapBufferRead01NEWT extends UITestCase {
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer[0]);
- // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_READ);
- gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL2ES3.GL_STATIC_READ);
+ // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW);
final int bufferName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER);
final GLBufferStorage bufferStorage = gl.getBufferStorage(bufferName);
System.err.println("gpu-01 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage);
Assert.assertEquals("Buffer storage's bytes-buffer not null before map", null, bufferStorage.getMappedBuffer());
- final ByteBuffer bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY);
- Assert.assertNotNull(bb);
- System.err.println("gpu-02 mapped GL_ARRAY_BUFFER -> "+bb);
+ final int floatOffset, byteOffset, mapByteLength;
+ final ByteBuffer bb;
+ if( useRange ) {
+ floatOffset = 3;
+ byteOffset = Buffers.SIZEOF_FLOAT*floatOffset;
+ mapByteLength = verticiesBB.capacity()-byteOffset;
+ bb = gl.glMapBufferRange(GL.GL_ARRAY_BUFFER, byteOffset, mapByteLength, GL.GL_MAP_READ_BIT);
+ } else {
+ floatOffset = 0;
+ byteOffset = 0;
+ mapByteLength = verticiesBB.capacity();
+ bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY);
+ }
+ System.err.println("gpu-02 mapped GL_ARRAY_BUFFER, floatOffset "+floatOffset+", byteOffset "+byteOffset+", mapByteLength "+mapByteLength+" -> "+bb);
System.err.println("gpu-03 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage);
- Assert.assertEquals("Buffer storage size not equals buffer storage size", bufferStorage.getSize(), bb.capacity());
- Assert.assertEquals("Buffer storage's bytes-buffer not equal with mapped bytes-buffer", bufferStorage.getMappedBuffer(), bb);
+ Assert.assertNotNull(bb);
+ Assert.assertEquals("BufferStorage size less byteOffset not equals buffer storage size", bufferStorage.getSize()-byteOffset, bb.capacity());
+ Assert.assertEquals("BufferStorage's bytes-buffer not equal with mapped bytes-buffer", bufferStorage.getMappedBuffer(), bb);
+ Assert.assertEquals("Buffer storage size not equals mapByteLength", mapByteLength, bb.capacity());
if(DEBUG) {
+ System.err.println("floatOffset "+floatOffset+", byteOffset "+byteOffset);
for(int i=0; i < bb.capacity(); i+=4) {
System.err.println("gpu "+i+": "+bb.getFloat(i));
}
}
for(int i=0; i < bb.capacity(); i+=4) {
- Assert.assertEquals(verticiesBB.getFloat(i), bb.getFloat(i), 0.0);
+ Assert.assertEquals(verticiesBB.getFloat(byteOffset+i), bb.getFloat(i), 0.0001f);
}
gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER);
Assert.assertEquals("Buffer storage's bytes-buffer not null after unmap", null, bufferStorage.getMappedBuffer());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
index 616aa52..b02238c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
@@ -66,14 +66,14 @@ public class TextureSequenceCubeES2 implements GLEventListener {
}
private TextureSequence texSeq;
- private ShaderState st;
- private PMVMatrix pmvMatrix;
+ public ShaderState st;
+ public PMVMatrix pmvMatrix;
private GLUniformData pmvMatrixUniform;
// private TextureCoords[] textureCoords = null;
private float nearPlaneNormalized;
// private float zoom0=-5.0f, zoom=zoom0;
// private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f;
- private float zoom=-2.3f;
+ public float zoom=-2.3f;
private float view_rotx = 0.0f, view_roty = 0.0f;
private final float view_rotz = 0.0f;
int[] vboNames = new int[4];
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
new file mode 100644
index 0000000..02f62c4
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
@@ -0,0 +1,211 @@
+/**
+ * Copyright 2014 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.demos.es2.av;
+
+import com.jogamp.opengl.util.av.AudioSink;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+import java.io.File;
+import java.net.URI;
+
+/**
+ * Parallel media player that demonstrate CrossFade of audio volume during playback.
+ * This also demonstrate audio only playback of the GLMediaPlayer.
+ */
+public class CrossFadePlayer
+{
+ static GLMediaPlayer[] player;
+ static volatile boolean stop = false;
+
+ public static void main(String[] args)
+ {
+
+ if(args.length==0) {
+ System.out.println("No files! \n" +
+ "pass as many media files you want\n" +
+ "to the CrossFadePlayer arguments \n" +
+ "and i will try CrossFade-play them all in parallel!");
+ }
+
+ GLMediaEventListener mediaEventListener = new GLMediaEventListener()
+ {
+ @Override
+ public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when)
+ {
+ System.out.println("\n***\nEvent mask changed: " + event_mask);
+ System.out.println("Timestamp: "+ when);
+ System.out.println("State of player: " + mp.getState().toString() +"\n");
+
+ if ((event_mask & GLMediaEventListener.EVENT_CHANGE_INIT) !=0) {
+ System.out.println("Duration: " + mp.getDuration() + "ms");
+ System.out.println("Volume: " + mp.getAudioVolume());
+ System.out.println("player.initGL()...");
+ new Thread() {
+ public void run() {
+ try {
+ mp.initGL(null);
+ if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+ mp.play();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PAUSE) !=0) {
+ System.out.println("player.paused()...");
+ } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PLAY) !=0) {
+ System.out.println("playing...");
+ System.out.println(mp.toString());
+ System.out.println(mp.getAudioSink().toString());
+ } else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ final StreamException se = mp.getStreamException();
+ if( null != se ) {
+ System.err.println("Player State: EOS + Exception");
+ stop = true;
+ } else {
+ System.err.println("Player State: EOS");
+ new Thread() {
+ public void run() {
+ System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f));
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
+ }
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mp.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ new Thread() {
+ public void run() {
+ System.out.println("terminating...");
+ stop = true;
+ }
+ }.start();
+ }
+
+ }
+ };
+
+ // Initialize media players
+ player = new GLMediaPlayer[args.length];
+ int i=0;
+ for( String arg: args ) {
+ player[i] = GLMediaPlayerFactory.createDefault();
+ if(player[i]!=null){
+ System.out.println("Created CrossFade player: "+ i + " " + player[i].getClass().getName());
+ player[i].addEventListener(mediaEventListener);
+ try {
+ final String filename = arg;
+ if(filename.equals("")){
+ System.out.println("No file selected: arg " + i +" = "+ filename);
+ player[i]=null;
+ } else {
+ File file = new File(filename);
+ if(!file.exists()){
+ System.out.println("File do not exist");
+ } else {
+ URI uri = file.toURI();
+ System.out.println("State of player "+ i +": " + player[i].getState().toString());
+ System.out.println("...initializing stream "+ i +"...");
+ player[i].initStream(uri, GLMediaPlayer.STREAM_ID_NONE, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
+
+ }
+ }
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ } else {
+ System.out.println("Failed to create player "+ i +"!");
+ }
+ i++;
+ }
+
+
+ // Main thread CrossFade until playback is done
+ long startTime = com.jogamp.common.os.Platform.currentTimeMillis();
+ double piPlayers = Math.PI*2.0f/args.length;
+ StreamException se = null;
+ while( null == se && stop == false ) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) { }
+
+ // Find out the longest duration...
+ float maxDuration = 1000.0f ;
+ for(GLMediaPlayer p: player) {
+ if(p!=null){
+ if( p.getDuration() > maxDuration) {
+ maxDuration = p.getDuration();
+ }
+ }
+ }
+
+ // tune the volume on players to crossfade!
+ float progress = (com.jogamp.common.os.Platform.currentTimeMillis()-startTime)/maxDuration;
+
+ i = 0;
+ for(GLMediaPlayer p: player){
+ if(p!=null){
+ AudioSink sink = p.getAudioSink();
+ if(sink != null){
+ float volume = (float) (0.5f+(0.5f*(Math.cos(40.0f*progress+(piPlayers*i)))));
+ float playbacktime = com.jogamp.common.os.Platform.currentTimeMillis()-startTime;
+ // System.out.println("player: "+ i +" volume = " + volume +" progress = "+ progress +" time = "+ playbacktime + " / duration = " + maxDuration);
+ sink.setVolume(volume);
+ }
+
+ se = p.getStreamException();
+ if( null != se) {
+ se.printStackTrace();
+ throw new RuntimeException(se);
+ }
+ }
+
+ i++;
+ }
+ }
+
+ for(GLMediaPlayer p: player) {
+ if(p!=null)
+ p.destroy(null);
+ }
+ System.out.println("...main exit...");
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
index c1ccf7c..b148eba 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
@@ -34,6 +34,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
@@ -41,6 +42,8 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.font.Font;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
@@ -49,6 +52,7 @@ import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -63,11 +67,13 @@ import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
* Simple cube movie player w/ aspect ration true projection on a cube.
*/
public class MovieCube implements GLEventListener {
+ public static final float zoom_def = -2.77f;
private static boolean waitForKey = false;
private final float zoom0, rotx, roty;
private TextureSequenceCubeES2 cube=null;
private GLMediaPlayer mPlayer=null;
private int swapInterval = 1;
+ private int swapIntervalSet = -1;
private long lastPerfPos = 0;
private volatile boolean resetGLState = false;
@@ -92,7 +98,7 @@ public class MovieCube implements GLEventListener {
* </p>
*/
public MovieCube() throws IOException, URISyntaxException {
- this(-2.3f, 0f, 0f);
+ this(zoom_def, 0f, 0f);
mPlayer.addEventListener(new GLMediaEventListener() {
@Override
@@ -106,9 +112,12 @@ public class MovieCube implements GLEventListener {
resetGLState();
}
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
- // loop for-ever ..
- mPlayer.seek(0);
- mPlayer.play();
+ new Thread() {
+ public void run() {
+ // loop for-ever ..
+ mPlayer.seek(0);
+ mPlayer.play();
+ } }.start();
}
}
});
@@ -147,6 +156,86 @@ public class MovieCube implements GLEventListener {
resetGLState = true;
}
+ private final class InfoTextRendererGLELBase extends TextRendererGLELBase {
+ static final float z_diff = 0.001f;
+ final float underlineSize;
+
+ InfoTextRendererGLELBase() {
+ // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+ super(Region.VBAA_RENDERING_BIT);
+ texSizeScale = 2;
+
+ fontSize = 1;
+ pixelScale = 1.0f / ( fontSize * 20f );
+
+ // underlineSize: 'underline' amount of pixel below 0/0 (Note: lineGap is negative)
+ final Font.Metrics metrics = font.getMetrics();
+ final float lineGap = metrics.getLineGap(fontSize);
+ final float descent = metrics.getDescent(fontSize);
+ underlineSize = descent - lineGap;
+ // System.err.println("XXX: fLG "+lineGap+", fDesc "+descent+", underlineSize "+underlineSize);
+
+ staticRGBAColor[0] = 0.0f;
+ staticRGBAColor[1] = 0.0f;
+ staticRGBAColor[2] = 0.0f;
+ staticRGBAColor[3] = 1.0f;
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ // non-exclusive mode!
+ this.usrPMVMatrix = cube.pmvMatrix;
+ super.init(drawable);
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ final GLAnimatorControl anim = drawable.getAnimator();
+ final float lfps = null != anim ? anim.getLastFPS() : 0f;
+ final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f;
+
+ // Note: MODELVIEW is from [ -1 .. 1 ]
+
+ // dy: position right above video rectangle (bottom text line)
+ final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight();
+ final float aspect_h = 1f/aspect;
+ final float dy = 1f-aspect_h;
+
+ // yoff1: position right above video rectangle (bottom text line)
+ // less than underlineSize, so 'underline' pixels are above video.
+ final float yoff1 = dy-(pixelScale*underlineSize);
+
+ // yoff2: position right below video rectangle (bottom text line)
+ final float yoff2 = 2f-dy;
+
+ /**
+ System.err.println("XXX: a "+aspect+", aspect_h "+aspect_h+", dy "+dy+
+ "; underlineSize "+underlineSize+" "+(pixelScale*underlineSize)+
+ "; yoff "+yoff1+", yoff2 "+yoff2); */
+
+ // FIXME: Graph TextRenderer does not scale well, i.e. text update per 1/10s cause too much recompute of regions!
+ // final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+ final String text1 = String.format("%03.0f/%03.0f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+ pts, mPlayer.getDuration() / 1000f,
+ mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(),
+ aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet);
+ final String text2 = String.format("audio: id %d, kbps %d, codec %s",
+ mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec());
+ final String text3 = String.format("video: id %d, kbps %d, codec %s",
+ mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec());
+ final String text4 = mPlayer.getURI().getRawPath();
+ if( displayOSD && null != renderer ) {
+ renderString(drawable, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff);
+ renderString(drawable, text2, 1 /* col */, 0 /* row */, -1+z_diff, yoff2, 1f+z_diff);
+ renderString(drawable, text3, 1 /* col */, 1 /* row */, -1+z_diff, yoff2, 1f+z_diff);
+ renderString(drawable, text4, 1 /* col */, 2 /* row */, -1+z_diff, yoff2, 1f+z_diff);
+ }
+ } };
+ private final InfoTextRendererGLELBase textRendererGLEL = new InfoTextRendererGLELBase();
+ private boolean displayOSD = true;
+
private final KeyListener keyAction = new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if( e.isAutoRepeat() ) {
@@ -155,7 +244,15 @@ public class MovieCube implements GLEventListener {
System.err.println("MC "+e);
final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
int pts1 = 0;
- switch(e.getKeyCode()) {
+ switch(e.getKeySymbol()) {
+ case KeyEvent.VK_V: {
+ switch(swapIntervalSet) {
+ case 0: swapInterval = 1; break;
+ default: swapInterval = 0; break;
+ }
+ break;
+ }
+ case KeyEvent.VK_O: displayOSD = !displayOSD; break;
case KeyEvent.VK_RIGHT: pts1 = pts0 + 1000; break;
case KeyEvent.VK_UP: pts1 = pts0 + 10000; break;
case KeyEvent.VK_PAGE_UP: pts1 = pts0 + 30000; break;
@@ -260,14 +357,11 @@ public class MovieCube implements GLEventListener {
added = true;
} else { added = false; }
System.err.println("MC.init: kl-added "+added+", "+drawable.getClass().getName());
+ drawable.addGLEventListener(textRendererGLEL);
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- final GL2ES2 gl = drawable.getGL().getGL2ES2();
- if(-1 != swapInterval) {
- gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
- }
if(null == mPlayer) { return; }
cube.reshape(drawable, x, y, width, height);
}
@@ -275,6 +369,7 @@ public class MovieCube implements GLEventListener {
@Override
public void dispose(GLAutoDrawable drawable) {
System.err.println(Thread.currentThread()+" MovieCube.dispose ... ");
+ drawable.disposeGLEventListener(textRendererGLEL, true);
disposeImpl(drawable, true);
}
@@ -297,6 +392,13 @@ public class MovieCube implements GLEventListener {
@Override
public void display(GLAutoDrawable drawable) {
+ if(-1 != swapInterval) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ drawable.getAnimator().resetFPSCounter();
+ swapIntervalSet = swapInterval;
+ swapInterval = -1;
+ }
if(null == mPlayer) { return; }
if( resetGLState ) {
@@ -392,7 +494,7 @@ public class MovieCube implements GLEventListener {
System.err.println("forceGLDef "+forceGLDef);
System.err.println("swapInterval "+swapInterval);
- final MovieCube mc = new MovieCube(-2.3f, 0f, 0f);
+ final MovieCube mc = new MovieCube(zoom_def, 0f, 0f);
mc.setSwapInterval(swapInterval);
final GLProfile glp;
@@ -437,7 +539,10 @@ public class MovieCube implements GLEventListener {
}
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
window.addGLEventListener(mc);
- anim.setUpdateFPSFrames(60, System.err);
+ anim.setUpdateFPSFrames(60, null);
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
anim.resetFPSCounter();
}
if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
index fcf1cd2..787dbab 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
@@ -48,6 +48,7 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.graph.curve.Region;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
@@ -60,6 +61,7 @@ import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
@@ -101,6 +103,7 @@ public class MovieSimple implements GLEventListener {
private int effects = EFFECT_NORMAL;
private float alpha = 1.0f;
private int swapInterval = 1;
+ private int swapIntervalSet = -1;
private GLMediaPlayer mPlayer;
private final boolean mPlayerShared;
@@ -127,6 +130,55 @@ public class MovieSimple implements GLEventListener {
defURI = _defURI;
}
+ private final class InfoTextRendererGLELBase extends TextRendererGLELBase {
+ InfoTextRendererGLELBase() {
+ // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+ super(Region.VBAA_RENDERING_BIT);
+ texSizeScale = 2;
+
+ fontSize = 18;
+
+ staticRGBAColor[0] = 1.0f;
+ staticRGBAColor[1] = 1.0f;
+ staticRGBAColor[2] = 1.0f;
+ staticRGBAColor[3] = 1.0f;
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ final GLAnimatorControl anim = drawable.getAnimator();
+ final float lfps = null != anim ? anim.getLastFPS() : 0f;
+ final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f;
+
+ // Note: MODELVIEW is from [ 0 .. height ]
+
+ final int height = drawable.getHeight();
+
+ final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight();
+
+ // FIXME: Graph TextRenderer does not scale well, i.e. text update per 1/10s cause too much recompute of regions!
+ // final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+ final String text1 = String.format("%03.0f/%03.0f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+ pts, mPlayer.getDuration() / 1000f,
+ mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(),
+ aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet);
+ final String text2 = String.format("audio: id %d, kbps %d, codec %s",
+ mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec());
+ final String text3 = String.format("video: id %d, kbps %d, codec %s",
+ mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec());
+ final String text4 = mPlayer.getURI().getRawPath();
+ if( displayOSD && null != renderer ) {
+ renderString(drawable, text1, 1 /* col */, 1 /* row */, 0, 0, -1);
+ renderString(drawable, text2, 1 /* col */, -4 /* row */, 0, height, -1);
+ renderString(drawable, text3, 1 /* col */, -3 /* row */, 0, height, -1);
+ renderString(drawable, text4, 1 /* col */, -2 /* row */, 0, height, -1);
+ }
+ } };
+ private final InfoTextRendererGLELBase textRendererGLEL = new InfoTextRendererGLELBase();
+ private boolean displayOSD = true;
+
private final MouseListener mouseAction = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(e.getY()<=winHeight/2 && null!=mPlayer && 1 == e.getClickCount()) {
@@ -170,8 +222,7 @@ public class MovieSimple implements GLEventListener {
zoom += e.getRotation()[1]/10f; // vertical: wheel
System.err.println("zoom: "+zoom);
}
- }
- };
+ } };
private final KeyListener keyAction = new KeyAdapter() {
public void keyReleased(KeyEvent e) {
@@ -181,7 +232,15 @@ public class MovieSimple implements GLEventListener {
System.err.println("MC "+e);
final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
int pts1 = 0;
- switch(e.getKeyCode()) {
+ switch(e.getKeySymbol()) {
+ case KeyEvent.VK_V: {
+ switch(swapIntervalSet) {
+ case 0: swapInterval = 1; break;
+ default: swapInterval = 0; break;
+ }
+ break;
+ }
+ case KeyEvent.VK_O: displayOSD = !displayOSD; break;
case KeyEvent.VK_RIGHT: pts1 = pts0 + 1000; break;
case KeyEvent.VK_UP: pts1 = pts0 + 10000; break;
case KeyEvent.VK_PAGE_UP: pts1 = pts0 + 30000; break;
@@ -237,8 +296,7 @@ public class MovieSimple implements GLEventListener {
if( 0 != pts1 ) {
mPlayer.seek(pts1);
}
- }
- };
+ } };
/**
* Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values
@@ -263,9 +321,12 @@ public class MovieSimple implements GLEventListener {
resetGLState();
}
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
- // loop for-ever ..
- mPlayer.seek(0);
- mPlayer.play();
+ new Thread() {
+ public void run() {
+ // loop for-ever ..
+ mPlayer.seek(0);
+ mPlayer.play();
+ } }.start();
}
}
});
@@ -512,6 +573,7 @@ public class MovieSimple implements GLEventListener {
winWidth = window.getWidth();
winHeight = window.getHeight();
}
+ drawable.addGLEventListener(textRendererGLEL);
}
protected void updateInterleavedVBO(GL gl, Texture tex) {
@@ -571,9 +633,6 @@ public class MovieSimple implements GLEventListener {
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
- if(-1 != swapInterval) {
- gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
- }
if(null == mPlayer) { return; }
winWidth = width;
winHeight = height;
@@ -609,6 +668,7 @@ public class MovieSimple implements GLEventListener {
@Override
public void dispose(GLAutoDrawable drawable) {
+ drawable.disposeGLEventListener(textRendererGLEL, true);
disposeImpl(drawable, true);
}
@@ -646,6 +706,13 @@ public class MovieSimple implements GLEventListener {
@Override
public void display(GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ drawable.getAnimator().resetFPSCounter();
+ swapIntervalSet = swapInterval;
+ swapInterval = -1;
+ }
if(null == mPlayer) { return; }
if( resetGLState ) {
@@ -662,8 +729,6 @@ public class MovieSimple implements GLEventListener {
lastPerfPos = currentPos;
}
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
if(null == st) {
@@ -737,23 +802,32 @@ public class MovieSimple implements GLEventListener {
// Use GLEventListener in all cases [A+V, V, A]
window.addGLEventListener(ms);
final GLAnimatorControl anim = window.getAnimator();
- anim.setUpdateFPSFrames(60, System.err);
+ anim.setUpdateFPSFrames(60, null);
anim.resetFPSCounter();
-
/**
* Kick off player w/o GLEventListener, i.e. for audio only.
*
- try {
- ms.mPlayer.initGL(null);
- } catch (Exception e) {
- e.printStackTrace();
- destroyWindow();
- return;
- }
- ms.mPlayer.play();
- System.out.println("play.1 "+ms.mPlayer);
+ new Thread() {
+ public void run() {
+ try {
+ mp.initGL(null);
+ if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+ mp.play();
+ }
+ System.out.println("play.1 "+mp);
+ } catch (Exception e) {
+ e.printStackTrace();
+ destroyWindow();
+ return;
+ }
+ }
+ }.start();
*/
}
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
+ window.getAnimator().resetFPSCounter();
+ }
+
boolean destroy = false;
Throwable err = null;
@@ -765,8 +839,13 @@ public class MovieSimple implements GLEventListener {
} else {
System.err.println("MovieSimple State: EOS");
if( loopEOS ) {
- ms.mPlayer.seek(0);
- ms.mPlayer.play();
+ new Thread() {
+ public void run() {
+ mp.setPlaySpeed(1f);
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
} else {
destroy = true;
}
@@ -916,12 +995,11 @@ public class MovieSimple implements GLEventListener {
System.err.println("GLProfile: "+glp);
GLCapabilities caps = new GLCapabilities(glp);
- final Animator anim = new Animator();
- anim.start();
-
final MovieSimple[] mss = new MovieSimple[windowCount];
final GLWindow[] windows = new GLWindow[windowCount];
for(int i=0; i<windowCount; i++) {
+ final Animator anim = new Animator();
+ anim.start();
windows[i] = GLWindow.create(caps);
windows[i].addWindowListener(new WindowAdapter() {
public void windowDestroyed(WindowEvent e) {
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java
index 7beceb2..714c397 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java
@@ -374,10 +374,28 @@ public class TestParenting01NEWT extends UITestCase {
int state = 0;
Window.ReparentOperation reparentAction;
- while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) {
+ while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) {
Thread.sleep(durationPerTest);
switch(state) {
case 0:
+ // top-level glWindow2 hide
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(true, glWindow2.isVisible());
+ glWindow2.setVisible(false);
+ Assert.assertEquals(false, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 1:
+ // top-level glWindow2 show
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow2.isVisible());
+ glWindow2.setVisible(true);
+ Assert.assertEquals(true, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 2:
// glWindow2 -- child --> glWindow1: compatible
Assert.assertEquals(true, glWindow2.isVisible());
System.err.println("Frames(1) "+glWindow2.getTotalFPSFrames());
@@ -403,7 +421,25 @@ public class TestParenting01NEWT extends UITestCase {
break;
- case 1:
+ case 3:
+ // child glWindow2 hide
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(true, glWindow2.isVisible());
+ glWindow2.setVisible(false);
+ Assert.assertEquals(false, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 4:
+ // child glWindow2 show
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow2.isVisible());
+ glWindow2.setVisible(true);
+ Assert.assertEquals(true, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 5:
// glWindow2 --> top
Assert.assertEquals(true, glWindow2.isVisible());
@@ -566,10 +602,29 @@ public class TestParenting01NEWT extends UITestCase {
int state = 0;
Window.ReparentOperation reparentAction;
- while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) {
+ while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) {
Thread.sleep(durationPerTest);
switch(state) {
case 0:
+ // child glWindow2 hide
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(true, glWindow2.isVisible());
+ glWindow2.setVisible(false);
+ Assert.assertEquals(false, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 1:
+ // child glWindow2 show
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow2.isVisible());
+ glWindow2.setVisible(true);
+ Assert.assertEquals(true, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 2:
+ // glWindow2 --> top
Assert.assertEquals(true, glWindow2.isVisible());
reparentAction = glWindow2.reparentWindow(null, -1, -1, reparentHints);
Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction);
@@ -584,7 +639,27 @@ public class TestParenting01NEWT extends UITestCase {
Assert.assertSame(display1,glWindow2.getScreen().getDisplay());
Assert.assertEquals(1,Display.getActiveDisplayNumber());
break;
- case 1:
+
+ case 3:
+ // top-level glWindow2 hide
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(true, glWindow2.isVisible());
+ glWindow2.setVisible(false);
+ Assert.assertEquals(false, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 4:
+ // top-level glWindow2 show
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow2.isVisible());
+ glWindow2.setVisible(true);
+ Assert.assertEquals(true, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 5:
+ // glWindow2 -- child --> glWindow1: compatible
Assert.assertEquals(true, glWindow2.isVisible());
reparentAction = glWindow2.reparentWindow(glWindow1, -1, -1, reparentHints);
Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction);
diff --git a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
index 82247a5..a08e9f8 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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.util;
import java.io.BufferedReader;
@@ -69,15 +69,15 @@ public abstract class UITestCase {
public static final String SINGLE_INSTANCE_LOCK_FILE = "UITestCase.lock";
public static final int SINGLE_INSTANCE_LOCK_PORT = 59999;
-
+
public static final long SINGLE_INSTANCE_LOCK_TO = 6*60*1000; // wait up to 6 mins
public static final long SINGLE_INSTANCE_LOCK_POLL = 1000; // poll every 1s
private static volatile SingletonInstance singletonInstance;
-
+
private static volatile boolean testSupported = true;
private static volatile boolean resetXRandRIfX11AfterClass = false;
-
+
private static volatile int maxMethodNameLen = 0;
private static final synchronized void initSingletonInstance() {
@@ -89,11 +89,11 @@ public abstract class UITestCase {
}
}
}
-
+
public static boolean isTestSupported() {
return testSupported;
}
-
+
public static void setTestSupported(boolean v) {
System.err.println("setTestSupported: "+v);
testSupported = v;
@@ -102,13 +102,13 @@ public abstract class UITestCase {
public static void setResetXRandRIfX11AfterClass() {
resetXRandRIfX11AfterClass = true;
}
-
+
/**
* Iterates through all outputs and sets the preferred mode and normal rotation using RandR 1.3.
* <p>
* With NV drivers, one need to add the Modes in proper order to the Screen's Subsection "Display",
* otherwise they are either in unsorted resolution order or even n/a!
- * </p>
+ * </p>
*/
@SuppressWarnings("unused")
public static void resetXRandRIfX11() {
@@ -122,7 +122,7 @@ public abstract class UITestCase {
final ProcessBuilder pb = new ProcessBuilder("xrandr", "-q");
pb.redirectErrorStream(true);
System.err.println("XRandR Query: "+pb.command());
- final Process p = pb.start();
+ final Process p = pb.start();
final MiscUtils.StreamDump dump = new MiscUtils.StreamDump( out, p.getInputStream(), ioSync );
dump.start();
while( !dump.eos() ) {
@@ -185,7 +185,7 @@ public abstract class UITestCase {
}
return null;
}
-
+
public static int processCommand(String[] cmdline, OutputStream outstream, String outPrefix) {
int errorCode = 0;
final Object ioSync = new Object();
@@ -207,9 +207,9 @@ public abstract class UITestCase {
e.printStackTrace();
errorCode = Integer.MIN_VALUE;
}
- return errorCode;
+ return errorCode;
}
-
+
public int getMaxTestNameLen() {
if(0 == maxMethodNameLen) {
int ml = 0;
@@ -221,13 +221,13 @@ public abstract class UITestCase {
}
maxMethodNameLen = ml;
}
- return maxMethodNameLen;
+ return maxMethodNameLen;
}
-
+
public final String getTestMethodName() {
return _unitTestName.getMethodName();
}
-
+
public final String getSimpleTestName(String separator) {
return getClass().getSimpleName()+separator+getTestMethodName();
}
@@ -235,10 +235,10 @@ public abstract class UITestCase {
public final String getFullTestName(String separator) {
return getClass().getName()+separator+getTestMethodName();
}
-
+
@BeforeClass
public static void oneTimeSetUp() {
- // one-time initialization code
+ // one-time initialization code
initSingletonInstance();
}
@@ -259,14 +259,14 @@ public abstract class UITestCase {
System.err.println(" - "+unsupportedTestMsg);
Assume.assumeTrue(testSupported); // abort
}
- System.err.println();
+ System.err.println();
}
@After
public void tearDown() {
System.err.println("++++ UITestCase.tearDown: "+getFullTestName(" - "));
}
-
+
public static void waitForKey(String preMessage) {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println(preMessage+"> Press enter to continue");
@@ -274,7 +274,7 @@ public abstract class UITestCase {
System.err.println(stdin.readLine());
} catch (IOException e) { }
}
-
+
static final String unsupportedTestMsg = "Test not supported on this platform.";
public String getSnapshotFilename(int sn, String postSNDetail, GLCapabilitiesImmutable caps, int width, int height, boolean sinkHasAlpha, String fileSuffix, String destPath) {
@@ -284,7 +284,7 @@ public abstract class UITestCase {
final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1;
final String simpleTestName = this.getSimpleTestName(".");
final String filenameBaseName;
- {
+ {
final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ;
final String scrnm;
if(caps.isOnscreen()) {
@@ -307,22 +307,22 @@ public abstract class UITestCase {
final String aaext = caps.getSampleExtension();
postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
- filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s",
- simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel,
- scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext,
+ filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s",
+ simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel,
+ scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext,
width, height, fileSuffix).replace(' ', '_');
}
- return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
+ return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
}
-
+
/**
- * Takes a snapshot of the drawable's current front framebuffer. Example filenames:
+ * Takes a snapshot of the drawable's current front framebuffer. Example filenames:
* <pre>
* TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgba8888_-D24-St00-Sa00_default-0400x0300.png
* TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgba8880-D24-St00-Sa00_default-0200x0150.png
* TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgba5551-D24-St00-Sa00_default-0200x0150.png
* </pre>
- * @param sn sequential number
+ * @param sn sequential number
* @param postSNDetail optional detail to be added to the filename after <code>sn</code>
* @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.
@@ -330,20 +330,20 @@ public abstract class UITestCase {
* If <code>null</code> the <code>"png"</code> 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 <code>null</code> the current working directory is being used.
+ * If <code>null</code> the current working directory is being used.
*/
public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
final GLDrawable drawable = gl.getContext().getGLReadDrawable();
- final String filename = getSnapshotFilename(sn, postSNDetail,
- drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+ final String filename = getSnapshotFilename(sn, postSNDetail,
+ drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
readBufferUtil.hasAlpha(), fileSuffix, destPath);
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));
- }
+ }
}
-
+
public class SnapshotGLEventListener implements GLEventListener {
private final GLReadBufferUtil screenshot;
private volatile boolean makeShot = false;
@@ -394,6 +394,6 @@ public abstract class UITestCase {
postSNDetail = v;
}
};
-
+
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libjogl2-java.git
More information about the pkg-java-commits
mailing list