summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java2
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java4
-rwxr-xr-xsrc/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java10
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java18
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java (renamed from src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java)3
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/FBObject.java1943
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLExtensions.java81
-rw-r--r--src/jogl/classes/com/jogamp/opengl/JoglVersion.java18
-rw-r--r--src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java98
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java381
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/FBObject.java483
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java179
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java12
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java25
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java3
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java3
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java25
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java1
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java6
-rw-r--r--src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java8
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawable.java48
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java70
-rw-r--r--src/jogl/classes/javax/media/opengl/GLBase.java55
-rw-r--r--src/jogl/classes/javax/media/opengl/GLCapabilities.java65
-rw-r--r--src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java9
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java94
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDrawableFactory.java85
-rw-r--r--src/jogl/classes/javax/media/opengl/GLProfile.java63
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java333
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java7
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java278
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java191
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java240
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableImpl.java47
-rw-r--r--src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java138
-rw-r--r--src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java70
-rw-r--r--src/jogl/classes/jogamp/opengl/GLPbufferImpl.java39
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLContext.java76
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java100
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java226
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java318
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java123
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java34
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java56
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java52
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java153
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java12
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java109
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java19
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java130
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java23
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java102
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java11
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java156
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java110
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java130
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java6
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m2
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface.m14
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java34
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java4
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java18
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java67
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java28
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java37
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java8
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java31
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/Capabilities.java15
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java13
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java226
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java44
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java17
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java9
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java127
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java54
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java2
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java4
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java21
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java49
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java51
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java18
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java2
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java16
-rw-r--r--src/nativewindow/native/macosx/OSXmisc.m112
-rw-r--r--src/nativewindow/native/x11/Xmisc.c30
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java17
-rw-r--r--src/newt/classes/com/jogamp/newt/Window.java16
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java80
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyEvent.java2
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java55
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java508
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java99
-rw-r--r--src/newt/classes/jogamp/newt/DefaultEDTUtil.java2
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java96
-rw-r--r--src/newt/classes/jogamp/newt/OffscreenWindow.java46
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java113
-rw-r--r--src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java21
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java16
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/MD.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java6
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java11
-rw-r--r--src/newt/classes/jogamp/newt/driver/broadcom/egl/Display.java4
-rw-r--r--src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java5
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java4
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/KDDisplay.java15
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/KDWindow.java5
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java18
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java16
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/X11Window.java4
-rw-r--r--src/newt/classes/jogamp/newt/event/NEWTEventTask.java13
-rw-r--r--src/newt/native/MacWindow.m56
-rw-r--r--src/newt/native/NewtMacWindow.m6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java272
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestFBOMRTNEWT01.java)61
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java258
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java92
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java8
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java11
-rwxr-xr-xsrc/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java19
-rwxr-xr-xsrc/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java142
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java1
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java19
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleDemoES1.java)37
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java309
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java39
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java178
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java52
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java9
-rwxr-xr-xsrc/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java5
-rwxr-xr-xsrc/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java11
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java7
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp10
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java18
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWTBug450.java)16
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java1
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java1
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java4
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java)195
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java56
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java19
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java36
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java13
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java11
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java210
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java239
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java264
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java1
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/UITestCase.java55
187 files changed, 9312 insertions, 3149 deletions
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
index 1d9cf3668..5334d45cf 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
@@ -410,7 +410,7 @@ public class BuildComposablePipeline {
output.flush();
output.close();
- System.out.println("wrote to file: " + file); // JAU
+ System.out.println("wrote to file: " + file);
}
/** Get the name of the object through which API calls should be routed. */
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
index 87a734e1f..482d35cae 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
@@ -293,9 +293,9 @@ public class BuildStaticGLInfo {
output.println(" public static String getFunctionAssociation(String glFunctionName)");
output.println(" {");
output.println(" String mappedName = null;");
- output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutationNumber(glFunctionName);");
+ output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutationNumber(glFunctionName);");
output.println(" for(int i = 0; null==mappedName && i < funcNamePermNum; i++) {");
- output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutation(glFunctionName, i);");
+ output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutation(glFunctionName, i);");
output.println(" try {");
output.println(" mappedName = (String)funcToAssocMap.get(tmp);");
output.println(" } catch (Exception e) { }");
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
index c1a4facd2..ba025e18c 100755
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
@@ -43,7 +43,7 @@ import com.jogamp.gluegen.GlueEmitterControls;
import com.jogamp.gluegen.GlueGen;
import com.jogamp.gluegen.MethodBinding;
import com.jogamp.gluegen.procaddress.ProcAddressConfiguration;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -224,11 +224,11 @@ public class GLConfiguration extends ProcAddressConfiguration {
}
}
}
- boolean isGLEnum = GLExtensionNames.isGLEnumeration(symbol);
- boolean isGLFunc = GLExtensionNames.isGLFunction(symbol);
+ boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol);
+ boolean isGLFunc = GLNameResolver.isGLFunction(symbol);
if (isGLFunc || isGLEnum) {
- if (GLExtensionNames.isExtensionVEN(symbol, isGLFunc)) {
- String extSuffix = GLExtensionNames.getExtensionSuffix(symbol, isGLFunc);
+ if (GLNameResolver.isExtensionVEN(symbol, isGLFunc)) {
+ String extSuffix = GLNameResolver.getExtensionSuffix(symbol, isGLFunc);
if (getDropUniqVendorExtensions(extSuffix)) {
if (DEBUG_IGNORES) {
System.err.println("Ignore UniqVendorEXT: " + symbol + ", vendor " + extSuffix);
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
index f4658ad7b..809c6783d 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
@@ -51,7 +51,7 @@ import com.jogamp.gluegen.SymbolFilter;
import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.procaddress.ProcAddressEmitter;
import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import java.io.IOException;
import java.io.PrintWriter;
@@ -110,13 +110,13 @@ public class GLEmitter extends ProcAddressEmitter {
if (declarations != null) {
for (Iterator<String> iterator = declarations.iterator(); iterator.hasNext();) {
String decl = iterator.next();
- boolean isGLFunction = GLExtensionNames.isGLFunction(decl);
+ boolean isGLFunction = GLNameResolver.isGLFunction(decl);
boolean isGLEnumeration = false;
if (!isGLFunction) {
- isGLEnumeration = GLExtensionNames.isGLEnumeration(decl);
+ isGLEnumeration = GLNameResolver.isGLEnumeration(decl);
}
if (isGLFunction || isGLEnumeration) {
- String renamed = GLExtensionNames.normalize(decl, isGLFunction);
+ String renamed = GLNameResolver.normalize(decl, isGLFunction);
if (!renamed.equals(decl)) {
config.addJavaSymbolRename(decl, renamed);
}
@@ -181,7 +181,7 @@ public class GLEmitter extends ProcAddressEmitter {
String cause = null;
for (String decl : declarations) {
boolean isFunc = !decl.startsWith("GL_");
- if (!GLExtensionNames.isExtension(decl, isFunc)) {
+ if (!GLNameResolver.isExtension(decl, isFunc)) {
isExtension = false;
break;
}
@@ -199,7 +199,7 @@ public class GLEmitter extends ProcAddressEmitter {
}
}
cause = decl;
- String unifiedName = GLExtensionNames.normalize(decl, isFunc);
+ String unifiedName = GLNameResolver.normalize(decl, isFunc);
// NOTE that we look up the unified name in the
// BuildStaticGLInfo's notion of the APIs -- since
// we might not be emitting glue code for the
@@ -472,12 +472,12 @@ public class GLEmitter extends ProcAddressEmitter {
w.println(" * it was statically linked.");
w.println(" */");
w.println(" public long getAddressFor(String functionNameUsr) {");
- w.println(" String functionNameBase = "+GLExtensionNames.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLExtensionNames.normalizeARB(functionNameUsr, true), true);");
+ w.println(" String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
w.println(" String addressFieldNameBase = PROCADDRESS_VAR_PREFIX + functionNameBase;");
w.println(" java.lang.reflect.Field addressField = null;");
- w.println(" int funcNamePermNum = "+GLExtensionNames.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
+ w.println(" int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
w.println(" for(int i = 0; null==addressField && i < funcNamePermNum; i++) {");
- w.println(" String addressFieldName = "+GLExtensionNames.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+ w.println(" String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
w.println(" try {");
w.println(" addressField = getClass().getField(addressFieldName);");
w.println(" } catch (Exception e) { }");
diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java
index 426333034..92554776a 100644
--- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java
@@ -37,7 +37,8 @@
*/
package com.jogamp.gluegen.runtime.opengl;
-public class GLExtensionNames {
+/** Runtime utility identify and resolve extension names, which may be subsumed to core. */
+public class GLNameResolver {
//GL_XYZ : GL_XYZ, GL_XYZ_GL2, GL_XYZ_ARB, GL_XYZ_OES, GL_XYZ_OML
//GL_XYZ : GL_XYZ, GL_GL2_XYZ, GL_ARB_XYZ, GL_OES_XYZ, GL_OML_XYZ
//
diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
index fe9efebc7..9775de491 100644
--- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
@@ -45,10 +45,10 @@ public class GLProcAddressResolver implements FunctionAddressResolver {
public long resolve(String name, DynamicLookupHelper lookup) {
long newProcAddress = 0;
- int permutations = GLExtensionNames.getFuncNamePermutationNumber(name);
+ int permutations = GLNameResolver.getFuncNamePermutationNumber(name);
for (int i = 0; 0 == newProcAddress && i < permutations; i++) {
- String funcName = GLExtensionNames.getFuncNamePermutation(name, i);
+ String funcName = GLNameResolver.getFuncNamePermutation(name, i);
try {
newProcAddress = lookup.dynamicLookupFunction(funcName);
} catch (Exception e) {
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java
new file mode 100644
index 000000000..644d87b1a
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java
@@ -0,0 +1,1943 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GLBase;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.opengl.FBObject.Attachment.Type;
+
+/**
+ * Core utility class simplifying usage of framebuffer objects (FBO)
+ * with all {@link GLProfile}s.
+ * <p>
+ * Supports on-the-fly reconfiguration of dimension and multisample buffers via {@link #reset(GL, int, int, int)}
+ * while preserving the {@link Attachment} references.
+ * </p>
+ * <p>
+ * Integrates default read/write framebuffers via {@link GLContext#getDefaultReadFramebuffer()} and {@link GLContext#getDefaultReadFramebuffer()},
+ * which is being hooked at {@link GL#glBindFramebuffer(int, int)} when the default (<code>zero</code>) framebuffer is selected.
+ * </p>
+ *
+ * <p>FIXME: Implement support for {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} .</p>
+ */
+public class FBObject {
+ protected static final boolean DEBUG = Debug.debug("FBObject");
+
+ /**
+ * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * <code>ARB_ES2_compatibility</code>, <code>ARB_framebuffer_object</code>, <code>EXT_framebuffer_object</code> or <code>OES_framebuffer_object</code>.
+ * </p>
+ * <p>
+ * Basic FBO support may only include one color attachment and no multisampling,
+ * as well as limited internal formats for renderbuffer.
+ * </p>
+ * @see GLContext#hasFBO()
+ */
+ public static final boolean supportsBasicFBO(GL gl) {
+ return gl.getContext().hasFBO();
+ }
+
+ /**
+ * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * <code>ARB_framebuffer_object</code>, or all of
+ * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
+ * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
+ * </p>
+ * <p>
+ * Full FBO support includes multiple color attachments and multisampling.
+ * </p>
+ */
+ public static final boolean supportsFullFBO(GL gl) {
+ return gl.isGL3() || // GL >= 3.0
+
+ gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
+
+ ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object*
+ gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
+ gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
+ gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) ) ;
+ }
+
+ public static final int getMaxSamples(GL gl) {
+ if( supportsFullFBO(gl) ) {
+ int[] val = new int[] { 0 } ;
+ gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
+ return val[0];
+ } else {
+ return 0;
+ }
+ }
+
+ /** Common super class of all attachments */
+ public static abstract class Attachment {
+ public enum Type {
+ NONE, DEPTH, STENCIL, DEPTH_STENCIL, COLOR, COLOR_TEXTURE, DEPTH_TEXTURE, STENCIL_TEXTURE;
+
+ /**
+ * Returns {@link #COLOR}, {@link #DEPTH}, {@link #STENCIL} or {@link #DEPTH_STENCIL}
+ * @throws IllegalArgumentException if <code>format</code> cannot be handled.
+ */
+ public static Type determine(int format) throws IllegalArgumentException {
+ switch(format) {
+ case GL.GL_RGBA4:
+ case GL.GL_RGB5_A1:
+ case GL.GL_RGB565:
+ case GL.GL_RGB8:
+ case GL.GL_RGBA8:
+ return Type.COLOR;
+ case GL.GL_DEPTH_COMPONENT16:
+ case GL.GL_DEPTH_COMPONENT24:
+ case GL.GL_DEPTH_COMPONENT32:
+ return Type.DEPTH;
+ case GL.GL_STENCIL_INDEX1:
+ case GL.GL_STENCIL_INDEX4:
+ case GL.GL_STENCIL_INDEX8:
+ return Type.STENCIL;
+ case GL.GL_DEPTH24_STENCIL8:
+ return Type.DEPTH_STENCIL;
+ default:
+ throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format));
+ }
+ }
+ };
+
+ /** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */
+ public final Type type;
+
+ /** immutable the internal format */
+ public final int format;
+
+ private int width, height;
+
+ private int name;
+
+ /** <code>true</code> if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */
+ protected boolean resourceOwner;
+
+ private int initCounter;
+
+ protected Attachment(Type type, int iFormat, int width, int height, int name) {
+ this.type = type;
+ this.format = iFormat;
+ this.width = width;
+ this.height = height;
+ this.name = name;
+ this.resourceOwner = false;
+ this.initCounter = 0;
+ }
+
+ /** width of attachment */
+ public final int getWidth() { return width; }
+ /** height of attachment */
+ public final int getHeight() { return height; }
+ /* pp */ final void setSize(int w, int h) { width = w; height = h; }
+
+ /** buffer name [1..max], maybe a texture or renderbuffer name, depending on type. */
+ public final int getName() { return name; }
+ /* pp */ final void setName(int n) { name = n; }
+
+ public final int getInitCounter() { return initCounter; }
+
+ /**
+ * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is <code>zero</code>.
+ * <p>Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.</p>
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
+ */
+ public void initialize(GL gl) throws GLException {
+ initCounter++;
+ /*
+ super.initialize(gl);
+ if(1 == getInitCounter() && 0 == getName() ) {
+ do init ..
+ freeResources = true; // if all OK
+ }
+ */
+ }
+
+ /**
+ * Releases the attachment buffer if initialized, i.e. name is <code>zero</code>.
+ * <p>Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.</p>
+ * @throws GLException if buffer release fails.
+ */
+ public void free(GL gl) throws GLException {
+ /*
+ if(1 == getInitCounter() && freeResources && .. ) {
+ do free ..
+ }
+ super.free(gl);
+ */
+ initCounter--;
+ if(0 == initCounter) {
+ resourceOwner = false;
+ name = 0;
+ }
+ if(DEBUG) {
+ System.err.println("Attachment.free: "+this);
+ }
+ }
+
+ /**
+ * <p>
+ * Comparison by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o) {
+ if( this == o ) return true;
+ if( ! ( o instanceof Attachment ) ) return false;
+ final Attachment a = (Attachment)o;
+ return type == a.type &&
+ format == a.format ||
+ width == a.width ||
+ height== a.height ||
+ name == a.name ;
+ }
+
+ /**
+ * <p>
+ * Hashed by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + type.ordinal();
+ hash = ((hash << 5) - hash) + format;
+ hash = ((hash << 5) - hash) + width;
+ hash = ((hash << 5) - hash) + height;
+ hash = ((hash << 5) - hash) + name;
+ return hash;
+ }
+
+ int objectHashCode() { return super.hashCode(); }
+
+ public String toString() {
+ return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+
+ ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+
+ ", resOwner "+resourceOwner+", initCount "+initCounter+"]";
+ }
+
+ public static Type getType(int attachmentPoint, int maxColorAttachments) {
+ if( GL.GL_COLOR_ATTACHMENT0 <= attachmentPoint && attachmentPoint < GL.GL_COLOR_ATTACHMENT0+maxColorAttachments ) {
+ return Type.COLOR;
+ }
+ switch(attachmentPoint) {
+ case GL.GL_DEPTH_ATTACHMENT:
+ return Type.DEPTH;
+ case GL.GL_STENCIL_ATTACHMENT:
+ return Type.STENCIL;
+ default:
+ throw new IllegalArgumentException("Invalid attachment point 0x"+Integer.toHexString(attachmentPoint));
+ }
+ }
+ }
+
+ /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */
+ public static class RenderAttachment extends Attachment {
+ private int samples;
+
+ /**
+ * @param type allowed types are {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR}
+ * @param iFormat
+ * @param samples
+ * @param width
+ * @param height
+ * @param name
+ */
+ public RenderAttachment(Type type, int iFormat, int samples, int width, int height, int name) {
+ super(validateType(type), iFormat, width, height, name);
+ this.samples = samples;
+ }
+
+ /** number of samples, or zero for no multisampling */
+ public final int getSamples() { return samples; }
+ /* pp */ final void setSamples(int s) { samples = s; }
+
+ private static Type validateType(Type type) {
+ switch(type) {
+ case DEPTH:
+ case STENCIL:
+ case COLOR:
+ return type;
+ default:
+ throw new IllegalArgumentException("Invalid type: "+type);
+ }
+ }
+
+ /**
+ * <p>
+ * Comparison by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o) {
+ if( this == o ) return true;
+ if( ! ( o instanceof RenderAttachment ) ) return false;
+ return super.equals(o) &&
+ samples == ((RenderAttachment)o).samples;
+ }
+
+ /**
+ * <p>
+ * Hashed by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = super.hashCode();
+ hash = ((hash << 5) - hash) + samples;
+ return hash;
+ }
+
+ @Override
+ public void initialize(GL gl) throws GLException {
+ super.initialize(gl);
+ if( 1 == getInitCounter() && 0 == getName() ) {
+ final int[] name = new int[] { -1 };
+ gl.glGenRenderbuffers(1, name, 0);
+ if( 0 == name[0] ) {
+ throw new GLException("null renderbuffer, "+this);
+ }
+ setName(name[0]);
+
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName());
+ if( samples > 0 ) {
+ ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight());
+ } else {
+ gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight());
+ }
+ int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteRenderbuffers(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this);
+ }
+ resourceOwner = true;
+ if(DEBUG) {
+ System.err.println("Attachment.init: "+this);
+ }
+ }
+ }
+
+ @Override
+ public void free(GL gl) {
+ if(1 == getInitCounter() && resourceOwner && 0 != getName() ) {
+ final int[] name = new int[] { getName() };
+ gl.glDeleteRenderbuffers(1, name, 0);
+ }
+ super.free(gl);
+ }
+
+ public String toString() {
+ return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+
+ ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+
+ ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]";
+ }
+ }
+
+ /**
+ * Marker interface, denotes a color buffer attachment.
+ * <p>Always an instance of {@link Attachment}.</p>
+ * <p>Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.</b>
+ */
+ public static interface Colorbuffer {
+ }
+
+ /** Color render buffer attachment */
+ public static class ColorAttachment extends RenderAttachment implements Colorbuffer {
+ public ColorAttachment(int iFormat, int samples, int width, int height, int name) {
+ super(Type.COLOR, iFormat, samples, width, height, name);
+ }
+ }
+
+ /** Texture attachment */
+ public static class TextureAttachment extends Attachment implements Colorbuffer {
+ /** details of the texture setup */
+ public final int dataFormat, dataType, magFilter, minFilter, wrapS, wrapT;
+
+ /**
+ * @param type allowed types are [ {@link Type#COLOR_TEXTURE}, {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} ]
+ * @param iFormat
+ * @param width
+ * @param height
+ * @param dataFormat
+ * @param dataType
+ * @param magFilter
+ * @param minFilter
+ * @param wrapS
+ * @param wrapT
+ * @param name
+ */
+ public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType,
+ int magFilter, int minFilter, int wrapS, int wrapT, int name) {
+ super(validateType(type), iFormat, width, height, name);
+ this.dataFormat = dataFormat;
+ this.dataType = dataType;
+ this.magFilter = magFilter;
+ this.minFilter = minFilter;
+ this.wrapS = wrapS;
+ this.wrapT = wrapT;
+ }
+
+ private static Type validateType(Type type) {
+ switch(type) {
+ case COLOR_TEXTURE:
+ case DEPTH_TEXTURE:
+ case STENCIL_TEXTURE:
+ return type;
+ default:
+ throw new IllegalArgumentException("Invalid type: "+type);
+ }
+ }
+
+ /**
+ * Initializes the texture and set it's parameter, if uninitialized, i.e. name is <code>zero</code>.
+ * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case.
+ */
+ @Override
+ public void initialize(GL gl) throws GLException {
+ super.initialize(gl);
+ if( 1 == getInitCounter() && 0 == getName() ) {
+ final int[] name = new int[] { -1 };
+ gl.glGenTextures(1, name, 0);
+ if(0 == name[0]) {
+ throw new GLException("null texture, "+this);
+ }
+ setName(name[0]);
+
+ gl.glBindTexture(GL.GL_TEXTURE_2D, name[0]);
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ if( 0 < magFilter ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter);
+ }
+ if( 0 < minFilter ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter);
+ }
+ if( 0 < wrapS ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS);
+ }
+ if( 0 < wrapT ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
+ }
+ int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteTextures(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this);
+ }
+ resourceOwner = true;
+ }
+ if(DEBUG) {
+ System.err.println("Attachment.init: "+this);
+ }
+ }
+
+ @Override
+ public void free(GL gl) {
+ if(1 == getInitCounter() && resourceOwner && 0 != getName() ) {
+ final int[] name = new int[] { getName() };
+ gl.glDeleteTextures(1, name, 0);
+ }
+ super.free(gl);
+ }
+ }
+
+ private boolean initialized;
+ private boolean basicFBOSupport;
+ private boolean fullFBOSupport;
+ private boolean rgba8Avail;
+ private boolean depth24Avail;
+ private boolean depth32Avail;
+ private boolean stencil01Avail;
+ private boolean stencil04Avail;
+ private boolean stencil08Avail;
+ private boolean stencil16Avail;
+ private boolean packedDepthStencilAvail;
+ private int maxColorAttachments, maxSamples, maxTextureSize, maxRenderbufferSize;
+
+ private int width, height, samples;
+ private int vStatus;
+ private int fbName;
+ private boolean bound;
+
+ private int colorAttachmentCount;
+ private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points
+ private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil
+
+ private final FBObject samplesSink; // MSAA sink
+ private TextureAttachment samplesSinkTexture;
+ private boolean samplesSinkDirty;
+
+ //
+ // ColorAttachment helper ..
+ //
+
+ private final void validateColorAttachmentPointRange(int point) {
+ if(maxColorAttachments != colorAttachmentPoints.length) {
+ throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints);
+ }
+ if(0 > point || point >= maxColorAttachments) {
+ throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"]");
+ }
+ }
+
+ private final void validateAddColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ if( null != colorAttachmentPoints[point] ) {
+ throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorAttachmentPoints[point]);
+ }
+ }
+
+ private final void addColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ final Colorbuffer c = colorAttachmentPoints[point];
+ if( null != c && c != ca ) {
+ throw new IllegalArgumentException("Add failed: requested to add "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ }
+ colorAttachmentPoints[point] = ca;
+ colorAttachmentCount++;
+ }
+
+ private final void removeColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ final Colorbuffer c = colorAttachmentPoints[point];
+ if( null != c && c != ca ) {
+ throw new IllegalArgumentException("Remove failed: requested to removed "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ }
+ colorAttachmentPoints[point] = null;
+ colorAttachmentCount--;
+ }
+
+ /**
+ * Return the {@link Colorbuffer} attachment at <code>attachmentPoint</code> if it is attached to this FBO, otherwise null.
+ *
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachTexture2D(GL, int, boolean, int, int, int, int)
+ * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
+ */
+ public final Colorbuffer getColorbuffer(int attachmentPoint) {
+ validateColorAttachmentPointRange(attachmentPoint);
+ return colorAttachmentPoints[attachmentPoint];
+ }
+
+ /**
+ * Finds the passed {@link Colorbuffer} within the valid range of attachment points
+ * using <i>reference</i> comparison only.
+ * <p>
+ * Note: Slow. Implementation uses a logN array search to save resources, i.e. not using a HashMap.
+ * </p>
+ * @param ca the {@link Colorbuffer} to look for.
+ * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1]
+ */
+ public final int getColorbufferAttachmentPoint(Colorbuffer ca) {
+ for(int i=0; i<colorAttachmentPoints.length; i++) {
+ if( colorAttachmentPoints[i] == ca ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the passed {@link Colorbuffer} if it is attached to this FBO, otherwise null.
+ * Implementation compares the <i>reference</i> only.
+ *
+ * <p>
+ * Note: Slow. Uses {@link #getColorbufferAttachmentPoint(Colorbuffer)} to determine it's attachment point
+ * to be used for {@link #getColorbuffer(int)}
+ * </p>
+ *
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachTexture2D(GL, int, boolean, int, int, int, int)
+ * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
+ */
+ public final Colorbuffer getColorbuffer(Colorbuffer ca) {
+ final int p = getColorbufferAttachmentPoint(ca);
+ return p>=0 ? getColorbuffer(p) : null;
+ }
+
+ /**
+ * Creates an uninitialized FBObject instance.
+ * <p>
+ * Call {@link #init(GL, int, int, int)} .. etc to use it.
+ * </p>
+ */
+ public FBObject() {
+ this(false);
+ }
+ /* pp */ FBObject(boolean isSampleSink) {
+ this.initialized = false;
+
+ // TBD @ init
+ this.basicFBOSupport = false;
+ this.fullFBOSupport = false;
+ this.rgba8Avail = false;
+ this.depth24Avail = false;
+ this.depth32Avail = false;
+ this.stencil01Avail = false;
+ this.stencil04Avail = false;
+ this.stencil08Avail = false;
+ this.stencil16Avail = false;
+ this.packedDepthStencilAvail = false;
+ this.maxColorAttachments=-1;
+ this.maxSamples=-1;
+ this.maxTextureSize = 0;
+ this.maxRenderbufferSize = 0;
+
+ this.width = 0;
+ this.height = 0;
+ this.samples = 0;
+ this.vStatus = -1;
+ this.fbName = 0;
+ this.bound = false;
+
+ this.colorAttachmentPoints = null; // at init ..
+ this.colorAttachmentCount = 0;
+ this.depth = null;
+ this.stencil = null;
+
+ this.samplesSink = isSampleSink ? null : new FBObject(true);
+ this.samplesSinkTexture = null;
+ this.samplesSinkDirty = true;
+ }
+
+ private void init(GL gl, int width, int height, int samples) throws GLException {
+ if(initialized) {
+ throw new GLException("FBO already initialized");
+ }
+ fullFBOSupport = supportsFullFBO(gl);
+
+ if( !fullFBOSupport && !supportsBasicFBO(gl) ) {
+ throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this);
+ }
+
+ basicFBOSupport = true;
+
+ rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8);
+ depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24);
+ depth32Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth32);
+ stencil01Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil1);
+ stencil04Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil4);
+ stencil08Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil8);
+ stencil16Avail = fullFBOSupport;
+
+ packedDepthStencilAvail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil);
+
+ final boolean NV_fbo_color_attachments = gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments);
+
+ int val[] = new int[1];
+
+ int glerr = gl.glGetError();
+ if(DEBUG && GL.GL_NO_ERROR != glerr) {
+ System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr));
+ }
+
+ int realMaxColorAttachments = 1;
+ maxColorAttachments = 1;
+ if( null != samplesSink && fullFBOSupport || NV_fbo_color_attachments ) {
+ try {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0);
+ glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1
+ } else if(DEBUG) {
+ System.err.println("FBObject.init-GL_MAX_COLOR_ATTACHMENTS query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ } catch (GLException gle) {}
+ }
+ maxColorAttachments = realMaxColorAttachments <= 8 ? realMaxColorAttachments : 8; // cap to limit array size
+
+ colorAttachmentPoints = new Colorbuffer[maxColorAttachments];
+ colorAttachmentCount = 0;
+
+ maxSamples = 0;
+ if(fullFBOSupport) {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
+ glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ maxSamples = val[0];
+ } else if(DEBUG) {
+ System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ }
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
+ maxTextureSize = val[0];
+ gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0);
+ this.maxRenderbufferSize = val[0];
+
+ glerr = gl.glGetError();
+ if(DEBUG && GL.GL_NO_ERROR != glerr) {
+ System.err.println("FBObject.init-preexisting.1 GL Error 0x"+Integer.toHexString(glerr));
+ }
+
+ this.width = width;
+ this.height = height;
+ this.samples = samples <= maxSamples ? samples : maxSamples;
+
+ if(DEBUG) {
+ System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples");
+ System.err.println("basicFBOSupport: "+basicFBOSupport);
+ System.err.println("fullFBOSupport: "+fullFBOSupport);
+ System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments);
+ System.err.println("maxSamples: "+maxSamples);
+ System.err.println("maxTextureSize: "+maxTextureSize);
+ System.err.println("maxRenderbufferSize: "+maxRenderbufferSize);
+ System.err.println("rgba8: "+rgba8Avail);
+ System.err.println("depth24: "+depth24Avail);
+ System.err.println("depth32: "+depth32Avail);
+ System.err.println("stencil01: "+stencil01Avail);
+ System.err.println("stencil04: "+stencil04Avail);
+ System.err.println("stencil08: "+stencil08Avail);
+ System.err.println("stencil16: "+stencil16Avail);
+ System.err.println("packedDepthStencil: "+packedDepthStencilAvail);
+ System.err.println("NV_fbo_color_attachments: "+NV_fbo_color_attachments);
+ System.err.println(gl.getContext().getGLVersion());
+ System.err.println(JoglVersion.getGLStrings(gl, null).toString());
+ System.err.println(gl.getContext());
+ }
+
+ checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error
+
+ if(width > 2 + maxTextureSize || height> 2 + maxTextureSize ||
+ width > maxRenderbufferSize || height> maxRenderbufferSize ) {
+ throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]");
+ }
+
+ if(null != samplesSink) {
+ // init sampling sink
+ samplesSink.reset(gl, width, height);
+ resetMSAATexture2DSink(gl);
+ }
+
+ // generate fbo ..
+ gl.glGenFramebuffers(1, val, 0);
+ fbName = val[0];
+ if(0 == fbName) {
+ throw new GLException("null framebuffer");
+ }
+
+ // bind fbo ..
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName);
+ checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error
+ if(!gl.glIsFramebuffer(fbName)) {
+ checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
+ }
+ bound = true;
+ initialized = true;
+
+ updateStatus(gl);
+ if(DEBUG) {
+ System.err.println("FBObject.init(): "+this);
+ }
+ }
+
+ /**
+ * Initializes or resets this FBO's instance.
+ * <p>
+ * In case the new parameters are compatible with the current ones
+ * no action will be performed. Otherwise all attachments will be recreated
+ * to match the new given parameters.
+ * </p>
+ * <p>
+ * Currently incompatibility and hence recreation is given if
+ * the size or sample count doesn't match for subsequent calls.
+ * </p>
+ *
+ * <p>Leaves the FBO bound state untouched</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth
+ * @param newHeight
+ * @throws GLException in case of an error
+ */
+ public final void reset(GL gl, int newWidth, int newHeight) {
+ reset(gl, newWidth, newHeight, 0);
+ }
+
+ /**
+ * Initializes or resets this FBO's instance.
+ * <p>
+ * In case the new parameters are compatible with the current ones
+ * no action will be performed. Otherwise all attachments will be recreated
+ * to match the new given parameters.
+ * </p>
+ * <p>
+ * Currently incompatibility and hence recreation is given if
+ * the size or sample count doesn't match for subsequent calls.
+ * </p>
+ *
+ * <p>Leaves the FBO bound state untouched</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth
+ * @param newHeight
+ * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}.
+ * @throws GLException in case of an error
+ */
+ public final void reset(GL gl, int newWidth, int newHeight, int newSamples) {
+ if(!initialized) {
+ init(gl, newWidth, newHeight, newSamples);
+ return;
+ }
+ newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp
+
+ if( newWidth != width || newHeight != height || newSamples != samples ) {
+ if(DEBUG) {
+ System.err.println("FBObject.reset - START - "+this);
+ }
+
+ final boolean wasBound = isBound();
+
+ width = newWidth;
+ height = newHeight;
+ samples = newSamples;
+ detachAllImpl(gl, true , true);
+ resetMSAATexture2DSink(gl);
+
+ if(wasBound) {
+ bind(gl);
+ } else {
+ unbind(gl);
+ }
+
+ if(DEBUG) {
+ System.err.println("FBObject.reset - END - "+this);
+ }
+ }
+ }
+
+ /**
+ * Note that the status may reflect an incomplete state during transition of attachments.
+ * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1
+ * @see #validateStatus()
+ */
+ public final int getStatus() {
+ return vStatus;
+ }
+
+ /** return the {@link #getStatus()} as a string. */
+ public final String getStatusString() {
+ return getStatusString(vStatus);
+ }
+
+ public static final String getStatusString(int fbStatus) {
+ switch(fbStatus) {
+ case -1:
+ return "NOT A FBO";
+
+ case GL.GL_FRAMEBUFFER_COMPLETE:
+ return "OK";
+
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ return("GL FBO: incomplete, incomplete attachment\n");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ return("GL FBO: incomplete, missing attachment");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ return("GL FBO: incomplete, attached images must have same dimensions");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
+ return("GL FBO: incomplete, attached images must have same format");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ return("GL FBO: incomplete, missing draw buffer");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ return("GL FBO: incomplete, missing read buffer");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ return("GL FBO: incomplete, missing multisample buffer");
+ case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+ return("GL FBO: incomplete, layer targets");
+
+ case GL.GL_FRAMEBUFFER_UNSUPPORTED:
+ return("GL FBO: Unsupported framebuffer format");
+ case GL2GL3.GL_FRAMEBUFFER_UNDEFINED:
+ return("GL FBO: framebuffer undefined");
+
+ case 0:
+ return("GL FBO: incomplete, implementation fault");
+ default:
+ return("GL FBO: incomplete, implementation ERROR 0x"+Integer.toHexString(fbStatus));
+ }
+ }
+
+ /**
+ * The status may even be valid if incomplete during transition of attachments.
+ * @see #getStatus()
+ */
+ public final boolean isStatusValid() {
+ switch(vStatus) {
+ case GL.GL_FRAMEBUFFER_COMPLETE:
+ return true;
+
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+ if(0 == colorAttachmentCount || null == depth) {
+ // we are in transition
+ return true;
+ }
+
+ case GL.GL_FRAMEBUFFER_UNSUPPORTED:
+ case GL2GL3.GL_FRAMEBUFFER_UNDEFINED:
+
+ case 0:
+ default:
+ System.out.println("Framebuffer " + fbName + " is incomplete: status = 0x" + Integer.toHexString(vStatus) +
+ " : " + getStatusString(vStatus));
+ return false;
+ }
+ }
+
+ private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException {
+ if(GL.GL_NO_ERROR != err) {
+ if(null != gl) {
+ destroy(gl);
+ }
+ if(null != exceptionMessage) {
+ throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err));
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private final void checkInitialized() throws GLException {
+ if(!initialized) {
+ throw new GLException("FBO not initialized, call init(GL) first.");
+ }
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the texture data type and format automatically.
+ *
+ * <p>Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.</p>
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException {
+ return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the texture data type and format automatically.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
+ final int textureInternalFormat, textureDataFormat, textureDataType;
+ if(gl.isGLES()) {
+ textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint,
+ int internalFormat, int dataFormat, int dataType,
+ int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
+ return attachTexture2D(gl, attachmentPoint,
+ new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType,
+ magFilter, minFilter, wrapS, wrapT, 0 /* name */));
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * <p>
+ * In case the passed TextureAttachment <code>texA</code> is uninitialized, i.e. it's texture name is <code>zero</code>,
+ * a new texture name is generated and setup w/ the texture parameter.<br/>
+ * Otherwise, i.e. texture name is not <code>zero</code>, the passed TextureAttachment <code>texA</code> is
+ * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
+ * </p>
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above.
+ * @return the passed TextureAttachment <code>texA</code> instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException {
+ validateAddColorAttachment(attachmentPoint, texA);
+
+ if(samples>0) {
+ removeColorAttachment(attachmentPoint, texA);
+ throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl).");
+ }
+
+ texA.initialize(gl);
+ addColorAttachment(attachmentPoint, texA);
+
+ bind(gl);
+
+ // Set up the color buffer for use as a renderable texture:
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ GL.GL_TEXTURE_2D, texA.getName(), 0);
+ updateStatus(gl);
+
+ if(!isStatusValid()) {
+ detachColorbuffer(gl, attachmentPoint);
+ throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.attachTexture2D: "+this);
+ }
+ return texA;
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the format automatically.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
+ * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException {
+ final int internalFormat;
+ if( rgba8Avail ) {
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
+ } else {
+ internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
+ }
+ return attachColorbuffer(gl, attachmentPoint, internalFormat);
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8}
+ * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated
+ * @throws IllegalArgumentException if <code>internalFormat</code> doesn't reflect a colorbuffer
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, int internalFormat) throws GLException, IllegalArgumentException {
+ final Attachment.Type atype = Attachment.Type.determine(internalFormat);
+ if( Attachment.Type.COLOR != atype ) {
+ throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+
+ return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0));
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param colA the template for the new {@link ColorAttachment}
+ * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException {
+ validateAddColorAttachment(attachmentPoint, colA);
+
+ colA.initialize(gl);
+ addColorAttachment(attachmentPoint, colA);
+
+ bind(gl);
+
+ // Attach the color buffer
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ GL.GL_RENDERBUFFER, colA.getName());
+
+ updateStatus(gl);
+ if(!isStatusValid()) {
+ detachColorbuffer(gl, attachmentPoint);
+ throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.attachColorbuffer: "+this);
+ }
+ return colA;
+ }
+
+
+ /**
+ * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance,
+ * selecting the internalFormat automatically.
+ * <p>
+ * Stencil and depth buffer can be attached only once.
+ * </p>
+ * <p>
+ * In case the desired type or bit-number is not supported, the next available one is chosen.
+ * </p>
+ * <p>
+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details
+ * about the attached buffer. The details cannot be returned, since it's possible 2 buffers
+ * are being created, depth and stencil.
+ * </p>
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl
+ * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL}
+ * @param reqBits desired bits for depth or -1 for default (24 bits)
+ * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached.
+ * @throws IllegalArgumentException
+ * @see #getDepthAttachment()
+ * @see #getStencilAttachment()
+ */
+ public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException {
+ if( 0 > reqBits ) {
+ reqBits = 24;
+ }
+ final int internalFormat;
+ int internalStencilFormat = -1;
+
+ switch ( atype ) {
+ case DEPTH:
+ if( 32 <= reqBits && depth32Avail ) {
+ internalFormat = GL.GL_DEPTH_COMPONENT32;
+ } else if( 24 <= reqBits && depth24Avail ) {
+ internalFormat = GL.GL_DEPTH_COMPONENT24;
+ } else {
+ internalFormat = GL.GL_DEPTH_COMPONENT16;
+ }
+ break;
+
+ case STENCIL:
+ if( 16 <= reqBits && stencil16Avail ) {
+ internalFormat = GL2GL3.GL_STENCIL_INDEX16;
+ } else if( 8 <= reqBits && stencil08Avail ) {
+ internalFormat = GL.GL_STENCIL_INDEX8;
+ } else if( 4 <= reqBits && stencil04Avail ) {
+ internalFormat = GL.GL_STENCIL_INDEX4;
+ } else if( 1 <= reqBits && stencil01Avail ) {
+ internalFormat = GL.GL_STENCIL_INDEX1;
+ } else {
+ throw new GLException("stencil buffer n/a");
+ }
+ break;
+
+ case DEPTH_STENCIL:
+ if( packedDepthStencilAvail ) {
+ internalFormat = GL.GL_DEPTH24_STENCIL8;
+ } else {
+ if( 24 <= reqBits && depth24Avail ) {
+ internalFormat = GL.GL_DEPTH_COMPONENT24;
+ } else {
+ internalFormat = GL.GL_DEPTH_COMPONENT16;
+ }
+ if( stencil08Avail ) {
+ internalStencilFormat = GL.GL_STENCIL_INDEX8;
+ } else if( stencil04Avail ) {
+ internalStencilFormat = GL.GL_STENCIL_INDEX4;
+ } else if( stencil01Avail ) {
+ internalStencilFormat = GL.GL_STENCIL_INDEX1;
+ } else {
+ throw new GLException("stencil buffer n/a");
+ }
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this);
+ }
+
+ attachRenderbufferImpl(gl, atype, internalFormat);
+
+ if(0<=internalStencilFormat) {
+ attachRenderbufferImpl(gl, Attachment.Type.STENCIL, internalStencilFormat);
+ }
+ }
+
+ /**
+ * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance,
+ * depending on the <code>internalFormat</code>.
+ * <p>
+ * Stencil and depth buffer can be attached only once.
+ * </p>
+ * <p>
+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details
+ * about the attached buffer. The details cannot be returned, since it's possible 2 buffers
+ * are being created, depth and stencil.
+ * </p>
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param internalFormat {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24}, {@link GL#GL_DEPTH_COMPONENT32},
+ * {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8}
+ * or {@link GL#GL_DEPTH24_STENCIL8}
+ * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached.
+ * @throws IllegalArgumentException
+ * @see #getDepthAttachment()
+ * @see #getStencilAttachment()
+ */
+ public final void attachRenderbuffer(GL gl, int internalFormat) throws GLException, IllegalArgumentException {
+ final Attachment.Type atype = Attachment.Type.determine(internalFormat);
+ if( Attachment.Type.DEPTH != atype && Attachment.Type.STENCIL != atype && Attachment.Type.DEPTH_STENCIL != atype ) {
+ throw new IllegalArgumentException("renderformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+ attachRenderbufferImpl(gl, atype, internalFormat);
+ }
+
+ protected final void attachRenderbufferImpl(GL gl, Attachment.Type atype, int internalFormat) throws GLException {
+ if( null != depth && ( Attachment.Type.DEPTH == atype || Attachment.Type.DEPTH_STENCIL == atype ) ) {
+ throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+ if( null != stencil && ( Attachment.Type.STENCIL== atype || Attachment.Type.DEPTH_STENCIL == atype ) ) {
+ throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+ attachRenderbufferImpl2(gl, atype, internalFormat);
+ }
+
+ private final void attachRenderbufferImpl2(GL gl, Attachment.Type atype, int internalFormat) throws GLException {
+ if( Attachment.Type.DEPTH == atype ) {
+ if(null == depth) {
+ depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0);
+ } else {
+ depth.setSize(width, height);
+ depth.setSamples(samples);
+ }
+ depth.initialize(gl);
+ } else if( Attachment.Type.STENCIL == atype ) {
+ if(null == stencil) {
+ stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, 0);
+ } else {
+ stencil.setSize(width, height);
+ stencil.setSamples(samples);
+ }
+ stencil.initialize(gl);
+ } else if( Attachment.Type.DEPTH_STENCIL == atype ) {
+ if(null == depth) {
+ depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0);
+ } else {
+ depth.setSize(width, height);
+ depth.setSamples(samples);
+ }
+ depth.initialize(gl);
+ if(null == stencil) {
+ stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, depth.getName());
+ } else {
+ stencil.setName(depth.getName());
+ stencil.setSize(width, height);
+ stencil.setSamples(samples);
+ }
+ stencil.initialize(gl);
+ }
+
+ bind(gl);
+
+ // Attach the buffer
+ if( Attachment.Type.DEPTH == atype ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName());
+ } else if( Attachment.Type.STENCIL == atype ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName());
+ } else if( Attachment.Type.DEPTH_STENCIL == atype ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName());
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName());
+ }
+
+ updateStatus(gl);
+ if( !isStatusValid() ) {
+ detachRenderbuffer(gl, atype);
+ throw new GLException("renderbuffer attachment failed: "+this.getStatusString());
+ }
+
+ if(DEBUG) {
+ System.err.println("FBObject.attachRenderbuffer: "+this);
+ }
+ }
+
+ /**
+ * <p>Leaves the FBO bound!</p>
+ * @param gl
+ * @param ca
+ * @throws IllegalArgumentException
+ */
+ public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException {
+ if(null == detachColorbufferImpl(gl, attachmentPoint, false)) {
+ throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this);
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.detachAll: "+this);
+ }
+ }
+
+ private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) {
+ final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here
+
+ if(null == colbuf) {
+ return null;
+ }
+
+ bind(gl);
+
+ if(colbuf instanceof TextureAttachment) {
+ final TextureAttachment texA = (TextureAttachment) colbuf;
+ if( 0 != texA.getName() ) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ GL.GL_TEXTURE_2D, 0, 0);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
+ }
+ texA.free(gl);
+ removeColorAttachment(attachmentPoint, texA);
+ if(recreate) {
+ texA.setSize(width, height);
+ attachTexture2D(gl, attachmentPoint, texA);
+ }
+ } else if(colbuf instanceof ColorAttachment) {
+ final ColorAttachment colA = (ColorAttachment) colbuf;
+ if( 0 != colA.getName() ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0+attachmentPoint,
+ GL.GL_RENDERBUFFER, 0);
+ }
+ colA.free(gl);
+ removeColorAttachment(attachmentPoint, colbuf);
+ if(recreate) {
+ colA.setSize(width, height);
+ colA.setSamples(samples);
+ attachColorbuffer(gl, attachmentPoint, colA);
+ }
+ }
+ return colbuf;
+ }
+
+ /**
+ *
+ * @param gl
+ * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL}
+ */
+ public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException {
+ detachRenderbufferImpl(gl, atype, false);
+ }
+
+ public final boolean isDepthStencilPackedFormat() {
+ final boolean res = null != depth && null != stencil &&
+ depth.format == stencil.format ;
+ if(res && depth.getName() != stencil.getName() ) {
+ throw new InternalError("depth/stencil packed format not sharing: depth "+depth+", stencil "+stencil);
+ }
+ return res;
+ }
+
+ private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException {
+ switch ( atype ) {
+ case DEPTH:
+ case STENCIL:
+ case DEPTH_STENCIL:
+ break;
+ default:
+ throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this);
+ }
+ if( null == depth && null == stencil ) {
+ return ; // nop
+ }
+ // reduction of possible combinations, create unique atype command(s)
+ final ArrayList<Attachment.Type> actions = new ArrayList<Attachment.Type>(2);
+ if( isDepthStencilPackedFormat() ) {
+ // packed
+ actions.add(Attachment.Type.DEPTH_STENCIL);
+ } else {
+ // individual
+ switch ( atype ) {
+ case DEPTH:
+ if( null != depth ) { actions.add(Attachment.Type.DEPTH); }
+ break;
+ case STENCIL:
+ if( null != stencil ) { actions.add(Attachment.Type.STENCIL); }
+ break;
+ case DEPTH_STENCIL:
+ if( null != depth ) { actions.add(Attachment.Type.DEPTH); }
+ if( null != stencil ) { actions.add(Attachment.Type.STENCIL); }
+ break;
+ default: // handled
+ }
+ }
+
+ bind(gl);
+
+ for(int i = 0; i < actions.size(); i++) {
+ final int format;
+
+ Attachment.Type action = actions.get(i);
+ switch ( action ) {
+ case DEPTH:
+ format = depth.format;
+ if( 0 != depth.getName() ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ }
+ depth.free(gl);
+ if(!recreate) {
+ depth = null;
+ }
+ break;
+ case STENCIL:
+ format = stencil.format;
+ if(0 != stencil.getName()) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ }
+ stencil.free(gl);
+ if(!recreate) {
+ stencil = null;
+ }
+ break;
+ case DEPTH_STENCIL:
+ format = depth.format;
+ if(0 != depth.getName()) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ }
+ depth.free(gl);
+ stencil.free(gl);
+ if(!recreate) {
+ depth = null;
+ stencil = null;
+ }
+ break;
+ default:
+ throw new InternalError("XXX");
+ }
+ if(recreate) {
+ attachRenderbufferImpl2(gl, action, format);
+ }
+ }
+ }
+
+ /**
+ * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s.
+ * <p>Leaves the FBO bound!</p>
+ * <p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
+ * </p>
+ * @param gl the current GL context
+ */
+ public final void detachAll(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.detachAll(gl);
+ }
+ detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */);
+ }
+
+ /**
+ * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s.
+ * <p>Leaves the FBO bound!</p>
+ * <p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
+ * </p>
+ * @param gl the current GL context
+ */
+ public final void detachAllColorbuffer(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.detachAllColorbuffer(gl);
+ }
+ detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */);
+ }
+
+ /**
+ * Detaches all {@link TextureAttachment}s
+ * <p>Leaves the FBO bound!</p>
+ * <p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
+ * </p>
+ * @param gl the current GL context
+ */
+ public final void detachAllTexturebuffer(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.detachAllTexturebuffer(gl);
+ }
+ for(int i=0; i<maxColorAttachments; i++) {
+ if(colorAttachmentPoints[i] instanceof TextureAttachment) {
+ detachColorbufferImpl(gl, i, false);
+ }
+ }
+ }
+
+ public final void detachAllRenderbuffer(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.detachAllRenderbuffer(gl);
+ }
+ detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, false);
+ }
+
+ private final void detachAllImpl(GL gl, boolean detachNonColorbuffer, boolean recreate) {
+ for(int i=0; i<maxColorAttachments; i++) {
+ detachColorbufferImpl(gl, i, recreate);
+ }
+ if( !recreate && colorAttachmentCount>0 ) {
+ throw new InternalError("Non zero ColorAttachments "+this);
+ }
+
+ if(detachNonColorbuffer) {
+ detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate);
+ }
+
+ if(DEBUG) {
+ System.err.println("FBObject.detachAll: [resetNonColorbuffer "+detachNonColorbuffer+", recreate "+recreate+"]: "+this);
+ }
+ }
+
+ /**
+ * @param gl the current GL context
+ */
+ public final void destroy(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.destroy(gl);
+ }
+
+ detachAllImpl(gl, true /* detachNonColorbuffer */, false /* recreate */);
+
+ // cache FB names, preset exposed to zero,
+ // braking ties w/ GL/GLContext link to getReadFramebuffer()/getWriteFramebuffer()
+ final int fb_cache = fbName;
+ fbName = 0;
+
+ int name[] = new int[1];
+ if(0!=fb_cache) {
+ name[0] = fb_cache;
+ gl.glDeleteFramebuffers(1, name, 0);
+ }
+ initialized = false;
+ bound = false;
+ if(DEBUG) {
+ System.err.println("FBObject.destroy: "+this);
+ }
+ }
+
+ private final boolean sampleSinkSizeMismatch() {
+ return samplesSink.getWidth() != width || samplesSink.getHeight() != height ;
+ }
+ private final boolean sampleSinkTexMismatch() {
+ return null == samplesSinkTexture || 0 == samplesSinkTexture.getName() ;
+ }
+ private final boolean sampleSinkDepthStencilMismatch() {
+ final boolean depthMismatch = ( null != depth && null == samplesSink.depth ) ||
+ ( null != depth && null != samplesSink.depth &&
+ depth.format != samplesSink.depth.format );
+
+ final boolean stencilMismatch = ( null != stencil && null == samplesSink.stencil ) ||
+ ( null != stencil && null != samplesSink.stencil &&
+ stencil.format != samplesSink.stencil.format );
+
+ return depthMismatch || stencilMismatch;
+ }
+
+ private final void resetMSAATexture2DSink(GL gl) throws GLException {
+ if(0 == samples) {
+ // MSAA off
+ if(null != samplesSink) {
+ samplesSink.detachAll(gl);
+ }
+ return;
+ }
+
+ boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch();
+ boolean sampleSinkTexMismatch = sampleSinkTexMismatch();
+ boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
+
+ /** if(DEBUG) {
+ System.err.println("FBObject.resetMSAATexture2DSink.0: \n\tTHIS "+this+",\n\tSINK "+samplesSink+
+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ } */
+
+ if(!sampleSinkSizeMismatch && !sampleSinkTexMismatch && !sampleSinkDepthStencilMismatch) {
+ // all properties match ..
+ return;
+ }
+
+ unbind(gl);
+
+ if(DEBUG) {
+ System.err.println("FBObject.resetMSAATexture2DSink: BEGIN\n\tTHIS "+this+",\n\tSINK "+samplesSink+
+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ }
+
+ if( sampleSinkDepthStencilMismatch ) {
+ samplesSink.detachAllRenderbuffer(gl);
+ }
+
+ if( sampleSinkSizeMismatch ) {
+ samplesSink.reset(gl, width, height);
+ }
+
+ if(null == samplesSinkTexture) {
+ samplesSinkTexture = samplesSink.attachTexture2D(gl, 0, true);
+ } else if( 0 == samplesSinkTexture.getName() ) {
+ samplesSinkTexture.setSize(width, height);
+ samplesSink.attachTexture2D(gl, 0, samplesSinkTexture);
+ }
+
+ if( sampleSinkDepthStencilMismatch ) {
+ samplesSink.attachRenderbuffer(gl, depth.format);
+ if( null != stencil && !isDepthStencilPackedFormat() ) {
+ samplesSink.attachRenderbuffer(gl, stencil.format);
+ }
+ }
+
+ sampleSinkSizeMismatch = sampleSinkSizeMismatch();
+ sampleSinkTexMismatch = sampleSinkTexMismatch();
+ sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
+ if(sampleSinkSizeMismatch || sampleSinkTexMismatch || sampleSinkDepthStencilMismatch) {
+ throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplesSink+
+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ }
+
+ if(DEBUG) {
+ System.err.println("FBObject.resetMSAATexture2DSink: END\n\tTHIS "+this+",\n\tSINK "+samplesSink+
+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ }
+ }
+
+ /**
+ * Bind this FBO, i.e. bind write framebuffer to {@link #getWriteFramebuffer()}.
+ *
+ * <p>If multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()},
+ * if full FBO is supported.</p>
+ *
+ * <p>
+ * In case you have attached more than one color buffer,
+ * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.
+ * </p>
+ * @param gl the current GL context
+ * @throws GLException
+ */
+ public final void bind(GL gl) throws GLException {
+ if(!bound || fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)) {
+ checkInitialized();
+ if(samples > 0 && fullFBOSupport) {
+ // draw to multisampling - read from samplesSink
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, getWriteFramebuffer());
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, getReadFramebuffer());
+ } else {
+ // one for all
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer());
+ }
+
+ checkNoError(null, gl.glGetError(), "FBObject post-bind"); // throws GLException if error
+ bound = true;
+ samplesSinkDirty = true;
+ }
+ }
+
+ /**
+ * Unbind this FBO, i.e. bind read and write framebuffer to default, see {@link GLBase#getDefaultDrawFramebuffer()}.
+ *
+ * <p>If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing
+ * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}</p>
+ *
+ * @param gl the current GL context
+ * @throws GLException
+ */
+ public final void unbind(GL gl) throws GLException {
+ if(bound) {
+ if(fullFBOSupport) {
+ // default read/draw buffers, may utilize GLContext/GLDrawable override of
+ // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer()
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0);
+ } else {
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer
+ }
+ checkNoError(null, gl.glGetError(), "FBObject post-unbind"); // throws GLException if error
+ bound = false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if framebuffer object is bound via {@link #bind(GL)}, otherwise <code>false</code>.
+ * <p>
+ * Method verifies the bound state via {@link GL#getBoundFramebuffer(int)}.
+ * </p>
+ * @param gl the current GL context
+ */
+ public final boolean isBound(GL gl) {
+ bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ;
+ return bound;
+ }
+
+ /** Returns <code>true</code> if framebuffer object is bound via {@link #bind(GL)}, otherwise <code>false</code>. */
+ public final boolean isBound() { return bound; }
+
+ /**
+ * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}.
+ *
+ * <p>The operation is skipped, if no multisampling is used or
+ * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)},
+ * see {@link #isSamplingBufferDirty()} </p>
+ *
+ * <p>If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing
+ * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}</p>
+ *
+ * <p>In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
+ * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()});
+ * </p>
+ *
+ * <p>Leaves the FBO unbound.</p>
+ *
+ * @param gl the current GL context
+ * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)}
+ * @throws IllegalArgumentException
+ */
+ public final void syncSamplingBuffer(GL gl) {
+ unbind(gl);
+ if(samples>0 && samplesSinkDirty) {
+ samplesSinkDirty = false;
+ resetMSAATexture2DSink(gl);
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName);
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer());
+ ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, ugly cast is OK
+ GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST);
+ if(fullFBOSupport) {
+ // default read/draw buffers, may utilize GLContext/GLDrawable override of
+ // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer()
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0);
+ } else {
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer
+ }
+ }
+ }
+
+ /**
+ * Bind the given texture colorbuffer.
+ *
+ * <p>If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called.</p>
+ *
+ * <p>Leaves the FBO unbound!</p>
+ *
+ * @param gl the current GL context
+ * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)}
+ * @throws IllegalArgumentException
+ */
+ public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException {
+ if(null == ta) { throw new IllegalArgumentException("null TextureAttachment"); }
+ if(samples > 0 && samplesSinkTexture == ta) {
+ syncSamplingBuffer(gl);
+ } else {
+ unbind(gl);
+ }
+ gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it ..
+ }
+
+ /**
+ * Unbind texture, ie bind 'non' texture 0
+ *
+ * <p>Leaves the FBO unbound.</p>
+ */
+ public final void unuse(GL gl) {
+ unbind(gl);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it
+ }
+
+ /**
+ * Returns <code>true</code> if <i>basic</i> or <i>full</i> FBO is supported, otherwise <code>false</code>.
+ * @param full <code>true</code> for <i>full</i> FBO supported query, otherwise <code>false</code> for <i>basic</i> FBO support query.
+ * @see #supportsFullFBO(GL)
+ * @see #supportsBasicFBO(GL)
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; }
+
+ /**
+ * Returns <code>true</code> if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise <code>false</code>.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsRGBA8() throws GLException { checkInitialized(); return rgba8Avail; }
+
+ /**
+ * Returns <code>true</code> if {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} is supported, otherwise <code>false</code>.
+ * @param bits 16, 24 or 32 bits
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsDepth(int bits) throws GLException {
+ checkInitialized();
+ switch(bits) {
+ case 16: return basicFBOSupport;
+ case 24: return depth24Avail;
+ case 32: return depth32Avail;
+ default: return false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} or {@link GL2GL3#GL_STENCIL_INDEX16} is supported, otherwise <code>false</code>.
+ * @param bits 1, 4, 8 or 16 bits
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsStencil(int bits) throws GLException {
+ checkInitialized();
+ switch(bits) {
+ case 1: return stencil01Avail;
+ case 4: return stencil04Avail;
+ case 8: return stencil08Avail;
+ case 16: return stencil16Avail;
+ default: return false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if {@link GL#GL_DEPTH24_STENCIL8} is supported, otherwise <code>false</code>.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsPackedDepthStencil() throws GLException { checkInitialized(); return packedDepthStencilAvail; }
+
+ /**
+ * Returns the maximum number of colorbuffer attachments.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; }
+
+ /**
+ * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; }
+
+ /**
+ * Returns <code>true</code> if this instance has been initialized with {@link #reset(GL, int, int)}
+ * or {@link #reset(GL, int, int, int)}, otherwise <code>false</code>
+ */
+ public final boolean isInitialized() { return initialized; }
+ /** Returns the width */
+ public final int getWidth() { return width; }
+ /** Returns the height */
+ public final int getHeight() { return height; }
+ /** Returns the number of samples for multisampling (MSAA). zero if no multisampling is used. */
+ public final int getNumSamples() { return samples; }
+ /** Returns the framebuffer name to render to. */
+ public final int getWriteFramebuffer() { return fbName; }
+ /** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */
+ public final int getReadFramebuffer() { return ( samples > 0 ) ? samplesSink.getReadFramebuffer() : fbName; }
+ /** Return the number of color/texture attachments */
+ public final int getColorAttachmentCount() { return colorAttachmentCount; }
+ /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */
+ public final RenderAttachment getStencilAttachment() { return stencil; }
+ /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */
+ public final RenderAttachment getDepthAttachment() { return depth; }
+
+ /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */
+ public final FBObject getSamplingSinkFBO() { return samplesSink; }
+
+ /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */
+ public final TextureAttachment getSamplingSink() { return samplesSinkTexture; }
+ /**
+ * Returns <code>true</code> if the multisampling colorbuffer (msaa-buffer)
+ * has been flagged dirty by a previous call of {@link #bind(GL)},
+ * otherwise <code>false</code>.
+ */
+ public final boolean isSamplingBufferDirty() { return samplesSinkDirty; }
+
+ int objectHashCode() { return super.hashCode(); }
+
+ public final String toString() {
+ final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ;
+ return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+", samples "+samples+"/"+maxSamples+
+ ", depth "+depth+", stencil "+stencil+", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+
+ ": "+caps+", msaa-sink "+samplesSinkTexture+", isSamplesSink "+(null == samplesSink)+
+ ", obj 0x"+Integer.toHexString(objectHashCode())+"]";
+ }
+
+ private final void updateStatus(GL gl) {
+ if( 0 == fbName ) {
+ vStatus = -1;
+ } else {
+ vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
new file mode 100644
index 000000000..f7e25fa01
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+/**
+ * Class holding OpenGL extension strings, commonly used by JOGL's implementation.
+ */
+public class GLExtensions {
+ public static final String VERSION_1_2 = "GL_VERSION_1_2";
+ public static final String VERSION_1_4 = "GL_VERSION_1_4";
+ public static final String VERSION_1_5 = "GL_VERSION_1_5";
+ public static final String VERSION_2_0 = "GL_VERSION_2_0";
+
+ public static final String ARB_debug_output = "GL_ARB_debug_output";
+ public static final String AMD_debug_output = "GL_AMD_debug_output";
+
+ public static final String ARB_framebuffer_object = "GL_ARB_framebuffer_object";
+ public static final String OES_framebuffer_object = "GL_OES_framebuffer_object";
+ public static final String EXT_framebuffer_object = "GL_EXT_framebuffer_object";
+ public static final String EXT_framebuffer_blit = "GL_EXT_framebuffer_blit";
+ public static final String EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample";
+ public static final String EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil";
+ public static final String OES_depth24 = "GL_OES_depth24";
+ public static final String OES_depth32 = "GL_OES_depth32";
+ public static final String OES_packed_depth_stencil = "GL_OES_packed_depth_stencil";
+ public static final String NV_fbo_color_attachments = "GL_NV_fbo_color_attachments";
+
+ public static final String ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
+
+ public static final String EXT_abgr = "GL_EXT_abgr";
+ public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8";
+ public static final String OES_stencil1 = "GL_OES_stencil1";
+ public static final String OES_stencil4 = "GL_OES_stencil4";
+ public static final String OES_stencil8 = "GL_OES_stencil8";
+ public static final String APPLE_float_pixels = "GL_APPLE_float_pixels";
+
+ public static final String ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
+ public static final String ARB_texture_rectangle = "GL_ARB_texture_rectangle";
+ public static final String EXT_texture_rectangle = "GL_EXT_texture_rectangle";
+ public static final String NV_texture_rectangle = "GL_NV_texture_rectangle";
+ public static final String EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888";
+ public static final String IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888";
+ public static final String EXT_texture_compression_s3tc = "GL_EXT_texture_compression_s3tc";
+ public static final String NV_texture_compression_vtc = "GL_NV_texture_compression_vtc";
+ public static final String SGIS_generate_mipmap = "GL_SGIS_generate_mipmap";
+ public static final String OES_read_format = "GL_OES_read_format";
+
+ public static final String OES_EGL_image_external = "GL_OES_EGL_image_external";
+
+ //
+ // Aliased GLX/WGL/.. extensions
+ //
+
+ public static final String ARB_pixel_format = "GL_ARB_pixel_format";
+ public static final String ARB_pbuffer = "GL_ARB_pbuffer";
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 75785fd86..cdb4b82bb 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -93,11 +93,13 @@ public class JoglVersion extends JogampVersion {
return sb;
}
- public static StringBuilder getDefaultOpenGLInfo(StringBuilder sb, boolean withCapabilitiesInfo) {
+ public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, boolean withCapabilitiesInfo) {
if(null==sb) {
sb = new StringBuilder();
}
- final AbstractGraphicsDevice device = GLProfile.getDefaultDevice();
+ if(null == device) {
+ device = GLProfile.getDefaultDevice();
+ }
sb.append("Default Profiles on device ").append(device).append(Platform.getNewline());
if(null!=device) {
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
@@ -120,13 +122,21 @@ public class JoglVersion extends JogampVersion {
if(null==sb) {
sb = new StringBuilder();
}
- GLContext ctx = gl.getContext();
-
+
sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline());
sb.append(device.getClass().getSimpleName()).append("[type ")
.append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ").append(Platform.getNewline());
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
sb.append(Platform.getNewline());
+
+ return getGLStrings(gl, sb);
+ }
+
+ public static StringBuilder getGLStrings(GL gl, StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ final GLContext ctx = gl.getContext();
sb.append("Swap Interval ").append(gl.getSwapInterval());
sb.append(Platform.getNewline());
sb.append("GL Profile ").append(gl.getGLProfile());
diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java
new file mode 100644
index 000000000..8450ffdb0
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.opengl.GLAutoDrawableDelegate;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+
+import jogamp.opengl.GLFBODrawableImpl;
+
+/**
+ * Platform-independent class exposing FBO offscreen functionality to
+ * applications.
+ * <p>
+ * This class distinguishes itself from {@link GLAutoDrawableDelegate}
+ * with it's {@link #setSize(int, int)} functionality.
+ * </p>
+ */
+public class OffscreenAutoDrawable extends GLAutoDrawableDelegate {
+
+ /**
+ * @param drawable a valid {@link GLDrawable}, may not be realized yet.
+ * @param context a valid {@link GLContext}, may not be made current (created) yet.
+ * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass <code>false</code>. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ */
+ public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, boolean ownDevice) {
+ super(drawable, context, null, ownDevice);
+ }
+
+ /**
+ * Attempts to resize this offscreen auto drawable, if supported
+ * by the underlying {@link GLDrawable).
+ * @param newWidth
+ * @param newHeight
+ * @return <code>true</code> if resize was executed, otherwise <code>false</code>.
+ * @throws GLException in case of an error during the resize operation
+ */
+ public boolean setSize(int newWidth, int newHeight) throws GLException {
+ boolean done = false;
+ if(drawable instanceof GLFBODrawableImpl) {
+ context.makeCurrent();
+ try {
+ ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight);
+ done = true;
+ } finally {
+ context.release();
+ }
+ }
+ if(done) {
+ this.defaultWindowResizedOp();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * If the underlying {@link GLDrawable} is an FBO implementation
+ * and contains an {#link FBObject}, the same is returned.
+ * Otherwise returns <code>null</code>.
+ */
+ public FBObject getFBObject() {
+ if(drawable instanceof GLFBODrawableImpl) {
+ return ((GLFBODrawableImpl)drawable).getFBObject();
+ }
+ return null;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 5ee58b78d..8d237162c 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -45,6 +45,7 @@ import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
import javax.media.opengl.Threading;
+import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
@@ -63,27 +64,19 @@ import org.eclipse.swt.widgets.Shell;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.JoglVersion;
/**
* Native SWT Canvas implementing GLAutoDrawable
- * <p>
- * FIXME: If this instance runs in multithreading mode, see {@link Threading#isSingleThreaded()} (impossible),
- * proper recursive locking is required for drawable/context @ destroy and display.
- * Recreation etc could pull those instances while animating!
- * Simply locking before using drawable/context offthread
- * would allow a deadlock situation!
- * </p>
- * <p>
- * NOTE: [MT-0] Methods utilizing [volatile] drawable/context are not synchronized.
- In case any of the methods are called outside of a locked state
- extra care should be added. Maybe we shall expose locking facilities to the user.
- However, since the user shall stick to the GLEventListener model while utilizing
- GLAutoDrawable implementations, she is safe due to the implicit locked state.
- * </p>
+ *
+ * <p>Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.</p>
+ *
*/
public class GLCanvas extends Canvas implements GLAutoDrawable {
+ private static final boolean DEBUG = Debug.debug("GLCanvas");
/*
* Flag for whether the SWT thread should be used for OpenGL calls when in single-threaded mode. This is controlled
@@ -97,22 +90,25 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
//private static final boolean useSWTThread = ThreadingImpl.getMode() != ThreadingImpl.WORKER;
/* GL Stuff */
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
private final GLDrawableHelper helper = new GLDrawableHelper();
- private volatile GLDrawable drawable; // volatile avoids locking all accessors. FIXME still need to sync destroy/display
+
+ private final GLContext shareWith;
+ private final GLCapabilitiesImmutable capsRequested;
+ private final GLCapabilitiesChooser capsChooser;
+
+ private volatile GLDrawable drawable; // volatile: avoid locking for read-only access
private GLContext context;
/* Native window surface */
private AbstractGraphicsDevice device;
- private final long nativeWindowHandle;
- private final ProxySurface proxySurface;
/* Construction parameters stored for GLAutoDrawable accessor methods */
private int additionalCtxCreationFlags = 0;
- private final GLCapabilitiesImmutable glCapsRequested;
/* Flag indicating whether an unprocessed reshape is pending. */
- private volatile boolean sendReshape;
+ private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking
/*
* Invokes init(...) on all GLEventListeners. Assumes context is current when run.
@@ -141,10 +137,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
};
/* Action to make specified context current prior to running displayAction */
- private final Runnable makeCurrentAndDisplayAction = new Runnable() {
+ private final Runnable makeCurrentAndDisplayOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.invokeGL(drawable, context, displayAction, initAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ helper.invokeGL(drawable, context, displayAction, initAction);
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -157,10 +159,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
};
/* Swaps buffers, making the GLContext current first */
- private final Runnable makeCurrentAndSwapBuffersAction = new Runnable() {
+ private final Runnable makeCurrentAndSwapBuffersOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -181,16 +189,33 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
private final Runnable disposeOnEDTGLAction = new Runnable() {
@Override
public void run() {
- helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction);
- }
- };
-
- private final Runnable disposeGraphicsDeviceAction = new Runnable() {
- @Override
- public void run() {
- if (null != device) {
- device.close();
- device = null;
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if (null != drawable && null != context) {
+ boolean animatorPaused = false;
+ final GLAnimatorControl animator = getAnimator();
+ if (null != animator) {
+ animatorPaused = animator.pause();
+ }
+
+ if(context.isCreated()) {
+ helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction);
+ }
+
+ if (animatorPaused) {
+ animator.resume();
+ }
+ }
+ // SWT is owner of the device handle, not us.
+ // Hence close() operation is a NOP.
+ if (null != device) {
+ device.close();
+ device = null;
+ }
+ SWTAccessor.setRealized(GLCanvas.this, false); // unrealize ..
+ } finally {
+ _lock.unlock();
}
}
};
@@ -200,6 +225,37 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
*/
private volatile Rectangle clientArea;
+ /**
+ * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)}
+ * on the SWT thread.
+ *
+ * @param parent
+ * Required (non-null) parent Composite.
+ * @param style
+ * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
+ * Canvas constructor, so OpenGL handles the background.
+ * @param caps
+ * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
+ * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
+ * actually used may differ based on the capabilities of the graphics device.
+ * @param chooser
+ * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
+ * requested GLCapabilities, and the available capabilities of the graphics device.
+ * @param shareWith
+ * Optional GLContext to share state (textures, vbos, shaders, etc.) with.
+ * @return a new instance
+ */
+ public static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps,
+ final GLCapabilitiesChooser chooser, final GLContext shareWith) {
+ final GLCanvas[] res = new GLCanvas[] { null };
+ parent.getDisplay().syncExec(new Runnable() {
+ public void run() {
+ res[0] = new GLCanvas( parent, style, caps, chooser, shareWith );
+ }
+ });
+ return res[0];
+ }
+
/**
* Creates a new SWT GLCanvas.
*
@@ -229,35 +285,29 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
clientArea = GLCanvas.this.getClientArea();
- /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite) */
+ /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
+ * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
device = SWTAccessor.getDevice(this);
- /* Native handle for the control, used to associate with GLContext */
- nativeWindowHandle = SWTAccessor.getWindowHandle(this);
/* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */
if(null == caps) {
caps = new GLCapabilities(GLProfile.getDefault(device));
}
- glCapsRequested = caps;
-
- final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile());
-
- /* Create a NativeWindow proxy for the SWT canvas */
- proxySurface = glFactory.createProxySurface(device, nativeWindowHandle, caps, chooser);
-
- /* Associate a GL surface with the proxy */
- drawable = glFactory.createGLDrawable(proxySurface);
- drawable.setRealized(true);
-
- context = drawable.createContext(shareWith);
-
+ this.capsRequested = caps;
+ this.capsChooser = chooser;
+ this.shareWith = shareWith;
+
+ // post create .. when ready
+ drawable = null;
+ context = null;
+
/* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
/* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
addPaintListener(new PaintListener() {
@Override
public void paintControl(final PaintEvent arg0) {
- if (!helper.isExternalAnimatorAnimating()) {
- display();
+ if ( !helper.isExternalAnimatorAnimating() ) {
+ display(); // checks: null != drawable
}
}
});
@@ -265,12 +315,112 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
addControlListener(new ControlAdapter() {
@Override
public void controlResized(final ControlEvent arg0) {
- clientArea = GLCanvas.this.getClientArea();
- /* Mark for OpenGL reshape next time the control is painted */
- sendReshape = true;
+ updateSizeCheck();
}
});
}
+ private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final void destroy(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return clientArea.width;
+ }
+
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return clientArea.height;
+ }
+
+ @Override
+ public String toString() {
+ return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]";
+ }
+ };
+
+ protected final void updateSizeCheck() {
+ final Rectangle oClientArea = clientArea;
+ final Rectangle nClientArea = GLCanvas.this.getClientArea();
+ if ( nClientArea != null &&
+ ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
+ ) {
+ clientArea = nClientArea; // write back new value
+ sendReshape = true; // Mark for OpenGL reshape next time the control is painted
+ }
+ }
+
+ @Override
+ public void display() {
+ if( null != drawable || validateDrawableAndContext() ) {
+ runInGLThread(makeCurrentAndDisplayOnEDTAction);
+ }
+ }
+
+
+ /** assumes drawable == null ! */
+ protected final boolean validateDrawableAndContext() {
+ if( GLCanvas.this.isDisposed() ) {
+ return false;
+ }
+ final Rectangle nClientArea = clientArea;
+ if(0 == nClientArea.width * nClientArea.height) {
+ return false;
+ }
+
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
+
+ /* Native handle for the control, used to associate with GLContext */
+ final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+
+ /* Create a NativeWindow proxy for the SWT canvas */
+ ProxySurface proxySurface = null;
+ try {
+ proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle,
+ capsRequested, capsChooser, swtCanvasUpStreamHook);
+ } catch (GLException gle) {
+ // not ready yet ..
+ if(DEBUG) { System.err.println(gle.getMessage()); }
+ }
+
+ if(null != proxySurface) {
+ /* Associate a GL surface with the proxy */
+ drawable = glFactory.createGLDrawable(proxySurface);
+ drawable.setRealized(true);
+
+ context = drawable.createContext(shareWith);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ final boolean res = null != drawable;
+ if(DEBUG && res) {
+ System.err.println("SWT GLCanvas realized! "+this+", "+drawable);
+ Thread.dumpStack();
+ }
+ return res;
+ }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
+ public int getWidth() {
+ return clientArea.width;
+ }
+
+ @Override
+ public int getHeight() {
+ return clientArea.height;
+ }
@Override
public void addGLEventListener(final GLEventListener arg0) {
@@ -296,11 +446,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
@Override
- public void display() {
- runInGLThread(makeCurrentAndDisplayAction);
- }
-
- @Override
public GLAnimatorControl getAnimator() {
return helper.getAnimator();
}
@@ -312,7 +457,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLContext getContext() {
- return context;
+ return null != drawable ? context : null;
}
@Override
@@ -322,7 +467,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GL getGL() {
- return (null == context) ? null : context.getGL();
+ final GLContext _context = context;
+ return (null == _context) ? null : _context.getGL();
}
@Override
@@ -352,27 +498,35 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLContext setContext(GLContext newCtx) {
- final GLContext oldCtx = context;
- final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
- context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLContext oldCtx = context;
+ final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ context=(GLContextImpl)newCtx;
+ if(newCtxCurrent) {
+ context.makeCurrent();
+ }
+ return oldCtx;
+ } finally {
+ _lock.unlock();
}
- return oldCtx;
}
@Override
public void setContextCreationFlags(final int arg0) {
additionalCtxCreationFlags = arg0;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
+ final GLContext _context = context;
+ if(null != _context) {
+ _context.setContextCreationFlags(additionalCtxCreationFlags);
}
}
@Override
public GL setGL(final GL arg0) {
- if (null != context) {
- context.setGL(arg0);
+ final GLContext _context = context;
+ if (null != _context) {
+ _context.setGL(arg0);
return arg0;
}
return null;
@@ -380,17 +534,24 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLContext createContext(final GLContext shareWith) {
- if(drawable != null) {
- final GLContext _ctx = drawable.createContext(shareWith);
- _ctx.setContextCreationFlags(additionalCtxCreationFlags);
- return _ctx;
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if(drawable != null) {
+ final GLContext _ctx = drawable.createContext(shareWith);
+ _ctx.setContextCreationFlags(additionalCtxCreationFlags);
+ return _ctx;
+ }
+ return null;
+ } finally {
+ _lock.unlock();
}
- return null;
}
@Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
- return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getChosenCapabilities();
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getChosenGLCapabilities() : null;
}
/**
@@ -399,46 +560,37 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @return Non-null GLCapabilities.
*/
public GLCapabilitiesImmutable getRequestedGLCapabilities() {
- return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getRequestedCapabilities();
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities() : null;
}
@Override
public GLDrawableFactory getFactory() {
- return (drawable != null) ? drawable.getFactory() : null;
+ final GLDrawable _drawable = drawable;
+ return (_drawable != null) ? _drawable.getFactory() : null;
}
@Override
public GLProfile getGLProfile() {
- return glCapsRequested.getGLProfile();
+ return capsRequested.getGLProfile();
}
@Override
public long getHandle() {
- return (drawable != null) ? drawable.getHandle() : 0;
- }
-
- @Override
- public int getHeight() {
- final Rectangle clientArea = this.clientArea;
- if (clientArea == null) return 0;
- return clientArea.height;
+ final GLDrawable _drawable = drawable;
+ return (_drawable != null) ? _drawable.getHandle() : 0;
}
@Override
public NativeSurface getNativeSurface() {
- return (drawable != null) ? drawable.getNativeSurface() : null;
- }
-
- @Override
- public int getWidth() {
- final Rectangle clientArea = this.clientArea;
- if (clientArea == null) return 0;
- return clientArea.width;
+ final GLDrawable _drawable = drawable;
+ return (_drawable != null) ? _drawable.getNativeSurface() : null;
}
@Override
public boolean isRealized() {
- return (drawable != null) ? drawable.isRealized() : false;
+ final GLDrawable _drawable = drawable;
+ return (_drawable != null) ? _drawable.isRealized() : false;
}
@Override
@@ -448,41 +600,18 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public void swapBuffers() throws GLException {
- runInGLThread(makeCurrentAndSwapBuffersAction);
+ runInGLThread(makeCurrentAndSwapBuffersOnEDTAction);
}
- // FIXME: API of update() method ?
@Override
public void update() {
- // FIXME: display();
+ // don't paint background etc .. nop avoids flickering
}
@Override
public void dispose() {
- if (null != drawable && null != context) { // drawable is volatile!
- boolean animatorPaused = false;
- final GLAnimatorControl animator = getAnimator();
- if (null != animator) {
- // can't remove us from animator for recreational addNotify()
- animatorPaused = animator.pause();
- }
-
- if(context.isCreated()) {
- runInGLThread(disposeOnEDTGLAction);
- }
-
- if (animatorPaused) {
- animator.resume();
- }
- }
- final Display display = getDisplay();
-
- if (display.getThread() == Thread.currentThread()) {
- disposeGraphicsDeviceAction.run();
- } else {
- display.syncExec(disposeGraphicsDeviceAction);
- }
- super.dispose();
+ runInGLThread(disposeOnEDTGLAction);
+ super.dispose();
}
/**
@@ -501,7 +630,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @see Platform#AWT_AVAILABLE
* @see Platform#getOSType()
*/
- private void runInGLThread(final Runnable action) {
+ private static void runInGLThread(final Runnable action) {
if(Platform.OSType.MACOS == Platform.OS_TYPE) {
SWTAccessor.invoke(true, action);
} else {
@@ -515,7 +644,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
final Display display = new Display();
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java
deleted file mode 100644
index 3e049a334..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2011 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package com.jogamp.opengl.util;
-
-import javax.media.opengl.*;
-
-public class FBObject {
- static final int MAX_FBO_TEXTURES = 32; // just for our impl .. not the real 'max' FBO color attachments
- private int[] fbo_tex_names;
- private int[] fbo_tex_units;
- private int fbo_tex_num;
- private int colorattachment_num;
-
- private boolean initialized;
- private int width, height;
- private int fb, depth_rb, stencil_rb, vStatus;
- private boolean bound;
-
- public FBObject(int width, int height) {
- this.fbo_tex_names = new int[MAX_FBO_TEXTURES];
- this.fbo_tex_units = new int[MAX_FBO_TEXTURES];
- this.fbo_tex_num = 0;
- this.colorattachment_num = 0;
- this.initialized = false;
- this.width = width;
- this.height = height;
- this.fb = 0;
- this.depth_rb = 0;
- this.stencil_rb = 0;
- this.bound = false;
- }
-
- /**
- * @return true if the FB status is valid, otherwise false
- * @see #getStatus()
- */
- public boolean isStatusValid() {
- switch(vStatus) {
- case GL.GL_FRAMEBUFFER_COMPLETE:
- return true;
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:
- case 0:
- default:
- System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) +
- " : " + getStatusString(vStatus));
- return false;
- }
- }
-
- /**
- * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1
- * @see #validateStatus()
- */
- public int getStatus() {
- return vStatus;
- }
-
- public String getStatusString() {
- return getStatusString(vStatus);
- }
-
- public static final String getStatusString(int fbStatus) {
- switch(fbStatus) {
- case -1:
- return "NOT A FBO";
- case GL.GL_FRAMEBUFFER_COMPLETE:
- return "OK";
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- return("GL FBO: Unsupported framebuffer format");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- return("GL FBO: incomplete, incomplete attachment\n");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- return("GL FBO: incomplete, missing attachment");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- return("GL FBO: incomplete, attached images must have same dimensions");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- return("GL FBO: incomplete, attached images must have same format");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- return("GL FBO: incomplete, missing draw buffer");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- return("GL FBO: incomplete, missing read buffer");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- return("GL FBO: incomplete, missing multisample buffer");
- case 0:
- return("GL FBO: incomplete, implementation fault");
- default:
- return("GL FBO: incomplete, implementation ERROR");
- }
- }
-
- private boolean checkNoError(GL gl, int err, String exceptionMessage) {
- if(GL.GL_NO_ERROR != err) {
- if(null != gl) {
- destroy(gl);
- }
- if(null != exceptionMessage) {
- throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err));
- }
- return false;
- }
- return true;
- }
-
- private final void checkInitialized() {
- if(!initialized) {
- throw new GLException("FBO not initialized, call init(GL) first.");
- }
- }
-
- private final void checkBound(GL gl, boolean shallBeBound) {
- checkInitialized();
- if(bound != shallBeBound) {
- final String s0 = shallBeBound ? "not" : "already" ;
- throw new GLException("FBO "+s0+" bound "+toString());
- }
- checkNoError(null, gl.glGetError(), "FBObject pre"); // throws GLException if error
- }
-
- /**
- * Initializes this FBO's instance with it's texture.
- *
- * <p>Leaves the FBO bound!</p>
- *
- * @param gl the current GL context
- * @throws GLException in case of an error
- */
- public void init(GL gl) throws GLException {
- if(initialized) {
- throw new GLException("FBO already initialized");
- }
- checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error
-
- // generate fbo ..
- int name[] = new int[1];
-
- gl.glGenFramebuffers(1, name, 0);
- fb = name[0];
- if(fb==0) {
- throw new GLException("null generated framebuffer");
- }
-
- // bind fbo ..
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb);
- checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error
- if(!gl.glIsFramebuffer(fb)) {
- checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
- }
- bound = true;
- initialized = true;
-
- updateStatus(gl);
- }
-
- /**
- * Attaches a[nother] Texture2D Color Buffer to this FBO's instance,
- * selecting the texture data type and format automatically.
- * <p>This may be done as many times as many color attachments are supported,
- * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.</p>
- *
- * <p>Assumes a bound FBO</p>
- * <p>Leaves the FBO bound!</p>
- *
- * @param gl the current GL context
- * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)}
- * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
- * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
- * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
- * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
- * @return idx of the new attached texture, otherwise -1
- * @throws GLException in case of an error
- */
- public int attachTexture2D(GL gl, int texUnit, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
- final int textureInternalFormat, textureDataFormat, textureDataType;
- if(gl.isGLES()) {
- textureInternalFormat=GL.GL_RGBA;
- textureDataFormat=GL.GL_RGBA;
- textureDataType=GL.GL_UNSIGNED_BYTE;
- } else {
- textureInternalFormat=GL.GL_RGBA8;
- textureDataFormat=GL.GL_BGRA;
- textureDataType=GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
- }
- return attachTexture2D(gl, texUnit, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
- }
-
- /**
- * Attaches a[nother] Texture2D Color Buffer to this FBO's instance,
- * selecting the texture data type and format automatically.
- * <p>This may be done as many times as many color attachments are supported,
- * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.</p>
- *
- * <p>Assumes a bound FBO</p>
- * <p>Leaves the FBO bound!</p>
- *
- * @param gl the current GL context
- * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)}
- * @param textureInternalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
- * @param textureDataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
- * @param textureDataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
- * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
- * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
- * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
- * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
- * @return index of the texture colorbuffer if bound and configured successfully, otherwise -1
- * @throws GLException in case the texture colorbuffer couldn't be allocated
- */
- public int attachTexture2D(GL gl, int texUnit,
- int textureInternalFormat, int textureDataFormat, int textureDataType,
- int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
- checkBound(gl, true);
- final int fbo_tex_idx = fbo_tex_num;
- gl.glGenTextures(1, fbo_tex_names, fbo_tex_num);
- if(fbo_tex_names[fbo_tex_idx]==0) {
- throw new GLException("null generated texture");
- }
- fbo_tex_units[fbo_tex_idx] = texUnit;
- fbo_tex_num++;
- if(0<=texUnit) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
- }
- gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx]);
- checkNoError(gl, gl.glGetError(), "FBObject Init.bindTex"); // throws GLException if error
- gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, textureInternalFormat, width, height, 0,
- textureDataFormat, textureDataType, null);
- int glerr = gl.glGetError();
- if(GL.GL_NO_ERROR != glerr) {
- int[] sz = new int[1];
- gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0);
- // throws GLException if error
- checkNoError(gl, glerr, "FBObject Init.texImage2D: "+
- " int-fmt 0x"+Integer.toHexString(textureInternalFormat)+
- ", "+width+"x"+height+
- ", data-fmt 0x"+Integer.toHexString(textureDataFormat)+
- ", data-type 0x"+Integer.toHexString(textureDataType)+
- ", max tex-sz "+sz[0]);
- }
- if( 0 < magFilter ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter);
- }
- if( 0 < minFilter ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter);
- }
- if( 0 < wrapS ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS);
- }
- if( 0 < wrapT ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
- }
-
- // Set up the color buffer for use as a renderable texture:
- gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
- GL.GL_COLOR_ATTACHMENT0 + colorattachment_num++,
- GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx], 0);
-
- updateStatus(gl);
- return isStatusValid() ? fbo_tex_idx : -1;
- }
-
- /**
- * Attaches one Depth Buffer to this FBO's instance.
- * <p>This may be done only one time.</p>
- *
- * <p>Assumes a bound FBO</p>
- * <p>Leaves the FBO bound!</p>
- * @param gl the current GL context
- * @param depthComponentType {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32}
- * @return true if the depth renderbuffer could be bound and configured, otherwise false
- * @throws GLException in case the depth renderbuffer couldn't be allocated or one is already attached.
- */
- public boolean attachDepthBuffer(GL gl, int depthComponentType) throws GLException {
- checkBound(gl, true);
- if(depth_rb != 0) {
- throw new GLException("FBO depth buffer already attached (rb "+depth_rb+")");
- }
- int name[] = new int[1];
- gl.glGenRenderbuffers(1, name, 0);
- depth_rb = name[0];
- if(depth_rb==0) {
- throw new GLException("null generated renderbuffer");
- }
- // Initialize the depth buffer:
- gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb);
- if(!gl.glIsRenderbuffer(depth_rb)) {
- System.err.println("not a depthbuffer: "+ depth_rb);
- name[0] = depth_rb;
- gl.glDeleteRenderbuffers(1, name, 0);
- depth_rb=0;
- return false;
- }
-
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, depthComponentType, width, height);
- // Set up the depth buffer attachment:
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
- GL.GL_DEPTH_ATTACHMENT,
- GL.GL_RENDERBUFFER, depth_rb);
- updateStatus(gl);
- return isStatusValid();
- }
-
- /**
- * Attaches one Stencil Buffer to this FBO's instance.
- * <p>This may be done only one time.</p>
- *
- * <p>Assumes a bound FBO</p>
- * <p>Leaves the FBO bound!</p>
- * @param gl the current GL context
- * @param stencilComponentType {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4} or {@link GL#GL_STENCIL_INDEX8}
- * @return true if the stencil renderbuffer could be bound and configured, otherwise false
- * @throws GLException in case the stencil renderbuffer couldn't be allocated or one is already attached.
- */
- public boolean attachStencilBuffer(GL gl, int stencilComponentType) throws GLException {
- checkBound(gl, true);
- if(stencil_rb != 0) {
- throw new GLException("FBO stencil buffer already attached (rb "+stencil_rb+")");
- }
- int name[] = new int[1];
- gl.glGenRenderbuffers(1, name, 0);
- stencil_rb = name[0];
- if(stencil_rb==0) {
- throw new GLException("null generated stencilbuffer");
- }
- // Initialize the stencil buffer:
- gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, stencil_rb);
- if(!gl.glIsRenderbuffer(stencil_rb)) {
- System.err.println("not a stencilbuffer: "+ stencil_rb);
- name[0] = stencil_rb;
- gl.glDeleteRenderbuffers(1, name, 0);
- stencil_rb=0;
- return false;
- }
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, stencilComponentType, width, height);
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
- GL.GL_STENCIL_ATTACHMENT,
- GL.GL_RENDERBUFFER, stencil_rb);
- updateStatus(gl);
- return isStatusValid();
- }
-
- /**
- * @param gl the current GL context
- */
- public void destroy(GL gl) {
- if(bound) {
- unbind(gl);
- }
-
- int name[] = new int[1];
-
- if(0!=stencil_rb) {
- name[0] = stencil_rb;
- gl.glDeleteRenderbuffers(1, name, 0);
- stencil_rb = 0;
- }
- if(0!=depth_rb) {
- name[0] = depth_rb;
- gl.glDeleteRenderbuffers(1, name, 0);
- depth_rb=0;
- }
- if(null!=fbo_tex_names && fbo_tex_num>0) {
- gl.glDeleteTextures(1, fbo_tex_names, fbo_tex_num);
- fbo_tex_names = new int[MAX_FBO_TEXTURES];
- fbo_tex_units = new int[MAX_FBO_TEXTURES];
- fbo_tex_num = 0;
- }
- colorattachment_num = 0;
- if(0!=fb) {
- name[0] = fb;
- gl.glDeleteFramebuffers(1, name, 0);
- fb = 0;
- }
- initialized = false;
- }
-
- /**
- * Bind this FBO
- * <p>In case you have attached more than one color buffer,
- * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.</p>
- * @param gl the current GL context
- */
- public void bind(GL gl) {
- checkBound(gl, false);
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb);
- bound = true;
- }
-
- /**
- * Unbind FBO, ie bind 'non' FBO 0
- * @param gl the current GL context
- */
- public void unbind(GL gl) {
- checkBound(gl, true);
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
- bound = false;
- }
-
- /**
- * Bind the texture with given index.
- *
- * <p>If a valid texture unit was named via {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)},
- * the unit is activated via {@link GL#glActiveTexture(int) glActiveTexture(GL.GL_TEXTURE0 + unit)}.</p>
- * @param gl the current GL context
- * @param texIdx index of the texture to use, prev. attached w/ {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)}
- */
- public void use(GL gl, int texIdx) {
- checkBound(gl, false);
- if(texIdx >= fbo_tex_num) {
- throw new GLException("Invalid texId, only "+fbo_tex_num+" textures are attached");
- }
- if(0<=fbo_tex_units[texIdx]) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + fbo_tex_units[texIdx]);
- }
- gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[texIdx]); // use it ..
- }
-
- /** Unbind texture, ie bind 'non' texture 0 */
- public void unuse(GL gl) {
- checkBound(gl, false);
- gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it
- }
-
- public final boolean isBound() { return bound; }
- public final int getWidth() { return width; }
- public final int getHeight() { return height; }
- public final int getFBName() { return fb; }
- public final int getTextureNumber() { return fbo_tex_num; }
- public final int getTextureName(int idx) { return fbo_tex_names[idx]; }
-
- /** @return the named texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit was desired. */
- public final int getTextureUnit(int idx) { return fbo_tex_units[idx]; }
- public final int getColorAttachmentNumber() { return colorattachment_num; }
- public final int getStencilBuffer() { return stencil_rb; }
- public final int getDepthBuffer() { return depth_rb; }
- public final String toString() {
- return "FBO[name "+fb+", size "+width+"x"+height+", color num "+colorattachment_num+", tex num "+fbo_tex_num+", depth "+depth_rb+", stencil "+stencil_rb+"]";
- }
-
- private void updateStatus(GL gl) {
- if(!gl.glIsFramebuffer(fb)) {
- vStatus = -1;
- } else {
- vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
- }
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
index 8401b9cd2..331d6fa4e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
@@ -39,6 +39,7 @@
package com.jogamp.opengl.util;
import com.jogamp.common.nio.Buffers;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
@@ -56,22 +57,32 @@ import java.nio.*;
public class GLBuffers extends Buffers {
/**
- * @param glType shall be one of
- * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
- * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
- * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
- * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
- * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
- * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
- * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
- * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
- * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
- * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27)
+ * @param glType shall be one of (29) <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL.GL_HALF_FLOAT, GLES2.GL_HALF_FLOAT_OES: <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
+ *
* @return -1 if glType is unhandled, otherwise the actual value > 0
*/
public static final int sizeOfGLType(int glType) {
- switch (glType) { // 25
+ switch (glType) { // 29
+ // case GL2.GL_BITMAP:
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
@@ -86,6 +97,8 @@ public class GLBuffers extends Buffers {
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL.GL_HALF_FLOAT:
+ case GLES2.GL_HALF_FLOAT_OES:
return SIZEOF_SHORT;
case GL.GL_FIXED:
@@ -108,29 +121,38 @@ public class GLBuffers extends Buffers {
case GL.GL_FLOAT:
return SIZEOF_FLOAT;
- case GL2.GL_DOUBLE:
+ case GL2GL3.GL_DOUBLE:
return SIZEOF_DOUBLE;
}
return -1;
}
/**
- * @param glType shall be one of
- * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
- * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
- * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
- * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
- * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
- * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
- * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
- * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
- * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
- * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27)
+ * @param glType shall be one of (29) <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
+ *
* @return null if glType is unhandled, otherwise the new Buffer object
*/
public static final Buffer newDirectGLBuffer(int glType, int numElements) {
- switch (glType) {
+ switch (glType) { // 29
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
@@ -145,6 +167,8 @@ public class GLBuffers extends Buffers {
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL.GL_HALF_FLOAT:
+ case GLES2.GL_HALF_FLOAT_OES:
return newDirectShortBuffer(numElements);
case GL.GL_FIXED:
@@ -174,18 +198,26 @@ public class GLBuffers extends Buffers {
}
/**
- * @param glType shall be one of
- * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
- * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
- * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
- * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
- * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
- * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
- * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
- * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
- * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
- * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27)
+ * @param glType shall be one of (29) <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
* @return null if glType is unhandled or parent is null or bufLen is 0, otherwise the new Buffer object
*/
public static final Buffer sliceGLBuffer(ByteBuffer parent, int bytePos, int byteLen, int glType) {
@@ -195,7 +227,7 @@ public class GLBuffers extends Buffers {
parent.position(bytePos);
parent.limit(bytePos + byteLen);
- switch (glType) {
+ switch (glType) { // 29
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
@@ -210,6 +242,8 @@ public class GLBuffers extends Buffers {
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL.GL_HALF_FLOAT:
+ case GLES2.GL_HALF_FLOAT_OES:
return parent.asShortBuffer();
case GL.GL_FIXED:
@@ -362,28 +396,46 @@ public class GLBuffers extends Buffers {
*
* @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
*
- * @param format must be one of
- * GL_COLOR_INDEX, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL,
- * GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_LUMINANCE,
- * GL_RG, GL_LUMINANCE_ALPHA,
- * GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_ABGR_EXT,
- * GL_RED_INTEGER, GL_GREEN_INTEGER, GL_BLUE_INTEGER,
- * GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER,
- * GL_RGBA_INTEGER, GL_BGRA_INTEGER, GL_HILO_NV, GL_SIGNED_HILO_NV (26)
+ * @param format must be one of (26) <br/>
+ * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
+ * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
+ * GL_RED GL_RED_INTEGER <br/>
+ * GL_GREEN GL_GREEN_INTEGER <br/>
+ * GL_BLUE GL_BLUE_INTEGER <br/>
+ * GL_ALPHA GL_LUMINANCE (12) <br/>
+ * <br/>
+ * GL_LUMINANCE_ALPHA GL_RG <br/>
+ * GL_RG_INTEGER GL_HILO_NV <br/>
+ * GL_SIGNED_HILO_NV (5) <br/>
+ * <br/>
+ * GL_RGB GL_RGB_INTEGER <br/>
+ * GL_BGR GL_BGR_INTEGER (4)<br/>
+ * <br/>
+ * GL_RGBA GL_RGBA_INTEGER <br/>
+ * GL_BGRA GL_BGRA_INTEGER <br/>
+ * GL_ABGR_EXT (5)<br/>
*
- * @param type must be one of
- * GL_BITMAP,
- * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
- * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
- * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
- * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
- * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
- * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
- * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
- * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
- * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
- * GL_HILO16_NV, GL_SIGNED_HILO16_NV (28)
+ * @param type must be one of (30) <br/>
+ * GL_BITMAP, <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
*
* @param width in pixels
* @param height in pixels
@@ -402,7 +454,7 @@ public class GLBuffers extends Buffers {
if (height < 0) return 0;
if (depth < 0) return 0;
- switch (format) /* 24 */ {
+ switch (format) /* 26 */ {
case GL2.GL_COLOR_INDEX:
case GL2GL3.GL_STENCIL_INDEX:
case GL2GL3.GL_DEPTH_COMPONENT:
@@ -445,7 +497,7 @@ public class GLBuffers extends Buffers {
throw new GLException("format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
}
- switch (type) /* 26 */ {
+ switch (type) /* 30 */ {
case GL2.GL_BITMAP:
if (GL2.GL_COLOR_INDEX == format || GL2GL3.GL_STENCIL_INDEX == format) {
return (depth * (height * ((width+7)/8)));
@@ -460,6 +512,7 @@ public class GLBuffers extends Buffers {
case GLES2.GL_HALF_FLOAT_OES:
esize = 2;
break;
+ case GL.GL_FIXED:
case GL2ES2.GL_INT:
case GL.GL_UNSIGNED_INT:
case GL.GL_FLOAT:
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index 368cbc0a2..b0fae8a6d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -35,6 +35,7 @@ import java.io.IOException;
import java.nio.*;
import javax.media.opengl.*;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
@@ -67,6 +68,10 @@ public class GLReadBufferUtil {
return null!=readTextureData && null!=readPixelBuffer ;
}
+ public boolean hasAlpha() { return 4 == components ? true : false ; }
+
+ public GLPixelStorageModes getGLPixelStorageModes() { return psm; }
+
/**
* @return the raw pixel ByteBuffer, filled by {@link #readPixels(GLAutoDrawable, boolean)}
*/
@@ -104,13 +109,14 @@ public class GLReadBufferUtil {
/**
* Read the drawable's pixels to TextureData and Texture, if requested at construction
*
- * @param gl the current GL object
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source.
* @param drawable the drawable to read from
* @param flip weather to flip the data vertically or not
*
* @see #GLReadBufferUtil(boolean, boolean)
*/
- public boolean readPixels(GL gl, GLDrawable drawable, boolean flip) {
+ public boolean readPixels(GL gl, boolean flip) {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
final int textureInternalFormat, textureDataFormat, textureDataType;
final int[] glImplColorReadVals = new int[] { 0, 0 };
@@ -118,7 +124,7 @@ public class GLReadBufferUtil {
textureInternalFormat=GL.GL_RGB;
textureDataFormat=GL.GL_RGB;
textureDataType = GL.GL_UNSIGNED_BYTE;
- } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable("GL_OES_read_format")) {
+ } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable(GLExtensions.OES_read_format)) {
gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
index 3b817afcf..cf0373044 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
@@ -1,15 +1,20 @@
package com.jogamp.opengl.util;
-import com.jogamp.common.util.*;
-import com.jogamp.opengl.util.glsl.ShaderState;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
-import java.nio.*;
-import java.util.Iterator;
-import java.util.ArrayList;
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.opengl.util.glsl.ShaderState;
public class ImmModeSink {
@@ -337,10 +342,8 @@ public class ImmModeSink {
enableBuffer(gl, true);
if (buffer!=null) {
- GL2ES1 glf = gl.getGL2ES1();
-
if(null==indices) {
- glf.glDrawArrays(mode, 0, count);
+ gl.glDrawArrays(mode, 0, count);
} else {
Class<?> clazz = indices.getClass();
int type=-1;
@@ -352,7 +355,7 @@ public class ImmModeSink {
if(0>type) {
throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this);
}
- glf.glDrawElements(mode, indices.remaining(), type, indices);
+ gl.glDrawElements(mode, indices.remaining(), type, indices);
// GL2: gl.glDrawRangeElements(mode, 0, indices.remaining()-1, indices.remaining(), type, indices);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
index fa66673fd..0022d5c2d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
@@ -48,6 +48,7 @@ import javax.media.opengl.GLException;
import javax.media.opengl.glu.gl2.GLUgl2;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.GLPixelStorageModes;
import com.jogamp.opengl.util.TGAWriter;
@@ -392,7 +393,7 @@ public class Screenshot {
private static void checkExtABGR() {
GL2 gl = GLUgl2.getCurrentGL2();
- if (!gl.isExtensionAvailable("GL_EXT_abgr")) {
+ if (!gl.isExtensionAvailable(GLExtensions.EXT_abgr)) {
throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr");
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
index 622ee1b79..1735fcddd 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
@@ -41,6 +41,7 @@ package com.jogamp.opengl.util.awt;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.*;
import com.jogamp.opengl.util.packrect.*;
import com.jogamp.opengl.util.texture.*;
@@ -1976,7 +1977,7 @@ public class TextRenderer {
private final boolean is15Available(GL gl) {
if (!checkFor_isExtensionAvailable_GL_VERSION_1_5) {
- isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable("GL_VERSION_1_5");
+ isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable(GLExtensions.VERSION_1_5);
checkFor_isExtensionAvailable_GL_VERSION_1_5 = true;
}
return isExtensionAvailable_GL_VERSION_1_5;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
index 49d4add5f..e7bf87a36 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
@@ -44,6 +44,7 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.opengl.*;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.texture.spi.*;
/**
@@ -262,8 +263,8 @@ public class Texture {
*
* See the <a href="#perftips">performance tips</a> above for hints
* on how to maximize performance when using many Texture objects.
- * @param gl TODO
- *
+ *
+ * @param gl the current GL context
* @throws GLException if no OpenGL context was current or if any
* OpenGL-related errors occurred
*/
@@ -448,12 +449,12 @@ public class Texture {
// See whether we have automatic mipmap generation support
boolean haveAutoMipmapGeneration =
- (gl.isExtensionAvailable("GL_VERSION_1_4") ||
- gl.isExtensionAvailable("GL_SGIS_generate_mipmap"));
+ (gl.isExtensionAvailable(GLExtensions.VERSION_1_4) ||
+ gl.isExtensionAvailable(GLExtensions.SGIS_generate_mipmap));
// Indicate to the TextureData what functionality is available
- data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr"));
- data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2"));
+ data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr));
+ data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2));
// Indicates whether both width and height are power of two
boolean isPOT = isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight);
@@ -646,7 +647,7 @@ public class Texture {
int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR);
int magFilter = GL.GL_LINEAR;
- int wrapMode = (gl.isExtensionAvailable("GL_VERSION_1_2") || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP;
+ int wrapMode = (gl.isExtensionAvailable(GLExtensions.VERSION_1_2) || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP;
// REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB
if (texTarget != GL2.GL_TEXTURE_RECTANGLE_ARB) {
@@ -925,8 +926,8 @@ public class Texture {
private void updateSubImageImpl(GL gl, TextureData data, int newTarget, int mipmapLevel,
int dstx, int dsty,
int srcx, int srcy, int width, int height) throws GLException {
- data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr"));
- data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2"));
+ data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr));
+ data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2));
Buffer buffer = data.getBuffer();
if (buffer == null && data.getMipmapData() == null) {
@@ -1044,8 +1045,8 @@ public class Texture {
case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- if (!gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc") &&
- !gl.isExtensionAvailable("GL_NV_texture_compression_vtc")) {
+ if (!gl.isExtensionAvailable(GLExtensions.EXT_texture_compression_s3tc) &&
+ !gl.isExtensionAvailable(GLExtensions.NV_texture_compression_vtc)) {
throw new GLException("DXTn compressed textures not supported by this graphics card");
}
break;
@@ -1081,7 +1082,7 @@ public class Texture {
private static boolean haveTexRect(GL gl) {
return (!disableTexRect &&
TextureIO.isTexRectEnabled() &&
- gl.isExtensionAvailable("GL_ARB_texture_rectangle"));
+ gl.isExtensionAvailable(GLExtensions.ARB_texture_rectangle));
}
private static boolean preferTexRect(GL gl) {
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 ca97cdc4b..b878c6002 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -155,6 +155,14 @@ public class TextureIO {
file. */
public static final String TIFF = "tiff";
+ /** Constant which can be used as a file suffix to indicate a PAM
+ file, NetPbm magic 7 - binary RGB and RGBA. Write support only. */
+ public static final String PAM = "pam";
+
+ /** Constant which can be used as a file suffix to indicate a PAM
+ file, NetPbm magic 6 - binary RGB. Write support only. */
+ public static final String PPM = "ppm";
+
private static final boolean DEBUG = Debug.debug("TextureIO");
// For manually disabling the use of the texture rectangle
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 5ee2104a3..6b41c0bc8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -102,7 +102,6 @@ import javax.media.opengl.GL;
*/
public interface TextureSequence {
public static final String GL_OES_EGL_image_external_Required_Prelude = "#extension GL_OES_EGL_image_external : enable\n";
- public static final String GL_OES_EGL_image_external = "GL_OES_EGL_image_external";
public static final String samplerExternalOES = "samplerExternalOES";
public static final String sampler2D = "sampler2D";
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
index c2b131b97..cd42a1157 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
@@ -77,8 +77,10 @@ public class NetPbmTextureWriter implements TextureWriter {
public int getMagic() { return magic; }
- public static final String PPM = "ppm";
- public static final String PAM = "pam";
+ /** @see TextureIO#PPM */
+ public static final String PPM = TextureIO.PPM;
+ /** @see TextureIO#PAM */
+ public static final String PAM = TextureIO.PAM;
public String getSuffix() { return (magic==6)?PPM:PAM; }
diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
index b57b85e5c..5fa8ce32d 100644
--- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
+++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
@@ -117,6 +117,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
final int availnum = available.size();
if (DEBUG) {
+ Thread.dumpStack();
System.err.println("Desired: " + gldes);
System.err.println("Available: " + availnum);
for (int i = 0; i < available.size(); i++) {
@@ -141,7 +142,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
for (int i = 0; i < scores.length; i++) {
scores[i] = NO_SCORE;
}
- final int gldes_samples = gldes.getSampleBuffers() ? gldes.getNumSamples() : 0;
+ final int gldes_samples = gldes.getNumSamples();
// Compute score for each
for (int i = 0; i < availnum; i++) {
@@ -158,8 +159,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
if (gldes.getStereo() != cur.getStereo()) {
continue;
}
- final int cur_samples =
- cur.getSampleBuffers() ? cur.getNumSamples() : 0;
+ final int cur_samples = cur.getNumSamples() ;
int score = 0;
// Compute difference in color depth
@@ -242,7 +242,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
if (i > 0) {
System.err.print(",");
}
- System.err.print(" " + scores[i]);
+ System.err.print(" " + i +": " + scores[i]);
}
System.err.println(" ]");
}
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 80d4f796c..0b2c664fe 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -51,8 +51,8 @@ import jogamp.opengl.Debug;
calls to {@link GLContext#makeCurrent makeCurrent} will block if
the context is current on another thread. This allows the internal
GLContext for the GLAutoDrawable to be used both by the event
- based rendering mechanism as well by end users directly.<P>
-
+ based rendering mechanism as well by end users directly.
+ <p>
The implementation shall initialize itself as soon as possible,
ie if the attached {@link javax.media.nativewindow.NativeSurface NativeSurface} becomes visible/realized.
The following protocol shall be satisfied:
@@ -64,18 +64,18 @@ import jogamp.opengl.Debug;
registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.</li>
<li> Send a reshape event by calling {@link GLEventListener#reshape reshape(..)} for all
registered {@link GLEventListener}s. This shall be done after the {@link GLEventListener#init init(..)} calls.</li>
- </ul><P>
-
+ </ul></P>
+ <p>
Another implementation detail is the drawable reconfiguration. One use case is where a window is being
dragged to another screen with a different pixel configuration, ie {@link GLCapabilities}. The implementation
- shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.<br>
+ shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.<br/>
For example, AWT's {@link java.awt.Canvas} 's {@link java.awt.Canvas#getGraphicsConfiguration getGraphicsConfiguration()}
is capable to determine a display device change. This is demonstrated within {@link javax.media.opengl.awt.GLCanvas}'s
and NEWT's <code>AWTCanvas</code> {@link javax.media.opengl.awt.GLCanvas#getGraphicsConfiguration getGraphicsConfiguration()}
specialization. Another demonstration is NEWT's {@link javax.media.nativewindow.NativeWindow NativeWindow}
- implementation on the Windows platform, which utilizes the native platform's <i>MonitorFromWindow(HWND)</i> function.<br>
+ implementation on the Windows platform, which utilizes the native platform's <i>MonitorFromWindow(HWND)</i> function.<br/>
All OpenGL resources shall be regenerated, while the drawable's {@link GLCapabilities} has
- to be choosen again. The following protocol shall be satisfied.
+ to be chosen again. The following protocol shall be satisfied.
<ul>
<li> Controlled disposal:</li>
<ul>
@@ -97,16 +97,16 @@ import jogamp.opengl.Debug;
</ul>
Note: Current graphics driver keep the surface configuration for a given window, even if the window is moved to
a monitor with a different pixel configuration, ie 32bpp to 16bpp. However, it is best to not assume such behavior
- and make your application comply with the above protocol.<P>
-
- However, to not introduce to much breakage with older applications and because of the situation
+ and make your application comply with the above protocol.
+ <p>
+ Avoiding breakage with older applications and because of the situation
mentioned above, the <code>boolean</code> system property <code>jogl.screenchange.action</code> will control the
- screen change action as follows:<br>
-
+ screen change action as follows:<br/>
<PRE>
-Djogl.screenchange.action=false Disable the drawable reconfiguration (the default)
-Djogl.screenchange.action=true Enable the drawable reconfiguration
</PRE>
+ </p>
*/
public interface GLAutoDrawable extends GLDrawable {
/** Flag reflecting wheather the drawable reconfiguration will be issued in
@@ -362,5 +362,29 @@ public interface GLAutoDrawable extends GLDrawable {
demos for examples.
@return the set GL pipeline or null if not successful */
public GL setGL(GL gl);
+
+ /**
+ * Method <i>may</i> return the upstream UI toolkit object
+ * holding this {@link GLAutoDrawable} instance, if exist.
+ * <p>
+ * Currently known Java UI toolkits and it's known return types are:
+ *
+ * <table border="1">
+ * <tr><td>Toolkit</td> <td>GLAutoDrawable Implementation</td> <td>~</td> <td>Return Type of getUpstreamWidget()</td</tr>
+ * <tr><td>NEWT</td> <td>{@link com.jogamp.newt.opengl.GLWindow}</td> <td>has a</td> <td>{@link com.jogamp.newt.Window}</td</tr>
+ * <tr><td>SWT</td> <td>{@link com.jogamp.opengl.swt.GLCanvas}</td> <td>is a</td> <td>{@link org.eclipse.swt.widgets.Canvas}</td</tr>
+ * <tr><td>AWT</td> <td>{@link javax.media.opengl.awt.GLCanvas}</td> <td>is a</td> <td>{@link java.awt.Canvas}</td</tr>
+ * <tr><td>AWT</td> <td>{@link javax.media.opengl.awt.GLJPanel}</td> <td>is a</td> <td>{@link javax.swing.JPanel}</td</tr>
+ * </table>
+ * However, the result may be other object types than the listed above
+ * due to new supported toolkits.
+ * </p>
+ * <p>
+ * This method may also return <code>null</code> if no UI toolkit is being used,
+ * as common for offscreen rendering.
+ * </p>
+ * @return
+ */
+ public Object getUpstreamWidget();
}
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
index 89d5cc4cb..67e81270d 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
@@ -28,6 +28,8 @@
package javax.media.opengl;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
@@ -56,23 +58,33 @@ import jogamp.opengl.GLDrawableImpl;
public class GLAutoDrawableDelegate extends GLAutoDrawableBase {
public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate");
- public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context) {
- super((GLDrawableImpl)drawable, (GLContextImpl)context);
+ /**
+ * @param drawable a valid {@link GLDrawable}, may not be realized yet.
+ * @param context a valid {@link GLContext}, may not be made current (created) yet.
+ * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
+ * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass <code>false</code>. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ */
+ public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) {
+ super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
+ this.upstreamWidget = null;
}
//
- // make protected methods accessible
+ // expose default methods
//
- public void defaultWindowRepaintOp() {
+ public final void windowRepaintOp() {
super.defaultWindowRepaintOp();
}
- public void defaultWindowResizedOp() {
+ public final void windowResizedOp() {
super.defaultWindowResizedOp();
}
- public void defaultWindowDestroyNotifyOp() {
+ public final void windowDestroyNotifyOp() {
super.defaultWindowDestroyNotifyOp();
}
@@ -80,44 +92,35 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase {
// Complete GLAutoDrawable
//
- private RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
-
+ private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
+ private final Object upstreamWidget;
+
+ @Override
+ protected final RecursiveLock getLock() { return lock; }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return upstreamWidget;
+ }
+
/**
* {@inheritDoc}
* <p>
- * This implementation calls {@link #defaultDestroyOp()}.
+ * This implementation calls {@link #defaultDestroy()}.
* </p>
* <p>
* User still needs to destroy the upstream window, which details are hidden from this aspect.
+ * This can be performed by overriding {@link #destroyImplInLock()}.
* </p>
*/
@Override
- public void destroy() {
- lock.lock();
- try {
- defaultDestroyOp();
- } finally {
- lock.unlock();
- }
+ public final void destroy() {
+ defaultDestroy();
}
@Override
public void display() {
- if( sendDestroy ) {
- sendDestroy=false;
- destroy();
- return;
- }
-
- lock.lock(); // sync: context/drawable could been recreated/destroyed while animating
- try {
- if( null != drawable && drawable.isRealized() && null != context ) {
- // surface is locked/unlocked implicit by context's makeCurrent/release
- helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
- }
- } finally {
- lock.unlock();
- }
+ defaultDisplay();
}
//
@@ -133,4 +136,9 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase {
public final void setRealized(boolean realized) {
}
+ @Override
+ public final void swapBuffers() throws GLException {
+ defaultSwapBuffers();
+ }
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index bd24b15bc..f5831a72d 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -340,5 +340,60 @@ public interface GLBase {
* completeness.
*/
public Object getExtension(String extensionName);
+
+ /** Aliased entrypoint of <code> void {@native glClearDepth}(GLclampd depth); </code> and <code> void {@native glClearDepthf}(GLclampf depth); </code>. */
+ public void glClearDepth( double depth );
+
+ /** Aliased entrypoint of <code> void {@native glDepthRange}(GLclampd depth); </code> and <code> void {@native glDepthRangef}(GLclampf depth); </code>. */
+ public void glDepthRange(double zNear, double zFar);
+
+ /**
+ * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, ..
+ * @return the GL buffer (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound.
+ */
+ public int glGetBoundBuffer(int target);
+
+ /**
+ * @param buffer a GL buffer name, generated with {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} for example.
+ * @return the size of the given GL buffer
+ */
+ public long glGetBufferSize(int buffer);
+
+ /**
+ * @return true if a VBO is bound to {@link GL.GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean glIsVBOArrayEnabled();
+
+ /**
+ * @return true if a VBO is bound to {@link GL.GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean glIsVBOElementArrayEnabled();
+
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ public int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ * </p>
+ */
+ public int getDefaultDrawFramebuffer();
+
+ /**
+ * Return the default read framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ * </p>
+ */
+ public int getDefaultReadFramebuffer();
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
index 61ab2e58d..8845ec665 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
@@ -55,8 +55,9 @@ import javax.media.nativewindow.CapabilitiesImmutable;
It currently contains the minimal number of routines which allow
configuration on all supported window systems. */
public class GLCapabilities extends Capabilities implements Cloneable, GLCapabilitiesImmutable {
- private GLProfile glProfile = null;
- private boolean pbuffer = false;
+ private GLProfile glProfile = null;
+ private boolean isPBuffer = false;
+ private boolean isFBO = false;
private boolean doubleBuffered = true;
private boolean stereo = false;
private boolean hardwareAccelerated = true;
@@ -105,7 +106,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
public int hashCode() {
// 31 * x == (x << 5) - x
int hash = 31 + this.glProfile.hashCode() ;
- hash = ((hash << 5) - hash) + ( this.pbuffer ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.isFBO ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.isPBuffer ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.stereo ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.hardwareAccelerated ? 1 : 0 );
hash = ((hash << 5) - hash) + this.depthBits;
@@ -132,7 +134,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
GLCapabilitiesImmutable other = (GLCapabilitiesImmutable)obj;
boolean res = super.equals(obj) &&
other.getGLProfile()==glProfile &&
- other.isPBuffer()==pbuffer &&
+ other.isPBuffer()==isPBuffer &&
+ other.isFBO()==isFBO &&
other.getStereo()==stereo &&
other.getHardwareAccelerated()==hardwareAccelerated &&
other.getDepthBits()==depthBits &&
@@ -180,8 +183,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
return -1;
}
- final int ms = sampleBuffers ? numSamples : 0;
- final int xms = caps.getSampleBuffers() ? caps.getNumSamples() : 0;
+ final int ms = getNumSamples();
+ final int xms = caps.getNumSamples() ;
if(ms > xms) {
return 1;
@@ -222,30 +225,53 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
@Override
public final boolean isPBuffer() {
- return pbuffer;
+ return isPBuffer;
}
/**
- * Enables or disables pbuffer usage.<br>
- * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}<br>
+ * Enables or disables pbuffer usage.
+ * <p>
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
+ * </p>
* Defaults to false.
*/
public void setPBuffer(boolean enable) {
if(enable) {
setOnscreen(false);
}
- pbuffer = enable;
+ isPBuffer = enable;
+ }
+
+ @Override
+ public final boolean isFBO() {
+ return isFBO;
+ }
+
+ /**
+ * Enables or disables FBO usage.
+ * <p>
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
+ * </p>
+ * Defaults to false.
+ */
+ public void setFBO(boolean enable) {
+ if(enable) {
+ setOnscreen(false);
+ }
+ isFBO = enable;
}
/**
* Sets whether the drawable surface supports onscreen.<br>
- * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)}<br>
+ * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)}
+ * and {@link #setFBO(int) setFBO(false)}<br>
* Defaults to true.
*/
@Override
public void setOnscreen(boolean onscreen) {
if(onscreen) {
setPBuffer(false);
+ setFBO(false);
}
super.setOnscreen(onscreen);
}
@@ -385,15 +411,18 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
return sampleBuffers;
}
- /** If sample buffers are enabled, indicates the number of buffers
- to be allocated. Defaults to 2. */
+ /**
+ * If sample buffers are enabled, indicates the number of buffers
+ * to be allocated. Defaults to 2.
+ * @see #getNumSamples()
+ */
public void setNumSamples(int numSamples) {
this.numSamples = numSamples;
}
@Override
public final int getNumSamples() {
- return numSamples;
+ return sampleBuffers ? numSamples : 0;
}
/** For pbuffers only, indicates whether floating-point buffers
@@ -462,12 +491,16 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
sink.append(glProfile);
if(!isOnscreen()) {
- if(pbuffer) {
+ if(isFBO) {
+ sink.append(", fbo");
+ }
+ if(isPBuffer) {
sink.append(", pbuffer [r2t ").append(pbufferRenderToTexture?1:0)
.append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0)
.append(", float ").append(pbufferFloatingPointBuffers?1:0)
.append("]");
- } else {
+ }
+ if(!isFBO && !isPBuffer) {
sink.append(", pixmap");
}
}
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
index 5f8795edc..7e0459b2d 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
@@ -111,7 +111,7 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
/**
* Returns the number of sample buffers to be allocated if sample
- * buffers are enabled. Defaults to 2.
+ * buffers are enabled, otherwise returns 0. Defaults to 2.
*/
int getNumSamples();
@@ -144,10 +144,15 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
boolean getStereo();
/**
- * Indicates whether pbuffer is used/requested.
+ * Indicates whether pbuffer offscreen is used/requested.
*/
boolean isPBuffer();
+ /**
+ * Indicates whether FBO offscreen is used/requested.
+ */
+ boolean isFBO();
+
@Override
boolean equals(Object obj);
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 351f90027..63a02ad9c 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -55,6 +55,7 @@ import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.opengl.GLExtensions;
/** Abstraction for an OpenGL rendering context. In order to perform
OpenGL rendering, a context must be "made current" on the current
@@ -69,6 +70,7 @@ import com.jogamp.common.util.locks.RecursiveLock;
abstraction provides a stable object which clients can use to
refer to a given context. */
public abstract class GLContext {
+
/**
* If <code>true</code> (default), bootstrapping the available GL profiles
* will use the highest compatible GL context for each profile,
@@ -120,13 +122,13 @@ public abstract class GLContext {
protected static final int CTX_PROFILE_ES = 1 << 3;
/** <code>ARB_create_context</code> related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_OPTION_FORWARD = 1 << 4;
- /** <code>ARB_create_context</code> related: flag debug. Not a cache key. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ /** <code>ARB_create_context</code> related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
/** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
- /** Context supports FBO, details see {@link #hasFBO()}.
+ /** Context supports basic FBO, details see {@link #hasFBO()}.
* Not a cache key.
* @see #hasFBO()
* @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
@@ -136,16 +138,6 @@ public abstract class GLContext {
/** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
- protected static final String GL_ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
- protected static final String GL_ARB_framebuffer_object = "GL_ARB_framebuffer_object";
- protected static final String GL_EXT_framebuffer_object = "GL_EXT_framebuffer_object";
- protected static final String GL_EXT_framebuffer_blit = "GL_EXT_framebuffer_blit";
- protected static final String GL_EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample";
- protected static final String GL_EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil";
- protected static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
- protected static final String GL_EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888";
- protected static final String GL_IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888";
-
private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>();
private final HashMap<String, Object> attachedObjectsByString = new HashMap<String, Object>();
@@ -639,11 +631,19 @@ public abstract class GLContext {
return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
}
- /** Returns whether the context supports FBO, hence is either GL-ES >= 2.0, >= core GL 3.0 or implements the extensions
- * <code>GL_ARB_ES2_compatibility</code>, <code>ARB_framebuffer_object</code> or all of
- * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
- * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
+ /**
+ * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * <code>GL_ARB_ES2_compatibility</code>, <code>GL_ARB_framebuffer_object</code>, <code>GL_EXT_framebuffer_object</code> or <code>GL_OES_framebuffer_object</code>.
+ * </p>
+ * <p>
+ * Basic FBO support may only include one color attachment and no multisampling,
+ * as well as limited internal formats for renderbuffer.
+ * </p>
* @see #CTX_IMPL_FBO
+ * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL)
+ * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL)
*/
public final boolean hasFBO() {
return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
@@ -659,13 +659,13 @@ public abstract class GLContext {
/** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns <code>true</code>. */
public boolean isNPOTTextureAvailable() {
- return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two);
+ return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
}
public boolean isTextureFormatBGRA8888Available() {
return isGL2GL3() ||
- isExtensionAvailable(GL_EXT_texture_format_BGRA8888) ||
- isExtensionAvailable(GL_IMG_texture_format_BGRA8888) ;
+ isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
}
/** @see GLProfile#isGL4bc() */
@@ -798,7 +798,32 @@ public abstract class GLContext {
}
protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; }
-
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ public abstract int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ * </p>
+ */
+ public abstract int getDefaultDrawFramebuffer();
+
+ /**
+ * Return the default read framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ * </p>
+ */
+ public abstract int getDefaultReadFramebuffer();
+
/**
* @return The extension implementing the GLDebugOutput feature,
* either <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>.
@@ -984,6 +1009,7 @@ public abstract class GLContext {
deviceVersionsAvailableSet.add(devKey);
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey);
+ System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
}
}
}
@@ -1010,6 +1036,10 @@ public abstract class GLContext {
validateProfileBits(profile, "profile");
validateProfileBits(resCtp, "resCtp");
+ if(DEBUG) {
+ System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
+ // Thread.dumpStack();
+ }
final String key = getDeviceVersionAvailableKey(device, reqMajor, profile);
final Integer val = new Integer(composeBits(resMajor, resMinor, resCtp));
synchronized(deviceVersionAvailable) {
@@ -1122,7 +1152,9 @@ public abstract class GLContext {
} else /* if (glpImpl.isGL2()) */ {
reqMajorCTP[0]=2;
}
- if( glpImpl.isGL2() ) { // incl GL3bc and GL4bc
+ if( glpImpl.isGLES() ) {
+ reqMajorCTP[1]=CTX_PROFILE_ES;
+ } else if( glpImpl.isGL2() ) { // incl GL3bc and GL4bc
reqMajorCTP[1]=CTX_PROFILE_COMPAT;
} else {
reqMajorCTP[1]=CTX_PROFILE_CORE;
@@ -1141,8 +1173,7 @@ public abstract class GLContext {
int _major[] = { 0 };
int _minor[] = { 0 };
int _ctp[] = { 0 };
- if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1],
- _major, _minor, _ctp)) {
+ if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], _major, _minor, _ctp)) {
return _ctp[0];
}
return 0; // n/a
@@ -1181,6 +1212,23 @@ public abstract class GLContext {
}
/**
+ * Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
+ * <p>
+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
+ * </p>
+ * <p>
+ * FBO support is queried as described in {@link #hasFBO()}.
+ * </p>
+ *
+ * @param device the device to request whether FBO is available for
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasFBO()
+ */
+ public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) {
+ return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) );
+ }
+
+ /**
* @param device the device to request whether the profile is available for
* @param reqMajor Key Value either 1, 2, 3 or 4
* @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index d6480e7aa..9a0d2cb99 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -50,9 +50,11 @@ import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.ReflectionUtil;
import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
import javax.media.opengl.GLProfile.ShutdownType;
import jogamp.opengl.Debug;
@@ -398,9 +400,18 @@ public abstract class GLDrawableFactory {
/**
* Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
* <p>
- * A Pbuffer drawable/surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.<br>
- * Otherwise a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.<br>
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below.
+ * </p>
+ * <p>
+ * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()}
+ * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true.
+ * </p>
+ * <p>
+ * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
+ * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+ * </p>
+ * <p>
+ * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
* </p>
*
* @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
@@ -421,42 +432,32 @@ public abstract class GLDrawableFactory {
throws GLException;
/**
- * Creates an offscreen NativeSurface.<br>
- * A Pbuffer surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.<br>
- * Otherwise a simple pixmap/bitmap surface is created. The latter is unlikely to be hardware accelerated.<br>
- *
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
- * @param caps the requested GLCapabilties
- * @param chooser the custom chooser, may be null for default
- * @param width the requested offscreen width
- * @param height the requested offscreen height
- * @return the created offscreen native surface
- *
- * @throws GLException if any window system-specific errors caused
- * the creation of the GLDrawable to fail.
- */
- public abstract NativeSurface createOffscreenSurface(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable caps,
- GLCapabilitiesChooser chooser,
- int width, int height);
-
- /**
- * Highly experimental API entry, allowing developer of new windowing system bindings
- * to leverage the native window handle to produce a NativeSurface implementation (ProxySurface), having the required GLCapabilities.<br>
- * Such surface can be used to instantiate a GLDrawable and hence test your new binding w/o the
- * costs of providing a full set of abstraction like the AWT GLCanvas or even the native NEWT bindings.
+ * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance.
+ * <p>
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given
+ * <code>windowHandle</code>'s native visualID if set or the given {@link GLCapabilitiesImmutable}.
+ * </p>
+ * <p>
+ * Lifecycle (destruction) of the given surface handle shall be handled by the caller.
+ * </p>
+ * <p>
+ * Such surface can be used to instantiate a GLDrawable. With the help of {@link GLAutoDrawableDelegate}
+ * you will be able to implement a new native windowing system binding almost on-the-fly, see {@link com.jogamp.opengl.swt.GLCanvas}.
+ * </p>
*
- * @param device the platform's target device, shall not be <code>null</code>
+ * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * Caller has to ensure it is compatible w/ the given <code>windowHandle</code>
+ * @param screenIdx matching screen index of given <code>windowHandle</code>
* @param windowHandle the native window handle
* @param caps the requested GLCapabilties
* @param chooser the custom chooser, may be null for default
- * @return The proxy surface wrapping the windowHandle on the device
+ * @param upstream optional {@link ProxySurface.UpstreamSurfaceHook} allowing control of the {@link ProxySurface}'s lifecycle and data it presents.
+ * @return the created {@link ProxySurface} instance w/ defined surface handle.
*/
- public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
+ public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
+ int screenIdx,
long windowHandle,
- GLCapabilitiesImmutable caps,
- GLCapabilitiesChooser chooser);
+ GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
/**
* Returns true if it is possible to create a GLPbuffer. Some older
@@ -492,23 +493,7 @@ public abstract class GLDrawableFactory {
GLContext shareWith)
throws GLException;
- /**
- * Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
- * <p>
- * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
- * </p>
- * <p>
- * FBO support is queried as described in {@link GLContext#hasFBO()}.
- * </p>
- *
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
- * @param glp {@link GLProfile} to check for FBO capabilities
- * @see GLContext#hasFBO()
- */
- public final boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp) {
- return 0 != ( GLContext.CTX_IMPL_FBO & GLContext.getAvailableContextProperties(device, glp) );
- }
-
+
//----------------------------------------------------------------------
// Methods for interacting with third-party OpenGL libraries
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index a7200b560..1e10dc9a6 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -86,7 +86,14 @@ public class GLProfile {
* </p>
*/
private static final boolean enableANGLE = Debug.isPropertyDefined("jogl.enable.ANGLE", true);
-
+
+ /**
+ * In case no OpenGL ES implementation is required
+ * and if the running platform may have a buggy implementation,
+ * setting the property <code>jogl.disable.opengles</code> disables querying a possible existing OpenGL ES implementation.
+ */
+ private static final boolean disableOpenGLES = Debug.isPropertyDefined("jogl.disable.opengles", true);
+
static {
// Also initializes TempJarCache if shall be used.
Platform.initSingleton();
@@ -117,10 +124,12 @@ public class GLProfile {
* @deprecated Use {@link #initSingleton()}. This method is subject to be removed in future versions of JOGL.
*/
public static void initSingleton(final boolean firstUIActionOnProcess) {
+ final boolean justInitialized;
initLock.lock();
try {
if(!initialized) { // volatile: ok
initialized = true;
+ justInitialized = true;
if(DEBUG) {
System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName());
Thread.dumpStack();
@@ -166,10 +175,17 @@ public class GLProfile {
return null;
}
});
+ } else {
+ justInitialized = false;
}
} finally {
initLock.unlock();
}
+ if(DEBUG) {
+ if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES2Impl ) ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true));
+ }
+ }
}
/**
@@ -1466,7 +1482,7 @@ public class GLProfile {
}
}
- if ( ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
+ if ( !disableOpenGLES && ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
t=null;
try {
eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2);
@@ -1532,18 +1548,17 @@ public class GLProfile {
if(DEBUG) {
// System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
- System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
- System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
- System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
- System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
- System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory);
- System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
- System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl);
- System.err.println("GLProfile.init defaultDevice "+defaultDevice);
- System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
- if(hasGL234Impl || hasGLES1Impl || hasGLES2Impl) { // avoid deadlock
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true));
- }
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
+ System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
+ System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
+ System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
+ System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory);
+ System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
+ System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl);
+ System.err.println("GLProfile.init defaultDevice "+defaultDevice);
+ System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice);
+ System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice);
+ System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
}
}
@@ -1642,24 +1657,6 @@ public class GLProfile {
if (DEBUG) {
System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail);
}
- if( hasGLES2Impl ) {
- // The native ES2 impl. overwrites a previous mapping using 'ES2 compatibility' by a desktop profile
- GLContext.mapAvailableGLVersion(device,
- 2, GLContext.CTX_PROFILE_ES,
- 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_IMPL_ES2_COMPAT);
- if (DEBUG) {
- System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES2 -> ES 2.0");
- }
- }
- if( hasGLES1Impl ) {
- // Always favor the native ES1 impl.
- GLContext.mapAvailableGLVersion(device,
- 1, GLContext.CTX_PROFILE_ES,
- 1, 0, GLContext.CTX_PROFILE_ES);
- if (DEBUG) {
- System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES1 -> ES 1.0");
- }
- }
addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */);
}
@@ -1767,7 +1764,7 @@ public class GLProfile {
}
_mappedProfiles.put(profile, glProfile);
if (DEBUG) {
- System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection());
+ System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection());
}
if(null==defaultGLProfileHW && isHardwareRasterizer[0]) {
defaultGLProfileHW=glProfile;
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 48f7ea24a..03fd78ac7 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -60,6 +60,7 @@ import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.OffscreenLayerOption;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -84,6 +85,8 @@ import javax.media.opengl.Threading;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
@@ -132,20 +135,6 @@ import jogamp.opengl.GLDrawableHelper;
* <ul>
* <li><pre>sun.awt.noerasebackground=true</pre></li>
* </ul>
- * <p>
- * FIXME: If this instance runs in multithreading mode, see {@link Threading#isSingleThreaded()} (default: single-thread),
- * proper recursive locking is required for drawable/context @ destroy and display.
- * Recreation etc could pull those instances while animating!
- * Simply locking before using drawable/context offthread
- * would allow a deadlock situation!
- * </p>
- * <p>
- * NOTE: [MT-0] Methods utilizing [volatile] drawable/context are not synchronized.
- In case any of the methods are called outside of a locked state
- extra care should be added. Maybe we shall expose locking facilities to the user.
- However, since the user shall stick to the GLEventListener model while utilizing
- GLAutoDrawable implementations, she is safe due to the implicit locked state.
- * </p>
*/
@SuppressWarnings("serial")
@@ -153,11 +142,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private static final boolean DEBUG = Debug.debug("GLCanvas");
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
private final GLDrawableHelper helper = new GLDrawableHelper();
private AWTGraphicsConfiguration awtConfig;
- private volatile GLDrawable drawable; // volatile avoids locking all accessors. FIXME still need to sync destroy/display
+ private volatile GLDrawable drawable; // volatile: avoid locking for read-only access
private GLContextImpl context;
- private boolean sendReshape = false;
+ private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking
// copy of the cstr args, mainly for recreation
private GLCapabilitiesImmutable capsReqUser;
@@ -262,6 +252,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
public void setShallUseOffscreenLayer(boolean v) {
shallUseOffscreenLayer = v;
}
@@ -273,8 +268,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public final boolean isOffscreenLayerSurfaceEnabled() {
- if(null != drawable) {
- return ((JAWTWindow)drawable.getNativeSurface()).isOffscreenLayerSurfaceEnabled();
+ final GLDrawable _drawable = drawable;
+ if(null != _drawable) {
+ return ((JAWTWindow)_drawable.getNativeSurface()).isOffscreenLayerSurfaceEnabled();
}
return false;
}
@@ -393,12 +389,18 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public GLContext createContext(final GLContext shareWith) {
- if(drawable != null) {
- final GLContext _ctx = drawable.createContext(shareWith);
- _ctx.setContextCreationFlags(additionalCtxCreationFlags);
- return _ctx;
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if(drawable != null) {
+ final GLContext _ctx = drawable.createContext(shareWith);
+ _ctx.setContextCreationFlags(additionalCtxCreationFlags);
+ return _ctx;
+ }
+ return null;
+ } finally {
+ _lock.unlock();
}
- return null;
}
@Override
@@ -407,7 +409,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public boolean isRealized() {
- return (null != drawable) ? drawable.isRealized() : false;
+ final GLDrawable _drawable = drawable;
+ return ( null != _drawable ) ? _drawable.isRealized() : false;
}
@Override
@@ -422,50 +425,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public void display() {
- if( !validateGLDrawable() ) {
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet");
- }
- return; // not yet available ..
- }
Threading.invoke(true, displayOnEDTAction, getTreeLock());
-
awtWindowClosingProtocol.addClosingListenerOneShot();
}
private void dispose(boolean regenerate) {
- final GLAnimatorControl animator = getAnimator();
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: dispose("+regenerate+") - START, hasContext " +
- (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
- Thread.dumpStack();
- }
-
- if(null!=drawable && null!=context) { // drawable is volatile!
- boolean animatorPaused = false;
- if(null!=animator) {
- // can't remove us from animator for recreational addNotify()
- animatorPaused = animator.pause();
- }
-
- disposeRegenerate=regenerate;
-
- if(context.isCreated()) {
- Threading.invoke(true, disposeOnEDTAction, getTreeLock());
- }
-
- if(animatorPaused) {
- animator.resume();
- }
- }
-
- if(!regenerate) {
- disposeAbstractGraphicsDevice();
- }
-
- if(DEBUG) {
- System.err.println(getThreadName()+": dispose("+regenerate+") - END, "+animator);
- }
+ disposeRegenerate=regenerate;
+ Threading.invoke(true, disposeOnEDTAction, getTreeLock());
}
/**
@@ -525,43 +491,49 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@SuppressWarnings("deprecation")
@Override
public void addNotify() {
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds());
- Thread.dumpStack();
- }
-
- /**
- * 'super.addNotify()' determines the GraphicsConfiguration,
- * while calling this class's overriden 'getGraphicsConfiguration()' method
- * after which it creates the native peer.
- * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
- * is being used in getGraphicsConfiguration().
- * This code order also allows recreation, ie re-adding the GLCanvas.
- */
- awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
- if(null==awtConfig) {
- throw new GLException("Error: NULL AWTGraphicsConfiguration");
- }
-
- // before native peer is valid: X11
- disableBackgroundErase();
-
- // issues getGraphicsConfiguration() and creates the native peer
- super.addNotify();
-
- // after native peer is valid: Windows
- disableBackgroundErase();
-
- if (!Beans.isDesignTime()) {
- createDrawableAndContext();
- }
-
- // init drawable by paint/display makes the init sequence more equal
- // for all launch flavors (applet/javaws/..)
- // validateGLDrawable();
-
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds());
+ Thread.dumpStack();
+ }
+
+ /**
+ * 'super.addNotify()' determines the GraphicsConfiguration,
+ * while calling this class's overriden 'getGraphicsConfiguration()' method
+ * after which it creates the native peer.
+ * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
+ * is being used in getGraphicsConfiguration().
+ * This code order also allows recreation, ie re-adding the GLCanvas.
+ */
+ awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
+ if(null==awtConfig) {
+ throw new GLException("Error: NULL AWTGraphicsConfiguration");
+ }
+
+ // before native peer is valid: X11
+ disableBackgroundErase();
+
+ // issues getGraphicsConfiguration() and creates the native peer
+ super.addNotify();
+
+ // after native peer is valid: Windows
+ disableBackgroundErase();
+
+ if (!Beans.isDesignTime()) {
+ createDrawableAndContext();
+ }
+
+ // init drawable by paint/display makes the init sequence more equal
+ // for all launch flavors (applet/javaws/..)
+ // validateGLDrawable();
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
+ }
+ } finally {
+ _lock.unlock();
}
}
@@ -580,23 +552,24 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
private boolean validateGLDrawable() {
- boolean realized = false;
- if (!Beans.isDesignTime()) {
- if ( null != drawable ) { // OK: drawable is volatile
- realized = drawable.isRealized();
- if ( !realized && 0 < drawable.getWidth() * drawable.getHeight() ) {
- // make sure drawable realization happens on AWT EDT, due to AWTTree lock
- AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction);
- realized = true;
- sendReshape=true; // ensure a reshape is being send ..
- if(DEBUG) {
- System.err.println(getThreadName()+": Realized Drawable: "+drawable.toString());
- Thread.dumpStack();
- }
+ final GLDrawable _drawable = drawable;
+ if ( null != _drawable ) {
+ if( _drawable.isRealized() ) {
+ return true;
+ }
+ if (!Beans.isDesignTime() &&
+ 0 < _drawable.getWidth() * _drawable.getHeight() ) {
+ // make sure drawable realization happens on AWT EDT, due to AWTTree lock
+ AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction);
+ sendReshape=true; // ensure a reshape is being send ..
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString());
+ Thread.dumpStack();
}
+ return true;
}
}
- return realized;
+ return false;
}
private Runnable setRealizedOnEDTAction = new Runnable() {
@Override
@@ -628,9 +601,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
try {
dispose(false);
} finally {
- context=null;
- drawable=null;
- awtConfig=null;
super.removeNotify();
}
}
@@ -650,7 +620,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public void reshape(int x, int y, int width, int height) {
super.reshape(x, y, width, height);
- if(null != drawable && drawable.isRealized() && !drawable.getChosenGLCapabilities().isOnscreen()) {
+ final GLDrawable _drawable = drawable;
+ if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) {
dispose(true);
} else {
sendReshape = true;
@@ -705,13 +676,19 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public GLContext setContext(GLContext newCtx) {
- final GLContext oldCtx = context;
- final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
- context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLContext oldCtx = context;
+ final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ context=(GLContextImpl)newCtx;
+ if(newCtxCurrent) {
+ context.makeCurrent();
+ }
+ return oldCtx;
+ } finally {
+ _lock.unlock();
}
- return oldCtx;
}
@Override
@@ -724,15 +701,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if (Beans.isDesignTime()) {
return null;
}
- GLContext ctx = getContext();
- return (ctx == null) ? null : ctx.getGL();
+ final GLContext _context = context;
+ return (_context == null) ? null : _context.getGL();
}
@Override
public GL setGL(GL gl) {
- GLContext ctx = getContext();
- if (ctx != null) {
- ctx.setGL(gl);
+ final GLContext _context = context;
+ if (_context != null) {
+ _context.setGL(gl);
return gl;
}
return null;
@@ -757,8 +734,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public void setContextCreationFlags(int flags) {
additionalCtxCreationFlags = flags;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
+ final GLContext _context = context;
+ if(null != _context) {
+ _context.setContextCreationFlags(additionalCtxCreationFlags);
}
}
@@ -791,26 +769,30 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public NativeSurface getNativeSurface() {
- return (null != drawable) ? drawable.getNativeSurface() : null;
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getNativeSurface() : null;
}
@Override
public long getHandle() {
- return (null != drawable) ? drawable.getHandle() : 0;
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getHandle() : 0;
}
@Override
public GLDrawableFactory getFactory() {
- return (null != drawable) ? drawable.getFactory() : null;
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getFactory() : null;
}
@Override
public String toString() {
- final int dw = (null!=drawable) ? drawable.getWidth() : -1;
- final int dh = (null!=drawable) ? drawable.getHeight() : -1;
+ final GLDrawable _drawable = drawable;
+ final int dw = (null!=_drawable) ? _drawable.getWidth() : -1;
+ final int dh = (null!=_drawable) ? _drawable.getHeight() : -1;
return "AWT-GLCanvas[Realized "+isRealized()+
- ",\n\t"+((null!=drawable)?drawable.getClass().getName():"null-drawable")+
+ ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
",\n\tFactory "+getFactory()+
",\n\thandle 0x"+Long.toHexString(getHandle())+
",\n\tDrawable size "+dw+"x"+dh+
@@ -824,7 +806,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
//
private boolean disposeRegenerate;
- private final Runnable postDisposeAction = new Runnable() {
+ private final Runnable postDisposeOnEDTAction = new Runnable() {
@Override
public void run() {
context=null;
@@ -854,7 +836,47 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private final Runnable disposeOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLAnimatorControl animator = getAnimator();
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: dispose("+disposeRegenerate+") - START, hasContext " +
+ (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
+ Thread.dumpStack();
+ }
+
+ if(null!=drawable && null!=context) {
+ boolean animatorPaused = false;
+ if(null!=animator) {
+ // can't remove us from animator for recreational addNotify()
+ animatorPaused = animator.pause();
+ }
+
+ if(context.isCreated()) {
+ helper.disposeGL(GLCanvas.this, drawable, context, postDisposeOnEDTAction);
+ }
+
+ if(animatorPaused) {
+ animator.resume();
+ }
+ }
+
+ if(!disposeRegenerate) {
+ if(null != awtConfig) {
+ disposeAbstractGraphicsDevice();
+ }
+ awtConfig=null;
+ }
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, "+animator);
+ }
+
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -874,7 +896,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if(DEBUG) {
System.err.println(getThreadName()+": GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
}
- awtConfig=null;
}
}
};
@@ -885,7 +906,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
*
* @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice)
*/
- void disposeAbstractGraphicsDevice() {
+ private void disposeAbstractGraphicsDevice() {
if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
disposeAbstractGraphicsDeviceAction.run();
} else {
@@ -936,14 +957,30 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private final Runnable displayOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.invokeGL(drawable, context, displayAction, initAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( validateGLDrawable() ) {
+ helper.invokeGL(drawable, context, displayAction, initAction);
+ } else if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet");
+ }
+ } finally {
+ _lock.unlock();
+ }
}
};
private final Runnable swapBuffersOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -1026,9 +1063,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
config = (AWTGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, aScreen);
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
} else {
try {
final ArrayList<AWTGraphicsConfiguration> bucket = new ArrayList<AWTGraphicsConfiguration>(1);
@@ -1036,9 +1073,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public void run() {
AWTGraphicsConfiguration c = (AWTGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, aScreen);
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
bucket.add(c);
}
});
@@ -1070,7 +1107,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
final Frame frame = new Frame("JOGL AWT Test");
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index cd18c5098..acb8f2183 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -87,7 +87,7 @@ import jogamp.opengl.awt.Java2D;
import jogamp.opengl.awt.Java2DGLContext;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.GLBuffers;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
@@ -251,6 +251,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
public void display() {
if (EventQueue.isDispatchThread()) {
// Want display() to be synchronous, so call paintImmediately()
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
index 804e9ee14..aabef29b0 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
@@ -32,7 +32,6 @@ import java.nio.FloatBuffer;
import javax.media.opengl.GL2ES2;
// FIXME: Subsume GL2GL3.GL_DRAW_FRAMEBUFFER -> GL2ES2.GL_DRAW_FRAMEBUFFER !
import javax.media.opengl.GL;
-import javax.media.opengl.GLException;
import javax.media.opengl.GLUniformData;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
@@ -45,7 +44,9 @@ import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderState;
@@ -60,6 +61,7 @@ public class VBORegion2PES2 extends GLRegion {
private FBObject fbo;
+ private TextureAttachment texA;
private PMVMatrix fboPMVMatrix;
GLUniformData mgl_fboPMVMatrix;
@@ -72,7 +74,7 @@ public class VBORegion2PES2 extends GLRegion {
super(renderModes);
fboPMVMatrix = new PMVMatrix();
mgl_fboPMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, fboPMVMatrix.glGetPMvMatrixf());
- mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
+ mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
}
public void update(GL2ES2 gl, RenderState rs) {
@@ -214,8 +216,9 @@ public class VBORegion2PES2 extends GLRegion {
final ShaderState st = rs.getShaderState();
gl.glViewport(0, 0, width, hight);
- st.uniform(gl, mgl_ActiveTexture);
- fbo.use(gl, 0);
+ st.uniform(gl, mgl_ActiveTexture);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + mgl_ActiveTexture.intValue());
+ fbo.use(gl, texA);
verticeFboAttr.enableBuffer(gl, true);
texCoordFboAttr.enableBuffer(gl, true);
indicesFbo.enableBuffer(gl, true);
@@ -244,20 +247,16 @@ public class VBORegion2PES2 extends GLRegion {
// System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5));
if(null != fbo && fbo.getWidth() != tex_width_c && fbo.getHeight() != tex_height_c ) {
- fbo.destroy(gl);
- fbo = null;
+ fbo.reset(gl, tex_width_c, tex_height_c);
}
- if(null == fbo) {
- fbo = new FBObject(tex_width_c, tex_height_c);
- fbo.init(gl);
+ if(null == fbo) {
+ fbo = new FBObject();
+ fbo.reset(gl, tex_width_c, tex_height_c);
// FIXME: shall not use bilinear, due to own AA ? However, w/o bilinear result is not smooth
- fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- // fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- fbo.attachDepthBuffer(gl, GL.GL_DEPTH_COMPONENT16); // FIXME: or shall we use 24 or 32 bit depth ?
- if(!fbo.isStatusValid()) {
- throw new GLException("FBO invalid: "+fbo);
- }
+ texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ // texA = fbo.attachTexture2D(gl, 0, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
} else {
fbo.bind(gl);
}
@@ -305,6 +304,7 @@ public class VBORegion2PES2 extends GLRegion {
if(null != fbo) {
fbo.destroy(gl);
fbo = null;
+ texA = null;
}
if(null != verticeTxtAttr) {
st.ownAttribute(verticeTxtAttr, false);
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index 5c6d7446a..cc4e1b434 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -30,6 +30,8 @@ package jogamp.opengl;
import java.io.PrintStream;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
@@ -46,6 +48,7 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.opengl.util.Animator;
@@ -63,43 +66,69 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
protected final GLDrawableHelper helper = new GLDrawableHelper();
protected final FPSCounterImpl fpsCounter = new FPSCounterImpl();
- protected GLDrawableImpl drawable;
+ protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
protected GLContextImpl context;
+ protected final boolean ownDevice;
protected int additionalCtxCreationFlags = 0;
- protected boolean sendReshape = false;
- protected boolean sendDestroy = false;
+ protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking
+ protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking
- public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context) {
+ /**
+ * @param drawable a valid {@link GLDrawableImpl}, may not be realized yet.
+ * @param context a valid {@link GLContextImpl}, may not be made current (created) yet.
+ * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass <code>false</code>. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ */
+ public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) {
this.drawable = drawable;
this.context = context;
+ this.ownDevice = ownDevice;
resetFPSCounter();
}
+ protected abstract RecursiveLock getLock();
+
/** Returns the delegated GLDrawable */
public final GLDrawable getDelegatedDrawable() { return drawable; }
/** Default implementation to handle repaint events from the windowing system */
- protected void defaultWindowRepaintOp() {
- if( null != drawable && drawable.isRealized() ) {
- if( !drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
+ protected final void defaultWindowRepaintOp() {
+ final GLDrawable _drawable = drawable;
+ if( null != _drawable && _drawable.isRealized() ) {
+ if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
display();
}
- }
+ }
}
/** Default implementation to handle resize events from the windowing system */
- protected void defaultWindowResizedOp() {
- if( null!=drawable ) {
+ protected final void defaultWindowResizedOp() {
+ final GLDrawable _drawable = drawable;
+ if( null!=_drawable ) {
if(DEBUG) {
System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+getWidth()+"x"+getHeight()+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
}
- sendReshape = true;
- defaultWindowRepaintOp();
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
+ if( _drawable.isRealized() ) {
+ if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
+ display();
+ }
+ }
}
}
- /** Default implementation to handle destroy notifications from the windowing system */
- protected void defaultWindowDestroyNotifyOp() {
+ /**
+ * Default implementation to handle destroy notifications from the windowing system.
+ *
+ * <p>
+ * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol}
+ * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default),
+ * {@link #defaultDestroy()} is being called.
+ * </p>
+ */
+ protected final void defaultWindowDestroyNotifyOp() {
final NativeSurface ns = getNativeSurface();
final boolean shallClose;
if(ns instanceof WindowClosingProtocol) {
@@ -108,27 +137,66 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
shallClose = true;
}
if( shallClose ) {
- // Is an animator thread perform rendering?
- if (helper.isExternalAnimatorRunning()) {
- // Pause animations before initiating safe destroy.
- final GLAnimatorControl ctrl = helper.getAnimator();
- final boolean isPaused = ctrl.pause();
- destroy();
- if(isPaused) {
- ctrl.resume();
- }
- } else if (null != ns && ns.isSurfaceLockedByOtherThread()) {
- // surface is locked by another thread
- // Flag that destroy should be performed on the next
- // attempt to display.
- sendDestroy = true;
- } else {
- // Without an external thread animating or locking the
- // surface, we are safe.
- destroy ();
- }
+ destroyAvoidAwareOfLocking();
}
}
+
+ /**
+ * Calls {@link #destroy()}
+ * directly if the following requirements are met:
+ * <ul>
+ * <li>An {@link GLAnimatorControl} is bound (see {@link #getAnimator()}) and running on another thread.
+ * Here we pause the animation while issuing the destruction.</li>
+ * <li>Surface is not locked by another thread (considered anonymous).</li>
+ * </ul>
+ * <p>
+ * Otherwise destroy is being flagged to be called within the next
+ * call of display().
+ * </p>
+ * <p>
+ * This method is being used to avoid deadlock if
+ * destruction is desired by <i>other</i> threads, e.g. the window manager.
+ * </p>
+ * @see #defaultWindowDestroyNotifyOp()
+ * @see #defaultDisplay()
+ */
+ protected final void destroyAvoidAwareOfLocking() {
+ final NativeSurface ns = getNativeSurface();
+
+ final GLAnimatorControl ctrl = helper.getAnimator();
+
+ // Is an animator thread perform rendering?
+ if ( helper.isAnimatorRunningOnOtherThread() ) {
+ // Pause animations before initiating safe destroy.
+ final boolean isPaused = ctrl.pause();
+ destroy();
+ if(isPaused) {
+ ctrl.resume();
+ }
+ } else if (null != ns && ns.isSurfaceLockedByOtherThread()) {
+ // surface is locked by another thread
+ // Flag that destroy should be performed on the next
+ // attempt to display.
+ sendDestroy = true; // async, but avoiding deadlock
+ } else {
+ // Without an external thread animating or locking the
+ // surface, we are safe.
+ destroy();
+ }
+ }
+
+ /**
+ * Calls {@link #destroyImplInLock()} while claiming the lock.
+ */
+ protected final void defaultDestroy() {
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ destroyImplInLock();
+ } finally {
+ lock.unlock();
+ }
+ }
/**
* Default implementation to destroys the drawable and context of this GLAutoDrawable:
@@ -137,24 +205,47 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
* <li>destroys the GLContext, if valid</li>
* <li>destroys the GLDrawable, if valid</li>
* </ul>
+ * <p>Method assumes the lock is being hold.</p>
+ * <p>Override it to extend it to destroy your resources, i.e. the actual window.
+ * In such case call <code>super.destroyImplInLock</code> first.</p>
*/
- protected void defaultDestroyOp() {
- if( null != drawable && drawable.isRealized() ) {
- if( null != context && context.isCreated() ) {
- // Catch dispose GLExceptions by GLEventListener, just 'print' them
- // so we can continue with the destruction.
- try {
- helper.disposeGL(this, drawable, context, null);
- } catch (GLException gle) {
- gle.printStackTrace();
+ protected void destroyImplInLock() {
+ final GLContext _context = context;
+ final GLDrawable _drawable = drawable;
+ if( null != _drawable ) {
+ if( _drawable.isRealized() ) {
+ if( null != _context && _context.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ helper.disposeGL(this, _drawable, _context, null);
+ } catch (GLException gle) {
+ gle.printStackTrace();
+ }
}
+ _drawable.setRealized(false);
+ }
+ if( ownDevice ) {
+ _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close();
}
- drawable.setRealized(false);
}
context = null;
drawable = null;
}
+ public final void defaultSwapBuffers() throws GLException {
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ if(drawable!=null && context != null) {
+ drawable.swapBuffers();
+ helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
//
// GLAutoDrawable
//
@@ -179,6 +270,30 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
fpsCounter.tickFPS();
} };
+ protected final void defaultDisplay() {
+ if( sendDestroy ) {
+ sendDestroy=false;
+ destroy();
+ return;
+ }
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ if( null != context ) {
+ // surface is locked/unlocked implicit by context's makeCurrent/release
+ helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ protected final Runnable defaultSwapAction = new Runnable() {
+ @Override
+ public final void run() {
+ drawable.swapBuffers();
+ } } ;
+
@Override
public final GLContext getContext() {
return context;
@@ -186,27 +301,35 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
@Override
public final GLContext setContext(GLContext newCtx) {
- final GLContext oldCtx = context;
- final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
- context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ final GLContext oldCtx = context;
+ final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ context=(GLContextImpl)newCtx;
+ if(newCtxCurrent) {
+ context.makeCurrent();
+ }
+ return oldCtx;
+ } finally {
+ lock.unlock();
}
- return oldCtx;
}
@Override
public final GL getGL() {
- if (context == null) {
+ final GLContext _context = context;
+ if (_context == null) {
return null;
}
- return context.getGL();
+ return _context.getGL();
}
@Override
public final GL setGL(GL gl) {
- if (context != null) {
- context.setGL(gl);
+ final GLContext _context = context;
+ if (_context != null) {
+ _context.setGL(gl);
return gl;
}
return null;
@@ -261,8 +384,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
@Override
public final void setContextCreationFlags(int flags) {
additionalCtxCreationFlags = flags;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
+ final GLContext _context = context;
+ if(null != _context) {
+ _context.setContextCreationFlags(additionalCtxCreationFlags);
}
}
@@ -331,27 +455,36 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
@Override
public final GLContext createContext(final GLContext shareWith) {
- if(drawable != null) {
- final GLContext _ctx = drawable.createContext(shareWith);
- _ctx.setContextCreationFlags(additionalCtxCreationFlags);
- return _ctx;
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ if(drawable != null) {
+ final GLContext _ctx = drawable.createContext(shareWith);
+ _ctx.setContextCreationFlags(additionalCtxCreationFlags);
+ return _ctx;
+ }
+ return null;
+ } finally {
+ lock.unlock();
}
- return null;
}
@Override
public final boolean isRealized() {
- return null != drawable ? drawable.isRealized() : false;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isRealized() : false;
}
@Override
public int getWidth() {
- return null != drawable ? drawable.getWidth() : 0;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getWidth() : 0;
}
@Override
public int getHeight() {
- return null != drawable ? drawable.getHeight() : 0;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getHeight() : 0;
}
/**
@@ -374,29 +507,26 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
- public final void swapBuffers() throws GLException {
- if(drawable!=null && context != null) {
- drawable.swapBuffers();
- }
- }
-
- @Override
public final GLCapabilitiesImmutable getChosenGLCapabilities() {
- return null != drawable ? drawable.getChosenGLCapabilities() : null;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getChosenGLCapabilities() : null;
}
@Override
public final GLProfile getGLProfile() {
- return null != drawable ? drawable.getGLProfile() : null;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getGLProfile() : null;
}
@Override
public final NativeSurface getNativeSurface() {
- return null != drawable ? drawable.getNativeSurface() : null;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getNativeSurface() : null;
}
@Override
public final long getHandle() {
- return null != drawable ? drawable.getHandle() : 0;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getHandle() : 0;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 4dd8806fa..bf6a0ee6e 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -49,8 +49,9 @@ import com.jogamp.common.os.DynamicLookupHelper;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.gluegen.runtime.FunctionAddressResolver;
import com.jogamp.gluegen.runtime.ProcAddressTable;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -88,13 +89,14 @@ public abstract class GLContextImpl extends GLContext {
// Tracks creation and initialization of buffer objects to avoid
// repeated glGet calls upon glMapBuffer operations
private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet
- private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
- private GLStateTracker glStateTracker = new GLStateTracker();
+ private final GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
+ private final GLStateTracker glStateTracker = new GLStateTracker();
private GLDebugMessageHandler glDebugHandler = null;
+ private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read }
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
-
+
protected GL gl;
protected static final Object mappedContextTypeObjectLock;
@@ -140,11 +142,11 @@ public abstract class GLContextImpl extends GLContext {
bufferSizeTracker.clearCachedBufferSizes();
}
- if (bufferStateTracker != null) {
+ if (bufferStateTracker != null) { // <init>
bufferStateTracker.clearBufferObjectState();
}
- if (glStateTracker != null) {
+ if (glStateTracker != null) { // <init>
glStateTracker.clearStates(false);
}
@@ -156,6 +158,11 @@ public abstract class GLContextImpl extends GLContext {
glRenderer = "";
glRendererLowerCase = glRenderer;
+
+ if (boundFBOTarget != null) { // <init>
+ boundFBOTarget[0] = 0; // draw
+ boundFBOTarget[1] = 0; // read
+ }
super.resetStates();
}
@@ -199,7 +206,7 @@ public abstract class GLContextImpl extends GLContext {
drawableRead = (GLDrawableImpl) readWrite;
}
final GLDrawable old = drawable;
- drawable = ( null != readWrite ) ? (GLDrawableImpl) readWrite : null;
+ drawable = (GLDrawableImpl) readWrite ;
if(lockHeld) {
makeCurrent();
}
@@ -252,16 +259,19 @@ public abstract class GLContextImpl extends GLContext {
public void release() throws GLException {
release(false);
}
- private void release(boolean force) throws GLException {
+ private void release(boolean inDestruction) throws GLException {
if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - release() - force: "+force+", "+lock);
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - release() - force: "+inDestruction+", "+lock);
}
if ( !lock.isOwner(Thread.currentThread()) ) {
throw new GLException("Context not current on current thread "+Thread.currentThread().getName()+": "+this);
}
- final boolean actualRelease = ( force || lock.getHoldCount() == 1 ) && 0 != contextHandle;
+ final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle;
try {
if( actualRelease ) {
+ if( !inDestruction ) {
+ drawable.contextMadeCurrent(this, false);
+ }
releaseImpl();
}
} finally {
@@ -306,13 +316,12 @@ public abstract class GLContextImpl extends GLContext {
}
try {
// release current context
- if(null != glDebugHandler) {
- if(lock.getHoldCount() == 1) {
- // needs current context to disable debug handler
- makeCurrent();
- }
- glDebugHandler.enable(false);
+ if(lock.getHoldCount() == 1) {
+ // needs current context to disable debug handler
+ makeCurrent();
}
+ drawable.contextRealized(this, false);
+ glDebugHandler.enable(false);
if(lock.getHoldCount() > 1) {
// pending release() after makeCurrent()
release(true);
@@ -329,7 +338,6 @@ public abstract class GLContextImpl extends GLContext {
if (TRACE_SWITCH) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
- Thread.dumpStack(); // JAU
}
}
} finally {
@@ -488,11 +496,18 @@ public abstract class GLContextImpl extends GLContext {
if(TRACE_GL) {
gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
}
+
+ drawable.contextRealized(this, true);
+
if(DEBUG || TRACE_SWITCH) {
System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT_NEW - "+lock);
}
- } else if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock);
+ } else {
+ drawable.contextMadeCurrent(this, true);
+
+ if(TRACE_SWITCH) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock);
+ }
}
/* FIXME: refactor dependence on Java 2D / JOGL bridge
@@ -543,14 +558,11 @@ public abstract class GLContextImpl extends GLContext {
final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
- if( !GLContext.getAvailableGLVersionsSet(device) ) {
- final int reqMajor;
- final int reqProfile;
- if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_ES) ) {
- // ES1 or ES2
- reqMajor = ctxMajorVersion;
- reqProfile = GLContext.CTX_PROFILE_ES;
- } else {
+ // Non ARB desktop profiles may not have been registered
+ if( !GLContext.getAvailableGLVersionsSet(device) ) { // not yet set
+ if( 0 == ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { // not ES profile
+ final int reqMajor;
+ final int reqProfile;
if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) {
reqMajor = 2;
} else {
@@ -561,12 +573,13 @@ public abstract class GLContextImpl extends GLContext {
} else {
reqProfile = GLContext.CTX_PROFILE_COMPAT;
}
- }
- GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
- ctxMajorVersion, ctxMinorVersion, ctxOptions);
- GLContext.setAvailableGLVersionsSet(device);
- if (DEBUG) {
- System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion());
+ GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
+ ctxMajorVersion, ctxMinorVersion, ctxOptions);
+ GLContext.setAvailableGLVersionsSet(device);
+
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion());
+ }
}
}
}
@@ -776,7 +789,7 @@ public abstract class GLContextImpl extends GLContext {
}
/**
- * Note: Since context creation is temproary, caller need to issue {@link #resetStates()}, if creation was successful, i.e. returns true.
+ * Note: Since context creation is temporary, caller need to issue {@link #resetStates()}, if creation was successful, i.e. returns true.
* This method does not reset the states, allowing the caller to utilize the state variables.
**/
private final boolean createContextARBMapVersionsAvailable(int reqMajor, int reqProfile) {
@@ -1034,22 +1047,29 @@ public abstract class GLContextImpl extends GLContext {
table.reset(getDrawableImpl().getGLDynamicLookupHelper() );
}
- private final void initGLRendererStrings() {
+ private final boolean initGLRendererStrings() {
final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString");
if(0 == _glGetString) {
// FIXME
System.err.println("Warning: Entry point to 'glGetString' is NULL.");
- Thread.dumpStack();
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ return false;
} else {
final String _glRenderer = glGetStringInt(GL.GL_RENDERER, _glGetString);
if(null == _glRenderer) {
// FIXME
- System.err.println("Warning: GL_RENDERER is NULL.");
- Thread.dumpStack();
+ if(DEBUG) {
+ System.err.println("Warning: GL_RENDERER is NULL.");
+ Thread.dumpStack();
+ }
+ return false;
} else {
glRenderer = _glRenderer;
glRendererLowerCase = glRenderer.toLowerCase();
+ return true;
}
}
}
@@ -1088,17 +1108,20 @@ public abstract class GLContextImpl extends GLContext {
}
updateGLXProcAddressTable();
- initGLRendererStrings();
+ final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
+
+ if( !initGLRendererStrings() && DEBUG) {
+ System.err.println("Warning: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+ }
if(!isCurrentContextHardwareRasterizer()) {
ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
}
- final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
- final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits);
if (DEBUG) {
- System.err.println(getThreadName() + ": Context FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
}
//
@@ -1154,11 +1177,10 @@ public abstract class GLContextImpl extends GLContext {
}
}
- if( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && ctxMajorVersion >= 2 ||
- isExtensionAvailable(GL_ARB_ES2_compatibility) ) {
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && major >= 2 ) || isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) ) {
ctxProfileBits |= CTX_IMPL_ES2_COMPAT;
ctxProfileBits |= CTX_IMPL_FBO;
- } else if( hasFBOImpl(ctxMajorVersion, ctxProfileBits, extensionAvailability) ) {
+ } else if( hasFBOImpl(major, ctxProfileBits, extensionAvailability) ) {
ctxProfileBits |= CTX_IMPL_FBO;
}
@@ -1168,23 +1190,26 @@ public abstract class GLContextImpl extends GLContext {
setContextVersion(major, minor, ctxProfileBits, true);
setDefaultSwapInterval();
+
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null));
+ }
}
- protected static final boolean hasFBOImpl(int ctxMajorVersion, int ctxProfileBits, ExtensionAvailabilityCache extCache) {
- return ( ctxMajorVersion >= 3 ) || // any >= 3.0 GL ctx
+ protected static final boolean hasFBOImpl(int major, int ctp, ExtensionAvailabilityCache extCache) {
+ return ( 0 != (ctp & CTX_PROFILE_ES) && major >= 2 ) || // ES >= 2.0
- ( 0 != (ctxProfileBits & CTX_PROFILE_ES) && ctxMajorVersion >= 2 ) || // ES >= 2.0
+ major >= 3 || // any >= 3.0 GL ctx
( null != extCache &&
- ( extCache.isExtensionAvailable(GL_ARB_ES2_compatibility) ) || // ES 2.0 compatible
+ extCache.isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) || // ES 2.0 compatible
- ( extCache.isExtensionAvailable(GL_ARB_framebuffer_object) ) || // ARB_framebuffer_object
+ extCache.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
- ( extCache.isExtensionAvailable(GL_EXT_framebuffer_object) && // EXT_framebuffer_object*
- extCache.isExtensionAvailable(GL_EXT_framebuffer_multisample) &&
- extCache.isExtensionAvailable(GL_EXT_framebuffer_blit) &&
- extCache.isExtensionAvailable(GL_EXT_packed_depth_stencil) ) );
+ extCache.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) || // EXT_framebuffer_object
+
+ extCache.isExtensionAvailable(GLExtensions.OES_framebuffer_object) ) ; // OES_framebuffer_object excluded
}
protected final void removeCachedVersion(int major, int minor, int ctxProfileBits) {
@@ -1259,11 +1284,11 @@ public abstract class GLContextImpl extends GLContext {
// dynamic function lookup at last incl name aliasing (not cached)
DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
- String tmpBase = GLExtensionNames.normalizeVEN(GLExtensionNames.normalizeARB(glFunctionName, true), true);
+ String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
long addr = 0;
- int variants = GLExtensionNames.getFuncNamePermutationNumber(tmpBase);
+ int variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase);
for(int i = 0; 0==addr && i < variants; i++) {
- String tmp = GLExtensionNames.getFuncNamePermutation(tmpBase, i);
+ String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
try {
addr = dynLookup.dynamicLookupFunction(tmp);
} catch (Exception e) { }
@@ -1317,7 +1342,7 @@ public abstract class GLContextImpl extends GLContext {
protected static String getContextFQN(AbstractGraphicsDevice device, int major, int minor, int ctxProfileBits) {
// remove non-key values
- ctxProfileBits &= ~( GLContext.CTX_OPTION_DEBUG | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) ;
+ ctxProfileBits &= ~( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) ;
return device.getUniqueID() + "-" + toHexString(composeBits(major, minor, ctxProfileBits));
}
@@ -1372,6 +1397,56 @@ public abstract class GLContextImpl extends GLContext {
}
//---------------------------------------------------------------------------
+ // Special FBO hook
+ //
+
+ /**
+ * Tracks {@link GL#GL_FRAMEBUFFER}, {@link GL2GL3#GL_DRAW_FRAMEBUFFER} and {@link GL2GL3#GL_READ_FRAMEBUFFER}
+ * to be returned via {@link #getBoundFramebuffer(int)}.
+ *
+ * <p>Invoked by {@link GL#glBindFramebuffer(int, int)}. </p>
+ *
+ * <p>Assumes valid <code>framebufferName</code> range of [0..{@link Integer#MAX_VALUE}]</p>
+ *
+ * <p>Does not throw an exception if <code>target</code> is unknown or <code>framebufferName</code> invalid.</p>
+ */
+ public final void setBoundFramebuffer(int target, int framebufferName) {
+ if(0 > framebufferName) {
+ return; // ignore invalid name
+ }
+ switch(target) {
+ case GL.GL_FRAMEBUFFER:
+ boundFBOTarget[0] = framebufferName; // draw
+ boundFBOTarget[1] = framebufferName; // read
+ break;
+ case GL2GL3.GL_DRAW_FRAMEBUFFER:
+ boundFBOTarget[0] = framebufferName; // draw
+ break;
+ case GL2GL3.GL_READ_FRAMEBUFFER:
+ boundFBOTarget[1] = framebufferName; // read
+ break;
+ default: // ignore untracked target
+ }
+ }
+ @Override
+ public final int getBoundFramebuffer(int target) {
+ switch(target) {
+ case GL.GL_FRAMEBUFFER:
+ case GL2GL3.GL_DRAW_FRAMEBUFFER:
+ return boundFBOTarget[0]; // draw
+ case GL2GL3.GL_READ_FRAMEBUFFER:
+ return boundFBOTarget[1]; // read
+ default:
+ throw new InternalError("Invalid FBO target name: "+toHexString(target));
+ }
+ }
+
+ @Override
+ public final int getDefaultDrawFramebuffer() { return drawable.getDefaultDrawFramebuffer(); }
+ @Override
+ public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }
+
+ //---------------------------------------------------------------------------
// GL_ARB_debug_output, GL_AMD_debug_output helpers
//
diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
index b950c2fdf..0000e6199 100644
--- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
+++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
@@ -37,6 +37,8 @@ import javax.media.opengl.GLException;
import com.jogamp.common.os.Platform;
import com.jogamp.gluegen.runtime.ProcAddressTable;
+import com.jogamp.opengl.GLExtensions;
+
import jogamp.opengl.gl4.GL4bcProcAddressTable;
/**
@@ -54,12 +56,6 @@ import jogamp.opengl.gl4.GL4bcProcAddressTable;
* the messages are translated to <i>ARB</i> {@link GLDebugMessage}, using {@link GLDebugMessage#translateAMDEvent(javax.media.opengl.GLContext, long, int, int, int, String)}.</p>
*/
public class GLDebugMessageHandler {
- /** Extension <i>GL_ARB_debug_output</i> implementing GLDebugMessage */
- public static final String GL_ARB_debug_output = "GL_ARB_debug_output".intern();
-
- /** Extension <i>GL_AMD_debug_output</i> implementing GLDebugMessage */
- public static final String GL_AMD_debug_output = "GL_AMD_debug_output".intern();
-
private static final boolean DEBUG = Debug.debug("GLDebugMessageHandler");
private static final int EXT_ARB = 1;
@@ -131,11 +127,11 @@ public class GLDebugMessageHandler {
}
return;
}
- if( ctx.isExtensionAvailable(GL_ARB_debug_output) ) {
- extName = GL_ARB_debug_output;
+ if( ctx.isExtensionAvailable(GLExtensions.ARB_debug_output) ) {
+ extName = GLExtensions.ARB_debug_output;
extType = EXT_ARB;
- } else if( ctx.isExtensionAvailable(GL_AMD_debug_output) ) {
- extName = GL_AMD_debug_output;
+ } else if( ctx.isExtensionAvailable(GLExtensions.AMD_debug_output) ) {
+ extName = GLExtensions.AMD_debug_output;
extType = EXT_AMD;
}
if(DEBUG) {
@@ -145,6 +141,8 @@ public class GLDebugMessageHandler {
if(0 == extType) {
if(DEBUG) {
System.err.println("GLDebugMessageHandler: No extension available! "+ctx.getGLVersion());
+ System.err.println("GL_EXTENSIONS "+ctx.getGLExtensionCount());
+ System.err.println(ctx.getGLExtensionsString());
}
return;
}
@@ -190,11 +188,11 @@ public class GLDebugMessageHandler {
}
public final boolean isExtensionARB() {
- return extName == GL_ARB_debug_output;
+ return extName == GLExtensions.ARB_debug_output;
}
public final boolean isExtensionAMD() {
- return extName == GL_AMD_debug_output;
+ return extName == GLExtensions.AMD_debug_output;
}
/**
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index e5c44a8d4..f7808294b 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -47,7 +47,8 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -88,7 +89,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
return null;
}
protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device);
-
+
/**
* Returns the shared device mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
* either a preexisting or newly created, or <code>null</code> if creation failed or not supported.<br>
@@ -115,7 +116,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
}
protected abstract AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device);
- /**
+ /**
* Returns the GLDynamicLookupHelper
* @param profile if EGL/ES, profile <code>1</code> refers to ES1 and <code>2</code> to ES2,
* otherwise the profile is ignored.
@@ -125,6 +126,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
// Dispatching GLDrawable construction in respect to the NativeSurface Capabilities
//
+ @Override
public GLDrawable createGLDrawable(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -132,23 +134,38 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration();
final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
final AbstractGraphicsDevice adevice = config.getScreen().getDevice();
+ final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile());
GLDrawable result = null;
adevice.lock();
try {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
- // layered surface -> Offscreen/PBuffer
+ // layered surface -> Offscreen/[FBO|PBuffer]
final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable();
chosenCapsMod.setOnscreen(false);
- chosenCapsMod.setPBuffer(canCreateGLPbuffer(adevice));
+ /* if( isFBOAvailable ) { // FIXME JAU: FBO n/a yet
+ chosenCapsMod.setFBO(true);
+ } else */
+ if( canCreateGLPbuffer(adevice) ) {
+ chosenCapsMod.setPBuffer(true);
+ } else {
+ chosenCapsMod.setFBO(false);
+ chosenCapsMod.setPBuffer(false);
+ }
config.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
+ }
+ if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
+ // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
+ result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ } else {
+ result = createOffscreenDrawableImpl(target);
}
- result = createOffscreenDrawableImpl(target);
} else if(chosenCaps.isOnscreen()) {
// onscreen
if(DEBUG) {
@@ -158,12 +175,18 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
} else {
// offscreen
if(DEBUG) {
- System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+chosenCaps.isPBuffer()+"): "+target);
+ System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO-chosen(-avail)/PBuffer: "+chosenCaps.isFBO()+"("+isFBOAvailable+")/"+chosenCaps.isPBuffer()+": "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target);
}
- result = createOffscreenDrawableImpl(target);
+ if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
+ // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
+ result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ } else {
+ result = createOffscreenDrawableImpl(target);
+ }
}
} finally {
adevice.unlock();
@@ -176,43 +199,42 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
//
- // Onscreen GLDrawable construction
+ // Onscreen GLDrawable construction
//
protected abstract GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target);
//---------------------------------------------------------------------------
//
- // PBuffer Offscreen GLDrawable construction
+ // PBuffer Offscreen GLDrawable construction
//
-
+
+ @Override
public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
+ @Override
public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
int width,
int height,
GLContext shareWith) {
- if(height<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ if(width<=0 || height<=0) {
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
-
AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
-
- if (!canCreateGLPbuffer(device)) {
- throw new GLException("Pbuffer support not available with device: "+device);
+ if ( !canCreateGLPbuffer(device) ) {
+ throw new GLException("Pbuffer not available with device: "+device);
}
-
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
GLDrawableImpl drawable = null;
device.lock();
try {
- drawable = (GLDrawableImpl) createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
+ drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
if(null != drawable) {
drawable.setRealized(true);
}
@@ -223,80 +245,163 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
if(null==drawable) {
throw new GLException("Could not create Pbuffer drawable for: "+device+", "+capsChosen+", "+width+"x"+height);
}
- return new GLPbufferImpl( drawable, shareWith);
+ return new GLPbufferImpl( drawable, shareWith, true);
}
//---------------------------------------------------------------------------
//
- // Offscreen GLDrawable construction
+ // Offscreen GLDrawable construction
//
- protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
-
+ @Override
public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
- int width,
- int height) {
+ int width, int height) {
if(width<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
+
+ if( capsRequested.isFBO() && GLContext.isFBOAvailable(device, capsRequested.getGLProfile()) ) {
+ device.lock();
+ try {
+ return createFBODrawableImpl(device, capsRequested, chooser, width, height);
+ } finally {
+ device.unlock();
+ }
+ }
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, false, canCreateGLPbuffer(device));
device.lock();
try {
- return createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
+ return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
} finally {
device.unlock();
}
}
- public NativeSurface createOffscreenSurface(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ /** Creates a platform independent offscreen FBO GLDrawable implementation */
+ protected GLDrawable createFBODrawableImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int initialWidth, int initialHeight) {
+ final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ final NativeSurface dummySurface = createDummySurfaceImpl(device, true, dummyCaps, null, 64, 64);
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
+
+ return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */);
+ }
+
+ /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */
+ protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
+
+ /**
+ * Creates a mutable {@link ProxySurface} w/o defined surface handle.
+ * <p>
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}.
+ * </p>
+ * <p>
+ * Lifecycle (destruction) of the TBD surface handle shall be handled by the caller.
+ * </p>
+ * @param device a valid platform dependent target device.
+ * @param createNewDevice if <code>true</code> a new device instance is created using <code>device</code> details,
+ * otherwise <code>device</code> instance is used as-is.
+ * @param capsChosen
+ * @param capsRequested
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ * @param lifecycleHook optional control of the surface's lifecycle
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
+ */
+ protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook);
+
+ /**
+ * A dummy surface is not visible on screen and will not be used to render directly to,
+ * it maybe on- or offscreen.
+ * <p>
+ * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information.
+ * It also allows creation of framebuffer objects which are used for rendering.
+ * </p>
+ * @param deviceReq which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param requestedCaps
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ *
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
+ */
+ public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int width, int height) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
device.lock();
try {
- return createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height);
+ return createDummySurfaceImpl(device, true, requestedCaps, chooser, width, height);
} finally {
device.unlock();
}
}
-
+
/**
- * creates an offscreen NativeSurface, which must implement SurfaceChangeable as well,
- * so the windowing system related implementation is able to set the surface handle.
+ * A dummy surface is not visible on screen and will not be used to render directly to,
+ * it maybe on- or offscreen.
+ * <p>
+ * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information.
+ * It also allows creation of framebuffer objects which are used for rendering.
+ * </p>
+ * @param device a valid platform dependent target device.
+ * @param createNewDevice if <code>true</code> a new device instance is created using <code>device</code> details,
+ * otherwise <code>device</code> instance is used as-is.
+ * @param requestedCaps
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
*/
- protected abstract NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height);
+ public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);
- public ProxySurface createProxySurface(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ //---------------------------------------------------------------------------
+ //
+ // ProxySurface (Wrapped pre-existing native surface) construction
+ //
+
+ @Override
+ public ProxySurface createProxySurface(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
+ GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
- throw new GLException("No shared device for requested: "+device);
+ throw new GLException("No shared device for requested: "+deviceReq);
+ }
+ if(0 == windowHandle) {
+ throw new IllegalArgumentException("Null windowHandle");
}
device.lock();
try {
- return createProxySurfaceImpl(device, windowHandle, capsRequested, chooser);
+ return createProxySurfaceImpl(device, screenIdx, windowHandle, capsRequested, chooser, upstream);
} finally {
device.unlock();
}
- }
-
- protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+ }
+
+ /**
+ * Creates a {@link ProxySurface} with a set surface handle.
+ * <p>
+ * Implementation is also required to allocate it's own {@link AbstractGraphicsDevice} instance.
+ * </p>
+ * @param upstream TODO
+ */
+ protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
+ GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
//---------------------------------------------------------------------------
//
@@ -304,7 +409,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//
protected abstract GLContext createExternalGLContextImpl();
-
+
+ @Override
public GLContext createExternalGLContext() {
NativeWindowFactory.getDefaultToolkitLock().lock();
try {
@@ -316,6 +422,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
protected abstract GLDrawable createExternalGLDrawableImpl();
+ @Override
public GLDrawable createExternalGLDrawable() {
NativeWindowFactory.getDefaultToolkitLock().lock();
try {
@@ -398,7 +505,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* normal ahead of time, use resetDisplayGamma(). Throws
* IllegalArgumentException if any of the parameters were
* out-of-bounds.
- *
+ *
* @param gamma The gamma value, typically > 1.0 (default value is
* 1.0)
* @param brightness The brightness value between -1.0 and 1.0,
@@ -484,7 +591,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
return;
if (gammaShutdownHook == null) {
gammaShutdownHook = new Thread(new Runnable() {
- public void run() {
+ @Override
+ public void run() {
synchronized (GLDrawableFactoryImpl.this) {
resetGammaRamp(originalGammaRamp);
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 0c01aa676..090c5fe69 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -189,8 +189,9 @@ public class GLDrawableHelper {
*/
public final void dispose(GLAutoDrawable drawable) {
synchronized(listenersLock) {
- for (int i=0; i < listeners.size(); i++) {
- listeners.get(i).dispose(drawable);
+ final ArrayList<GLEventListener> _listeners = listeners;
+ for (int i=0; i < _listeners.size(); i++) {
+ _listeners.get(i).dispose(drawable);
}
}
}
@@ -209,8 +210,9 @@ public class GLDrawableHelper {
/** The default init action to be called once after ctx is being created @ 1st makeCurrent(). */
public final void init(GLAutoDrawable drawable) {
synchronized(listenersLock) {
- for (int i=0; i < listeners.size(); i++) {
- final GLEventListener listener = listeners.get(i) ;
+ final ArrayList<GLEventListener> _listeners = listeners;
+ for (int i=0; i < _listeners.size(); i++) {
+ final GLEventListener listener = _listeners.get(i) ;
// If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called.
// This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window),
@@ -232,8 +234,9 @@ public class GLDrawableHelper {
}
private final void displayImpl(GLAutoDrawable drawable) {
synchronized(listenersLock) {
- for (int i=0; i < listeners.size(); i++) {
- final GLEventListener listener = listeners.get(i) ;
+ final ArrayList<GLEventListener> _listeners = listeners;
+ for (int i=0; i < _listeners.size(); i++) {
+ final GLEventListener listener = _listeners.get(i) ;
// GLEventListener may need to be init,
// in case this one is added after the realization of the GLAutoDrawable
init( listener, drawable, true /* sendReshape */) ;
@@ -324,7 +327,7 @@ public class GLDrawableHelper {
}
}
- public final boolean isExternalAnimatorRunning() {
+ public final boolean isAnimatorRunningOnOtherThread() {
return ( null != animatorCtrl ) ? animatorCtrl.isStarted() && animatorCtrl.getThread() != Thread.currentThread() : false ;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index 58a4ac6b4..abf2bf557 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -42,6 +42,7 @@ package jogamp.opengl;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
@@ -75,7 +76,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
if( !realized ) {
return; // destroyed already
}
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
if ( caps.getDoubleBuffered() ) {
if(!surface.surfaceSwap()) {
int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
@@ -149,6 +150,9 @@ public abstract class GLDrawableImpl implements GLDrawable {
realized = realizedArg;
AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice();
if(realizedArg) {
+ if(surface instanceof ProxySurface) {
+ ((ProxySurface)surface).createNotify();
+ }
if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) {
throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)");
}
@@ -156,17 +160,21 @@ public abstract class GLDrawableImpl implements GLDrawable {
aDevice.lock();
}
try {
- setRealizedImpl();
if(realizedArg) {
+ setRealizedImpl();
updateHandle();
} else {
destroyHandle();
+ setRealizedImpl();
}
} finally {
if(realizedArg) {
unlockSurface();
} else {
aDevice.unlock();
+ if(surface instanceof ProxySurface) {
+ ((ProxySurface)surface).destroyNotify();
+ }
}
}
} else if(DEBUG) {
@@ -175,6 +183,39 @@ public abstract class GLDrawableImpl implements GLDrawable {
}
protected abstract void setRealizedImpl();
+ /**
+ * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: <code>construct</code>, <code>destroy</code>.
+ * <p>
+ * If <code>realized</code> is <code>true</code>, the context has just been created and made current.
+ * </p>
+ * <p>
+ * If <code>realized</code> is <code>false</code>, the context is still current and will be release and destroyed after this method returns.
+ * </p>
+ * <p>
+ * @see #contextMadeCurrent(GLContext, boolean)
+ */
+ protected void contextRealized(GLContext glc, boolean realized) {}
+
+ /**
+ * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: <code>makeCurrent</code>, <code>release</code>.
+ * <p>
+ * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered.
+ * </p>
+ * <p>
+ * If <code>current</code> is <code>true</code>, the context has just been made current.
+ * </p>
+ * <p>
+ * If <code>current</code> is <code>false</code>, the context is still current and will be release after this method returns.
+ * </p>
+ * @see #contextRealized(GLContext, boolean)
+ */
+ protected void contextMadeCurrent(GLContext glc, boolean current) { }
+
+ /** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/
+ protected int getDefaultDrawFramebuffer() { return 0; }
+ /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
+ protected int getDefaultReadFramebuffer() { return 0; }
+
@Override
public final synchronized boolean isRealized() {
return realized;
@@ -190,10 +231,12 @@ public abstract class GLDrawableImpl implements GLDrawable {
return surface.getHeight();
}
+ /** @see NativeSurface#lockSurface() */
public final int lockSurface() throws GLException {
return surface.lockSurface();
}
+ /** @see NativeSurface#unlockSurface() */
public final void unlockSurface() {
surface.unlockSurface();
}
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
new file mode 100644
index 000000000..b7ea4f826
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -0,0 +1,138 @@
+package jogamp.opengl;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
+
+/**
+ * Offscreen GLDrawable implementation using framebuffer object (FBO)
+ * as it's offscreen rendering mechanism.
+ *
+ * @see GLDrawableImpl#contextRealized(GLContext, boolean)
+ * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean)
+ * @see GLDrawableImpl#getDefaultDrawFramebuffer()
+ * @see GLDrawableImpl#getDefaultReadFramebuffer()
+ */
+public class GLFBODrawableImpl extends GLDrawableImpl {
+ final GLDrawableImpl parent;
+ final FBObject fbo;
+ int texUnit;
+ int samplesTexUnit = 0;
+ int width=0, height=0, samples=0;
+
+ protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent,
+ NativeSurface surface, int initialWidth, int initialHeight, int textureUnit) {
+ super(factory, surface, false);
+ this.parent = parent;
+ this.texUnit = textureUnit;
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
+ this.width = initialWidth;
+ this.height = initialHeight;
+ this.samples = caps.getNumSamples();
+ this.fbo = new FBObject();
+ }
+
+ @Override
+ protected void contextRealized(GLContext glc, boolean realized) {
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
+ final GL gl = glc.getGL();
+ if(realized) {
+ fbo.reset(gl, width, height, samples);
+ samples = fbo.getNumSamples(); // update, maybe capped
+ if(samples > 0) {
+ fbo.attachColorbuffer(gl, 0, caps.getAlphaBits()>0);
+ } else {
+ fbo.attachTexture2D(gl, 0, caps.getAlphaBits()>0);
+ }
+ if( caps.getStencilBits() > 0 ) {
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24);
+ } else {
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ }
+ } else if(null != fbo) {
+ fbo.destroy(gl);
+ }
+ }
+
+ @Override
+ protected void contextMadeCurrent(GLContext glc, boolean current) {
+ final GL gl = glc.getGL();
+ if(current) {
+ fbo.bind(gl);
+ } else {
+ fbo.unbind(gl);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
+ fbo.use(gl, samples > 0 ? fbo.getSamplingSink() : (TextureAttachment) fbo.getColorbuffer(0) );
+ if( samples > 0) {
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbo.getReadFramebuffer());
+ }
+ }
+ }
+
+ @Override
+ protected int getDefaultDrawFramebuffer() { return fbo.getWriteFramebuffer(); }
+
+ @Override
+ protected int getDefaultReadFramebuffer() { return fbo.getReadFramebuffer(); }
+
+ public FBObject getFBObject() { return fbo; }
+
+ public void setSize(GL gl, int newWidth, int newHeight) throws GLException {
+ width = newWidth;
+ height = newHeight;
+ fbo.reset(gl, width, height, samples);
+ samples = fbo.getNumSamples(); // update, maybe capped
+ }
+
+ public void setSamples(GL gl, int newSamples) throws GLException {
+ samples = newSamples;
+ fbo.reset(gl, width, height, samples);
+ samples = fbo.getNumSamples(); // update, maybe capped
+ }
+
+
+ @Override
+ public GLContext createContext(GLContext shareWith) {
+ final GLContext ctx = parent.createContext(shareWith);
+ ctx.setGLDrawable(this, false);
+ return ctx;
+ }
+
+ @Override
+ public GLDynamicLookupHelper getGLDynamicLookupHelper() {
+ return parent.getGLDynamicLookupHelper();
+ }
+
+ @Override
+ protected void swapBuffersImpl() {
+ }
+
+ @Override
+ protected void setRealizedImpl() {
+ parent.setRealized(realized);
+ if(realized) {
+ final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) msConfig.getChosenCapabilities();
+ final GLCapabilitiesImmutable chosenFBOCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, true /*FBO*/, false /*PBO*/);
+ msConfig.setChosenCapabilities(chosenFBOCaps);
+ }
+ }
+
+ @Override
+ public int getWidth() {
+ return width;
+ }
+
+ @Override
+ public int getHeight() {
+ return height;
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
index b7c15bfda..3f38f33bc 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
@@ -38,7 +38,8 @@ public class GLGraphicsConfigurationUtil {
public static final int WINDOW_BIT = 1 << 0;
public static final int BITMAP_BIT = 1 << 1;
public static final int PBUFFER_BIT = 1 << 2;
- public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT ;
+ public static final int FBO_BIT = 1 << 3;
+ public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT | FBO_BIT ;
public static final StringBuilder winAttributeBits2String(StringBuilder sb, int winattrbits) {
if(null==sb) {
@@ -61,30 +62,43 @@ public class GLGraphicsConfigurationUtil {
sb.append(", ");
}
sb.append("PBUFFER");
+ seperator=true;
+ }
+ if( 0 != ( FBO_BIT & winattrbits ) ) {
+ if(seperator) {
+ sb.append(", ");
+ }
+ sb.append("FBO");
}
return sb;
}
/**
+ * @param isFBO TODO
* @return bitmask representing the input boolean in exclusive or logic, ie only one bit will be set
*/
- public static final int getWinAttributeBits(boolean isOnscreen, boolean isPBuffer) {
+ public static final int getWinAttributeBits(boolean isOnscreen, boolean isPBuffer, boolean isFBO) {
int winattrbits = 0;
if(isOnscreen) {
winattrbits |= WINDOW_BIT;
- } else if (!isPBuffer) {
- winattrbits |= BITMAP_BIT;
} else {
- winattrbits |= PBUFFER_BIT;
+ if(isFBO) {
+ winattrbits |= FBO_BIT;
+ }
+ if (!isPBuffer) {
+ winattrbits |= BITMAP_BIT;
+ } else {
+ winattrbits |= PBUFFER_BIT;
+ }
}
return winattrbits;
}
/**
- * @see #getWinAttributeBits(boolean, boolean)
+ * @see #getWinAttributeBits(boolean, boolean, boolean)
*/
public static final int getWinAttributeBits(GLCapabilitiesImmutable caps) {
- return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer());
+ return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer(), false);
}
public static final boolean addGLCapabilitiesPermutations(List<GLCapabilitiesImmutable> capsBucket, GLCapabilitiesImmutable temp, int winattrbits) {
@@ -92,43 +106,58 @@ public class GLGraphicsConfigurationUtil {
if( 0 != ( WINDOW_BIT & winattrbits ) ) {
GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
cpy.setOnscreen(true);
+ cpy.setPBuffer(false);
+ cpy.setFBO(false);
capsBucket.add(cpy);
}
- if( 0 != ( PBUFFER_BIT & winattrbits ) ) {
+ if( 0 != ( PBUFFER_BIT & winattrbits ) || 0 != ( FBO_BIT & winattrbits ) ) {
GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
- cpy.setPBuffer(true);
+ cpy.setFBO(0 != ( FBO_BIT & winattrbits ));
+ cpy.setPBuffer(0 != ( PBUFFER_BIT & winattrbits ));
capsBucket.add(cpy);
}
if( 0 != ( BITMAP_BIT & winattrbits ) ) {
GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
cpy.setOnscreen(false);
cpy.setPBuffer(false);
+ cpy.setFBO(false);
capsBucket.add(cpy);
}
return capsBucket.size() > preSize;
}
- public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable)
+ public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable)
{
if( !capsRequested.isOnscreen() ) {
- return fixOffScreenGLCapabilities(capsRequested, pbufferAvailable);
+ return fixOffscreenGLCapabilities(capsRequested, fboAvailable, pbufferAvailable);
}
- return capsRequested;
+ return fixOnscreenGLCapabilities(capsRequested);
}
- public static GLCapabilitiesImmutable fixOffScreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable)
+ public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested)
+ {
+ if( !capsRequested.isOnscreen() ) {
+ // fix caps ..
+ GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
+ caps2.setOnscreen(true);
+ return caps2;
+ }
+ return capsRequested;
+ }
+
+ public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable)
{
if( capsRequested.getDoubleBuffered() ||
capsRequested.isOnscreen() ||
- ( !pbufferAvailable && capsRequested.isPBuffer() ) )
+ ( fboAvailable != capsRequested.isFBO() ) ||
+ ( pbufferAvailable != capsRequested.isPBuffer() ) )
{
// fix caps ..
GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN
caps2.setOnscreen(false);
- if(caps2.isPBuffer() && !pbufferAvailable) {
- caps2.setPBuffer(false);
- }
+ caps2.setFBO( fboAvailable );
+ caps2.setPBuffer( pbufferAvailable );
return caps2;
}
return capsRequested;
@@ -136,25 +165,28 @@ public class GLGraphicsConfigurationUtil {
public static GLCapabilitiesImmutable fixGLPBufferGLCapabilities(GLCapabilitiesImmutable capsRequested)
{
- if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || !capsRequested.isPBuffer()) {
+ if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || !capsRequested.isPBuffer() || capsRequested.isFBO() ) {
// fix caps ..
GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN - we don't need to be single buffered ..
caps2.setOnscreen(false);
caps2.setPBuffer(true);
+ caps2.setFBO(false);
return caps2;
}
return capsRequested;
}
+ /** Fix opaque setting while preserve alpha bits */
public static GLCapabilitiesImmutable fixOpaqueGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean isOpaque)
{
GLCapabilities caps2 = null;
if( capsRequested.isBackgroundOpaque() != isOpaque) {
- // fix caps ..
+ final int alphaBits = capsRequested.getAlphaBits();
caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setBackgroundOpaque(isOpaque);
+ caps2.setAlphaBits(alphaBits);
return caps2;
}
return capsRequested;
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index a8277fd71..32f4cb696 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
@@ -42,10 +42,14 @@ package jogamp.opengl;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLPbuffer;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
/** Platform-independent class exposing pbuffer functionality to
applications. This class is not exposed in the public API as it
would probably add no value; however it implements the GLDrawable
@@ -54,9 +58,8 @@ import javax.media.opengl.GLPbuffer;
public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
private int floatMode;
- public GLPbufferImpl(GLDrawableImpl pbufferDrawable,
- GLContext sharedContext) {
- super(pbufferDrawable, null); // drawable := pbufferDrawable
+ public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext, boolean ownDevice) {
+ super(pbufferDrawable, null, ownDevice); // drawable := pbufferDrawable
GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)
drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities();
@@ -102,7 +105,7 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
//
// GLDrawable delegation
//
-
+
@Override
public final void setRealized(boolean realized) {
}
@@ -110,10 +113,19 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
//
// GLAutoDrawable completion
//
+ private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
+
+ @Override
+ protected final RecursiveLock getLock() { return lock; }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return null;
+ }
@Override
public void destroy() {
- defaultDestroyOp();
+ defaultDestroy();
}
@Override
@@ -122,12 +134,23 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
}
@Override
- public void display() {
- if( null != drawable && drawable.isRealized() && null != context ) {
- helper.invokeGL(drawable, context, defaultDisplayAction, initAction);
+ public final void display() {
+ final RecursiveLock _lock = lock;
+ _lock.lock(); // sync: context/drawable could been recreated/destroyed while animating
+ try {
+ if( null != context ) {
+ helper.invokeGL(drawable, context, defaultDisplayAction, initAction);
+ }
+ } finally {
+ _lock.unlock();
}
}
+ @Override
+ public final void swapBuffers() throws GLException {
+ defaultSwapBuffers();
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index 65a4c3ece..c5d0df645 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -110,14 +110,8 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected void makeCurrentImpl() throws GLException {
- if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) {
- throw new GLException("drawable not properly initialized, NO DISPLAY: "+drawable);
- }
if (EGL.eglGetCurrentContext() != contextHandle) {
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- drawable.getHandle(),
- drawableRead.getHandle(),
- contextHandle)) {
+ if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
throw new GLException("Error making context 0x" +
Long.toHexString(contextHandle) + " current: error code 0x" + Integer.toHexString(EGL.eglGetError()));
}
@@ -126,10 +120,7 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected void releaseImpl() throws GLException {
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- EGL.EGL_NO_SURFACE,
- EGL.EGL_NO_SURFACE,
- EGL.EGL_NO_CONTEXT)) {
+ if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT)) {
throw new GLException("Error freeing OpenGL context 0x" +
Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(EGL.eglGetError()));
}
@@ -137,7 +128,7 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected void destroyImpl() throws GLException {
- if (!EGL.eglDestroyContext(((EGLDrawable)drawable).getDisplay(), contextHandle)) {
+ if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle)) {
final int eglError = EGL.eglGetError();
if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */
throw new GLException("Error destroying OpenGL context 0x" +
@@ -158,16 +149,16 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected boolean createImpl(GLContextImpl shareWith) throws GLException {
- long eglDisplay = ((EGLDrawable)drawable).getDisplay();
- EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration();
- GLProfile glProfile = drawable.getGLProfile();
- long eglConfig = config.getNativeConfig();
+ final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
+ final long eglDisplay = config.getScreen().getDevice().getHandle();
+ final GLProfile glProfile = drawable.getGLProfile();
+ final long eglConfig = config.getNativeConfig();
long shareWithHandle = EGL.EGL_NO_CONTEXT;
- if (eglDisplay == 0) {
+ if ( 0 == eglDisplay ) {
throw new GLException("Error: attempted to create an OpenGL context without a display connection");
}
- if (eglConfig == 0) {
+ if ( 0 == eglConfig ) {
throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration");
}
@@ -217,10 +208,7 @@ public abstract class EGLContext extends GLContextImpl {
",\n\t"+this+
",\n\tsharing with 0x" + Long.toHexString(shareWithHandle));
}
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- drawable.getHandle(),
- drawableRead.getHandle(),
- contextHandle)) {
+ if (!EGL.eglMakeCurrent(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
throw new GLException("Error making context 0x" +
Long.toHexString(contextHandle) + " current: error code " + EGL.eglGetError());
}
@@ -269,8 +257,7 @@ public abstract class EGLContext extends GLContextImpl {
eglQueryStringInitialized = true;
}
if (eglQueryStringAvailable) {
- final String ret = EGL.eglQueryString(((EGLDrawable)drawable).getDisplay(),
- EGL.EGL_EXTENSIONS);
+ final String ret = EGL.eglQueryString(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_EXTENSIONS);
if (DEBUG) {
System.err.println("EGL extensions: " + ret);
}
@@ -291,7 +278,7 @@ public abstract class EGLContext extends GLContextImpl {
}
return false;
}
- return EGL.eglSwapInterval(((EGLDrawable)drawable).getDisplay(), interval);
+ return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval);
}
@Override
@@ -300,6 +287,45 @@ public abstract class EGLContext extends GLContextImpl {
@Override
public abstract void releasePbufferFromTexture();
+ //
+ // Accessible ..
+ //
+
+ /**
+ * If context is an ES profile, map it to the given device
+ * via {@link GLContext#mapAvailableGLVersion(AbstractGraphicsDevice, int, int, int, int, int)}.
+ * <p>
+ * We intentionally override a non native EGL device ES profile mapping,
+ * i.e. this will override/modify an already 'set' X11/WGL/.. mapping.
+ * </p>
+ *
+ * @param device
+ */
+ protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) {
+ mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions);
+ }
+
+ protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) {
+ int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES );
+ mapCurrentAvailableGLVersionImpl(device, major, 0, ctp);
+ }
+ private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) {
+ if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) {
+ // ES1 or ES2
+ final int reqMajor = major;
+ final int reqProfile = GLContext.CTX_PROFILE_ES;
+ GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
+ major, minor, ctp);
+ }
+ }
+
+ protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ return GLContext.getAvailableGLVersionsSet(device);
+ }
+ protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ GLContext.setAvailableGLVersionsSet(device);
+ }
+
protected static String toHexString(int hex) {
return GLContext.toHexString(hex);
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
index e09400c09..432010f49 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
@@ -30,12 +30,15 @@ package jogamp.opengl.egl;
import java.nio.IntBuffer;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.opengl.GLException;
import jogamp.opengl.Debug;
import com.jogamp.common.util.LongIntHashMap;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
/**
* This implementation provides recursive calls to
@@ -67,23 +70,6 @@ public class EGLDisplayUtil {
return eglDisplay;
}
- public static long eglGetDisplay(NativeSurface surface, boolean allowFallBackToDefault) {
- final long nDisplay;
- if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) {
- nDisplay = surface.getSurfaceHandle(); // don't even ask ..
- } else {
- nDisplay = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY
- }
- long eglDisplay = EGLDisplayUtil.eglGetDisplay(nDisplay);
- if (eglDisplay == EGL.EGL_NO_DISPLAY && nDisplay != EGL.EGL_DEFAULT_DISPLAY && allowFallBackToDefault) {
- if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglGetDisplay(): Fall back to EGL_DEFAULT_DISPLAY");
- }
- eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- }
- return eglDisplay;
- }
-
public static synchronized boolean eglInitialize(long eglDisplay, int[] major, int major_offset, int[] minor, int minor_offset) {
final boolean res;
final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init
@@ -99,7 +85,19 @@ public class EGLDisplayUtil {
return res;
}
+ /**
+ *
+ * @param eglDisplay
+ * @param major
+ * @param minor
+ * @return true if the eglDisplay is valid and it's reference counter becomes one and {@link EGL#eglTerminate(long)} was successful, otherwise false
+ *
+ * @see EGL#eglInitialize(long, int[], int, int[], int)}
+ */
public static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) {
+ if( EGL.EGL_NO_DISPLAY == eglDisplay) {
+ return false;
+ }
final boolean res;
final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init
if(1==refCnt) { // only initialize once
@@ -114,7 +112,14 @@ public class EGLDisplayUtil {
return res;
}
+ /**
+ * @param eglDisplay the EGL display handle
+ * @return true if the eglDisplay is valid and it's reference counter becomes zero and {@link EGL#eglTerminate(long)} was successful, otherwise false
+ */
public static synchronized boolean eglTerminate(long eglDisplay) {
+ if( EGL.EGL_NO_DISPLAY == eglDisplay) {
+ return false;
+ }
final boolean res;
final int refCnt = eglDisplayCounter.get(eglDisplay) - 1; // 1 - 1 = 0 -> final terminate
if(0==refCnt) { // no terminate if still in use or already terminated
@@ -130,4 +135,65 @@ public class EGLDisplayUtil {
}
return res;
}
+
+ public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() {
+ public long eglGetAndInitDisplay(long nativeDisplayID) {
+ long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID);
+ if (eglDisplay == EGL.EGL_NO_DISPLAY) {
+ throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ }
+ if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
+ throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ }
+ return eglDisplay;
+ }
+ public void eglTerminate(long eglDisplayHandle) {
+ EGLDisplayUtil.eglTerminate(eglDisplayHandle);
+ }
+ };
+
+ /**
+ * @param nativeDisplayID
+ * @param connection
+ * @param unitID
+ * @return an initialized EGLGraphicsDevice
+ * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails
+ * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLDisplayLifecycleCallback)
+ */
+ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) {
+ final EGLGraphicsDevice eglDisplay = new EGLGraphicsDevice(nativeDisplayID, 0, connection, unitID, eglLifecycleCallback);
+ eglDisplay.open();
+ return eglDisplay;
+ }
+
+ /**
+ * @param surface
+ * @param allowFallBackToDefault
+ * @return an initialized EGLGraphicsDevice
+ * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails
+ */
+ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(NativeSurface surface, boolean allowFallBackToDefault) {
+ long nativeDisplayID;
+ if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) {
+ nativeDisplayID = surface.getSurfaceHandle(); // don't even ask ..
+ } else {
+ nativeDisplayID = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY
+ }
+ long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID);
+ if (eglDisplay == EGL.EGL_NO_DISPLAY && nativeDisplayID != EGL.EGL_DEFAULT_DISPLAY && allowFallBackToDefault) {
+ if(DEBUG) {
+ System.err.println("EGLDisplayUtil.eglGetDisplay(): Fall back to EGL_DEFAULT_DISPLAY");
+ }
+ nativeDisplayID = EGL.EGL_DEFAULT_DISPLAY;
+ eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID);
+ }
+ if (eglDisplay == EGL.EGL_NO_DISPLAY) {
+ throw new GLException("Failed to created EGL display: "+surface+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ }
+ if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
+ throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ }
+ final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice();
+ return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback);
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
index 491f22119..383b61f88 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
@@ -36,82 +36,65 @@
package jogamp.opengl.egl;
-import jogamp.opengl.GLDynamicLookupHelper;
-import jogamp.opengl.GLDrawableImpl;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.VisualIDHolder.VIDType;
-import javax.media.opengl.*;
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.GLDynamicLookupHelper;
-import com.jogamp.nativewindow.egl.*;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
public abstract class EGLDrawable extends GLDrawableImpl {
- protected boolean ownEGLDisplay = false; // for destruction
- protected boolean ownEGLSurface = false; // for destruction
- private EGLGraphicsConfiguration eglConfig;
- protected long eglDisplay;
- protected long eglSurface;
+ private boolean ownEGLSurface = false; // for destruction
- protected EGLDrawable(EGLDrawableFactory factory,
- NativeSurface component) throws GLException {
+ protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException {
super(factory, component, false);
- eglSurface=EGL.EGL_NO_SURFACE;
- eglDisplay=0;
- }
-
- public long getDisplay() {
- return eglDisplay;
- }
-
- @Override
- public long getHandle() {
- return eglSurface;
- }
-
- public EGLGraphicsConfiguration getGraphicsConfiguration() {
- return eglConfig;
- }
-
- @Override
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
- return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities();
}
@Override
public abstract GLContext createContext(GLContext shareWith);
- protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle);
-
- private void recreateSurface() {
- // create a new EGLSurface ..
- if(EGL.EGL_NO_SURFACE!=eglSurface) {
- EGL.eglDestroySurface(eglDisplay, eglSurface);
- }
+ protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle);
+ private final void recreateSurface() {
+ final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice();
if(DEBUG) {
- System.err.println(getThreadName() + ": createSurface using eglDisplay "+toHexString(eglDisplay)+", "+eglConfig);
+ System.err.println(getThreadName() + ": createSurface using "+eglConfig);
+ }
+ if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) {
+ EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle());
}
-
- eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), surface.getSurfaceHandle());
- int eglError0 = EGL.EGL_SUCCESS;
+
+ final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook();
+ final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface();
+ long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle());
+
+ int eglError0;
if (EGL.EGL_NO_SURFACE == eglSurface) {
eglError0 = EGL.eglGetError();
if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) {
// Try window handle if available and differs (Windows HDC / HWND).
// ANGLE impl. required HWND on Windows.
- if(surface instanceof NativeWindow) {
- final NativeWindow nw = (NativeWindow) surface;
+ if(upstreamSurface instanceof NativeWindow) {
+ final NativeWindow nw = (NativeWindow) upstreamSurface;
if(nw.getWindowHandle() != nw.getSurfaceHandle()) {
if(DEBUG) {
System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle");
}
- eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), nw.getWindowHandle());
+ eglSurface = createSurface(eglConfig, nw.getWindowHandle());
if (EGL.EGL_NO_SURFACE == eglSurface) {
eglError0 = EGL.eglGetError();
}
}
}
}
+ } else {
+ eglError0 = EGL.EGL_SUCCESS;
}
if (EGL.EGL_NO_SURFACE == eglSurface) {
throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0));
@@ -120,6 +103,8 @@ public abstract class EGLDrawable extends GLDrawableImpl {
if(DEBUG) {
System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface));
}
+
+ ((MutableSurface)surface).setSurfaceHandle(eglSurface);
}
@Override
@@ -130,131 +115,72 @@ public abstract class EGLDrawable extends GLDrawableImpl {
}
@Override
- protected void setRealizedImpl() {
+ protected final void setRealizedImpl() {
+ final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice();
if (realized) {
- AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration();
- AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
- if(aDevice instanceof EGLGraphicsDevice) {
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START");
- }
- // just fetch the data .. trust but verify ..
- eglDisplay = aDevice.getHandle();
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Invalid EGL display in EGLGraphicsDevice from "+aDevice);
+ final long eglDisplayHandle = eglDevice.getHandle();
+ if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) {
+ throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice);
+ }
+ int[] tmp = new int[1];
+ boolean eglSurfaceValid = 0 != surface.getSurfaceHandle();
+ if(eglSurfaceValid) {
+ eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0);
+ if(!eglSurfaceValid) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface);
+ }
}
- if(aConfig instanceof EGLGraphicsConfiguration) {
- eglConfig = (EGLGraphicsConfiguration) aConfig; // done ..
- if (null == eglConfig) {
- throw new GLException("Null EGLGraphicsConfiguration from "+aConfig);
- }
-
- int[] tmp = new int[1];
- if ( 0 != surface.getSurfaceHandle() &&
- EGL.eglQuerySurface(eglDisplay, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) {
- // surface holds static EGLSurface
- eglSurface = surface.getSurfaceHandle();
- if(DEBUG) {
- System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface));
- }
- } else {
- // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface();
- ownEGLSurface=true;
- }
- } else {
- throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig);
+ }
+ if(eglSurfaceValid) {
+ // surface holds valid EGLSurface
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl re-using component's EGLSurface: handle "+toHexString(surface.getSurfaceHandle()));
}
+ ownEGLSurface=false;
} else {
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START");
+ // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface();
+ // However .. let's validate the surface object first
+ if( ! (surface instanceof ProxySurface) ) {
+ throw new InternalError("surface not ProxySurface: "+surface.getClass().getName()+", "+surface);
}
- // create a new EGL config ..
- ownEGLDisplay=true;
- // EGLSurface is ours ..
- ownEGLSurface=true;
-
- eglDisplay = EGLDisplayUtil.eglGetDisplay(surface, true);
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Failed to created EGL display: "+surface+", "+aDevice+", error "+toHexString(EGL.eglGetError()));
+ final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook();
+ if( null == upstreamHook ) {
+ throw new InternalError("null upstreamHook of: "+surface);
}
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed"+", error "+Integer.toHexString(EGL.eglGetError()));
+ if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) {
+ throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook);
}
- EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
- AbstractGraphicsScreen s = new DefaultGraphicsScreen(e, aConfig.getScreen().getIndex());
- final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
- if(aConfig instanceof EGLGraphicsConfiguration) {
- final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
- if(0 == capsChosen.getEGLConfig()) {
- // 'refresh' the native EGLConfig handle
- capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDisplay, capsChosen.getEGLConfigID()));
- if(0 == capsChosen.getEGLConfig()) {
- throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig);
- }
- }
- eglConfig = new EGLGraphicsConfiguration(s, capsChosen, capsRequested, null);
- if(DEBUG) {
- System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig);
- }
- } else {
- eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsRequested, capsRequested, null, s, aConfig.getVisualID(VIDType.NATIVE), false);
-
- if (null == eglConfig) {
- throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s);
- } else if(DEBUG) {
- System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig);
- }
+ if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) {
+ throw new InternalError("null upstream surface");
+ }
+ ownEGLSurface=true;
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface");
}
- // subsequent updateHandle() will issue recreateSurface();
- }
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface);
}
- } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) {
+ } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) {
if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", eglDisplay: "+toHexString(eglDisplay)+", eglSurface: "+toHexString(eglSurface));
+ System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle()));
}
// Destroy the window surface
- if (!EGL.eglDestroySurface(eglDisplay, eglSurface)) {
+ if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) {
throw new GLException("Error destroying window surface (eglDestroySurface)");
}
- eglSurface = EGL.EGL_NO_SURFACE;
- if (ownEGLDisplay && EGL.EGL_NO_DISPLAY!=eglDisplay) {
- EGLDisplayUtil.eglTerminate(eglDisplay);
- }
- eglDisplay=EGL.EGL_NO_DISPLAY;
- eglConfig=null;
+ ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE);
}
}
@Override
protected final void swapBuffersImpl() {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
// single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
- if(!EGL.eglSwapBuffers(eglDisplay, eglSurface)) {
+ if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) {
throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this);
}
}
- /**
- * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable.
- * Leave it here for later impl. of an EGLExternalDrawable.
- public int getWidth() {
- int[] tmp = new int[1];
- if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) {
- throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError()));
- }
- return tmp[0];
- }
-
- public int getHeight() {
- int[] tmp = new int[1];
- if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) {
- throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError()));
- }
- return tmp[0];
- } */
-
@Override
public GLDynamicLookupHelper getGLDynamicLookupHelper() {
if (getGLProfile().usesNativeGLES2()) {
@@ -271,8 +197,8 @@ public abstract class EGLDrawable extends GLDrawableImpl {
return getClass().getName()+"[realized "+isRealized()+
",\n\tfactory "+getFactory()+
",\n\tsurface "+getNativeSurface()+
- ",\n\teglSurface "+toHexString(eglSurface)+
- ",\n\teglConfig "+eglConfig+
+ ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+
+ ",\n\teglConfig "+surface.getGraphicsConfiguration()+
",\n\trequested "+getRequestedGLCapabilities()+
",\n\tchosen "+getChosenGLCapabilities()+"]";
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index e4f6f0ef8..c848e3e5c 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -46,21 +46,29 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.nativewindow.VisualIDHolder;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLProfile.ShutdownType;
+import jogamp.opengl.Debug;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.os.Platform;
@@ -69,6 +77,9 @@ import com.jogamp.nativewindow.WrappedSurface;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
public class EGLDrawableFactory extends GLDrawableFactoryImpl {
+ /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true);
+ /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true);
+
private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null;
private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null;
private static boolean isANGLE = false;
@@ -184,10 +195,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if(DEBUG) {
System.err.println("EGLDrawableFactory.destroy("+shutdownType+"): "+sr.device.toString());
}
- final long eglDisplay = sr.device.getHandle();
- if(EGL.EGL_NO_DISPLAY != eglDisplay) {
- EGLDisplayUtil.eglTerminate(eglDisplay);
- }
+ sr.device.close();
}
sharedMap.clear();
sharedMap = null;
@@ -234,7 +242,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
// final EGLContext getContextES1() { return contextES1; }
// final EGLContext getContextES2() { return contextES2; }
final boolean wasES1ContextAvailable() { return wasES1ContextCreated; }
- final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }
+ final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }
}
@Override
@@ -248,66 +256,144 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper;
}
- /**
- private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) {
- boolean madeCurrent = false;
- final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile));
- caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
- caps.setDoubleBuffered(false);
- caps.setOnscreen(false);
- caps.setPBuffer(true);
- final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );
- if(null!=drawable) {
+ private boolean isEGLContextAvailable(AbstractGraphicsDevice adevice, EGLGraphicsDevice sharedEGLDevice, String profileString) {
+ if( !GLProfile.isAvailable(adevice, profileString) ) {
+ return false;
+ }
+ final GLProfile glp = GLProfile.get(adevice, profileString) ;
+ final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory();
+ EGLGraphicsDevice eglDevice = null;
+ NativeSurface surface = null;
+ ProxySurface upstreamSurface = null; // X11, GLX, ..
+ boolean success = false;
+ boolean deviceFromUpstreamSurface = false;
+ try {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
+ if(adevice instanceof EGLGraphicsDevice || null == desktopFactory || !QUERY_EGL_ES_NATIVE_TK) {
+ eglDevice = sharedEGLDevice; // reuse
+ surface = createDummySurfaceImpl(eglDevice, false, caps, null, 64, 64); // egl pbuffer offscreen
+ upstreamSurface = (ProxySurface)surface;
+ upstreamSurface.createNotify();
+ deviceFromUpstreamSurface = false;
+ } else {
+ surface = desktopFactory.createDummySurface(adevice, caps, null, 64, 64); // X11, WGL, .. dummy window
+ upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ;
+ if(null != upstreamSurface) {
+ upstreamSurface.createNotify();
+ }
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true);
+ deviceFromUpstreamSurface = true;
+ }
+
+ final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface );
+ drawable.setRealized(true);
final EGLContext context = (EGLContext) drawable.createContext(null);
if (null != context) {
- context.setSynchronized(true);
try {
context.makeCurrent(); // could cause exception
- madeCurrent = context.isCurrent();
+ success = context.isCurrent();
+ if(success) {
+ final String glVersion = context.getGL().glGetString(GL.GL_VERSION);
+ if(null == glVersion) {
+ // Oops .. something is wrong
+ if(DEBUG) {
+ System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!");
+ }
+ success = false;
+ }
+ }
+ if(success) {
+ context.mapCurrentAvailableGLVersion(eglDevice);
+ if(eglDevice != adevice) {
+ context.mapCurrentAvailableGLVersion(adevice);
+ }
+ }
} catch (GLException gle) {
if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed");
+ System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed");
gle.printStackTrace();
}
} finally {
context.destroy();
}
}
- drawable.destroy();
+ drawable.setRealized(false);
+ } catch (Throwable t) {
+ if(DEBUG) {
+ System.err.println("Catched Exception:");
+ t.printStackTrace();
+ }
+ success = false;
+ } finally {
+ if(eglDevice == sharedEGLDevice) {
+ if(null != upstreamSurface) {
+ upstreamSurface.destroyNotify();
+ }
+ } else if( deviceFromUpstreamSurface ) {
+ if(null != eglDevice) {
+ eglDevice.close();
+ }
+ if(null != upstreamSurface) {
+ upstreamSurface.destroyNotify();
+ }
+ } else {
+ if(null != upstreamSurface) {
+ upstreamSurface.destroyNotify();
+ }
+ if(null != eglDevice) {
+ eglDevice.close();
+ }
+ }
}
- return madeCurrent;
- } */
+ return success;
+ }
/* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) {
if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) {
return null;
}
- String connection = adevice.getConnection();
+ final String connection = adevice.getConnection();
SharedResource sr;
synchronized(sharedMap) {
sr = sharedMap.get(connection);
}
if(null==sr) {
- long eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError()));
- } else if(DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: eglDisplay(EGL_DEFAULT_DISPLAY): 0x"+Long.toHexString(eglDisplay));
+ final boolean madeCurrentES1;
+ final boolean madeCurrentES2;
+ final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+
+ if(QUERY_EGL_ES) {
+ madeCurrentES1 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES1);
+ madeCurrentES2 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES2);
+ } else {
+ madeCurrentES1 = true;
+ madeCurrentES2 = true;
+ EGLContext.mapStaticGLESVersion(sharedDevice, 1);
+ if(sharedDevice != adevice) {
+ EGLContext.mapStaticGLESVersion(adevice, 1);
+ }
+ EGLContext.mapStaticGLESVersion(sharedDevice, 2);
+ if(sharedDevice != adevice) {
+ EGLContext.mapStaticGLESVersion(adevice, 2);
+ }
}
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+
+ if( !EGLContext.getAvailableGLVersionsSet(adevice) ) {
+ // Even though we override the non EGL native mapping intentionally,
+ // avoid exception due to double 'set' - carefull exception of the rule.
+ EGLContext.setAvailableGLVersionsSet(adevice);
}
- final EGLGraphicsDevice sharedDevice = new EGLGraphicsDevice(eglDisplay, connection, adevice.getUnitID());
- // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1);
- // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2);
- final boolean madeCurrentES1 = true; // FIXME
- final boolean madeCurrentES2 = true; // FIXME
sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2);
+
synchronized(sharedMap) {
sharedMap.put(connection, sr);
+ if(adevice != sharedDevice) {
+ sharedMap.put(sharedDevice.getConnection(), sr);
+ }
}
if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: device: " + sharedDevice);
+ System.err.println("EGLDrawableFactory.createShared: devices: queried " + QUERY_EGL_ES + "[nativeTK "+QUERY_EGL_ES_NATIVE_TK+"], " + adevice + ", " + sharedDevice);
System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1);
System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2);
}
@@ -378,8 +464,51 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- return new EGLOnscreenDrawable(this, target);
+ return new EGLOnscreenDrawable(this, getEGLSurface(target));
+ }
+
+ protected static NativeSurface getEGLSurface(NativeSurface surface) {
+ AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration();
+ AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
+ if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) {
+ // already in native EGL format
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": getEGLSurface - already in EGL format - use as-is: "+aConfig);
+ }
+ return surface;
+ }
+ // create EGL instance out of platform native types
+ final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true);
+ final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
+ final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
+ final EGLGraphicsConfiguration eglConfig;
+ if( aConfig instanceof EGLGraphicsConfiguration ) {
+ // Config is already in EGL type - reuse ..
+ final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
+ if( 0 == capsChosen.getEGLConfig() ) {
+ // 'refresh' the native EGLConfig handle
+ capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID()));
+ if( 0 == capsChosen.getEGLConfig() ) {
+ throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig);
+ }
+ }
+ eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null);
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": getEGLSurface - Reusing chosenCaps: "+eglConfig);
+ }
+ } else {
+ eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
+ capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false);
+
+ if (null == eglConfig) {
+ throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen);
+ } else if(DEBUG) {
+ System.err.println(getThreadName() + ": getEGLSurface - Chosen eglConfig: "+eglConfig);
+ }
+ }
+ return new WrappedSurface(eglConfig, EGL.EGL_NO_SURFACE, surface.getWidth(), surface.getHeight(), new EGLUpstreamSurfaceHook(surface));
}
+ static String getThreadName() { return Thread.currentThread().getName(); }
@Override
protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
@@ -401,20 +530,115 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser));
- ns.surfaceSizeChanged(width, height);
- return ns;
+ protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+ final EGLGraphicsDevice device;
+ if(createNewDevice) {
+ final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq;
+ device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID());
+ } else {
+ device = (EGLGraphicsDevice) deviceReq;
+ }
+ final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
+ return new WrappedSurface(config, 0, width, height, lifecycleHook);
+ }
+
+ @Override
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq));
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook);
+ }
+ private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) {
+ if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
+ if(0 == eglDevice.getHandle()) {
+ eglDevice.open();
+ s.setImplBitfield(ProxySurface.OWN_DEVICE);
+ }
+ createPBufferSurfaceImpl(s, false);
+ if(DEBUG) {
+ System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+ }
+ }
+ }
+ @Override
+ public final void destroy(ProxySurface s) {
+ if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) {
+ final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) s.getGraphicsConfiguration();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice();
+ EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(EGL.EGL_NO_SURFACE);
+ if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) {
+ eglDevice.close();
+ }
+ if(DEBUG) {
+ System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+ }
+ }
+ }
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return s.initialWidth;
+ }
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return s.initialHeight;
+ }
+ @Override
+ public String toString() {
+ return "EGLSurfaceLifecycleHook[]";
+ }
+
+ };
+
+ /**
+ * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface.
+ * It will also hold the resulting pbuffer surface handle.
+ * @param useTexture
+ * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle
+ */
+ protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) {
+ final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) ms.getGraphicsConfiguration();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final int texFormat;
+
+ if(useTexture) {
+ texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ;
+ } else {
+ texFormat = EGL.EGL_NO_TEXTURE;
+ }
+
+ if (DEBUG) {
+ System.out.println("Pbuffer config: " + config);
+ }
+
+ final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat);
+ final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0);
+ if (EGL.EGL_NO_SURFACE==surf) {
+ throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+ms.getWidth()+"x"+ms.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ } else if(DEBUG) {
+ System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf));
+ }
+ ms.setSurfaceHandle(surf);
+ return ms;
}
@Override
- protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- EGLGraphicsDevice device = (EGLGraphicsDevice) adevice;
- DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
- WrappedSurface ns = new WrappedSurface(cfg, windowHandle);
- return ns;
+ protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq;
+ final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID());
+ final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
+ final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
+ return new WrappedSurface(cfg, windowHandle, 0, 0, upstream);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
index 56e7a4d22..716a6e6f1 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
@@ -42,6 +42,7 @@ import java.util.List;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
@@ -96,9 +97,10 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
}
void updateGraphicsConfiguration() {
+ CapabilitiesImmutable capsChosen = getChosenCapabilities();
EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(
- getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen());
+ GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), capsChosen).chooseGraphicsConfiguration(
+ capsChosen, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED);
if(null!=newConfig) {
// FIXME: setScreen( ... );
setChosenCapabilities(newConfig.getChosenCapabilities());
@@ -151,7 +153,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config,
boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) {
List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
if( EGLConfig2Capabilities(bucket, glp, display, config, winattrmask, forceTransparentFlag) ) {
return (EGLGLCapabilities) bucket.get(0);
} else if ( relaxed && EGLConfig2Capabilities(bucket, glp, display, config, GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag) ) {
@@ -209,24 +211,6 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
return false;
}
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) {
- caps.setRedBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) {
- caps.setGreenBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) {
- caps.setBlueBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) {
- caps.setAlphaBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) {
- caps.setStencilBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) {
- caps.setDepthBits(val.get(0));
- }
if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SAMPLES, val)) {
caps.setSampleBuffers(val.get(0)>0?true:false);
caps.setNumSamples(val.get(0));
@@ -262,6 +246,25 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
caps.setTransparentAlphaValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0));
} */
}
+ // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) {
+ caps.setRedBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) {
+ caps.setGreenBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) {
+ caps.setBlueBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) {
+ caps.setAlphaBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) {
+ caps.setStencilBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) {
+ caps.setDepthBits(val.get(0));
+ }
return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, caps, drawableTypeBits );
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
index 5ab2632c6..0b21d2054 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
@@ -38,7 +38,6 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
-import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.VisualIDHolder.VIDType;
@@ -47,6 +46,7 @@ import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLDrawableFactory;
@@ -81,27 +81,27 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
// become the pre-selector for X11/.. to match the native visual id w/ EGL, if native ES is selected
final String nwType = NativeWindowFactory.getNativeWindowType(false);
if(NativeWindowFactory.TYPE_X11 == nwType) {
- nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, eglFactory);
+ nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
} /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) {
nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, eglFactory);
} else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
} */
// become the selector for KD/EGL ..
- kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, eglFactory);
+ kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
}
static void unregisterFactory() {
final String nwType = NativeWindowFactory.getNativeWindowType(false);
if(NativeWindowFactory.TYPE_X11 == nwType) {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, nativeGraphicsConfigurationFactory);
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, nativeGraphicsConfigurationFactory);
} /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) {
GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, nativeGraphicsConfigurationFactory);
} else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
} */
nativeGraphicsConfigurationFactory = null;
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, kdeglGraphicsConfigurationFactory);
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, kdeglGraphicsConfigurationFactory);
kdeglGraphicsConfigurationFactory = null;
}
@@ -110,7 +110,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl (
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (absScreen == null) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects");
}
@@ -140,7 +140,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen,
(GLCapabilitiesImmutable) capsRequested,
(GLCapabilitiesChooser) chooser,
- absScreen, VisualIDHolder.VID_UNDEFINED, false);
+ absScreen, nativeVisualID, false);
} else {
// handle non native cases (X11, ..)
if(null == nativeGraphicsConfigurationFactory) {
@@ -154,7 +154,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen,
(GLCapabilitiesImmutable) capsRequested,
(GLCapabilitiesChooser) chooser,
- absScreen, VisualIDHolder.VID_UNDEFINED, false);
+ absScreen, nativeVisualID, false);
if(null == cfg || VisualIDHolder.VID_UNDEFINED == cfg.getVisualID(VIDType.NATIVE)) {
cfg = null;
if(DEBUG) {
@@ -167,7 +167,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(DEBUG) {
System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+nativeGraphicsConfigurationFactory.getClass().getSimpleName());
}
- cfg = nativeGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen);
+ cfg = nativeGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, nativeVisualID);
}
}
return cfg;
@@ -180,6 +180,9 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
}
EGLGraphicsDevice eglDevice = sharedResource.getDevice();
long eglDisplay = eglDevice.getHandle();
+ if(0 == eglDisplay) {
+ throw new GLException("null eglDisplay");
+ }
List<GLCapabilitiesImmutable> availableCaps = null;
IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
@@ -223,32 +226,24 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("Null AbstractGraphicsDevice");
}
- final long eglDisplay;
+ final EGLGraphicsDevice eglDevice;
final boolean ownEGLDisplay;
- if( !(absDevice instanceof EGLGraphicsDevice) ) {
- eglDisplay = EGLDisplayUtil.eglGetDisplay(absDevice.getHandle());
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Could not get EGL display from: "+absDevice);
- }
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed eglDisplay 0x"+Long.toHexString(eglDisplay)+", "+absDevice+", error 0x"+Integer.toHexString(EGL.eglGetError()));
- }
- ownEGLDisplay = true;
- } else {
- eglDisplay = absDevice.getHandle();
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Invalid EGL display: "+absDevice);
+ if( absDevice instanceof EGLGraphicsDevice ) {
+ eglDevice = (EGLGraphicsDevice) absDevice;
+ if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) {
+ throw new GLException("Invalid EGL display: "+eglDevice);
}
ownEGLDisplay = false;
+ } else {
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice.getHandle(), absDevice.getConnection(), absDevice.getUnitID());
+ ownEGLDisplay = true;
}
- EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(absDevice) );
-
- GLProfile glp = capsChosen.getGLProfile();
- GLCapabilities fixedCaps;
+ final GLProfile glp = capsChosen.getGLProfile();
+ final EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory();
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(absDevice, glp), factory.canCreateGLPbuffer(absDevice) );
- EGLGraphicsConfiguration res = eglChooseConfig(eglDisplay, capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag);
+ EGLGraphicsConfiguration res = eglChooseConfig(eglDevice.getHandle(), capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag);
if(null==res) {
if(DEBUG) {
System.err.println("eglChooseConfig failed with given capabilities "+capsChosen);
@@ -257,52 +252,67 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
// Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..]
//
// rgb888 - d16, s4
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
+ fixedCaps.setSampleBuffers(true);
+ fixedCaps.setNumSamples(4);
fixedCaps.setRedBits(8);
fixedCaps.setGreenBits(8);
fixedCaps.setBlueBits(8);
fixedCaps.setDepthBits(16);
- fixedCaps.setSampleBuffers(true);
- fixedCaps.setNumSamples(4);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (1): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
//
// rgb565 - d16, s0
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
fixedCaps.setRedBits(5);
fixedCaps.setGreenBits(6);
fixedCaps.setBlueBits(5);
fixedCaps.setDepthBits(16);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (2): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
//
// rgb565 - d16, s4
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
+ fixedCaps.setSampleBuffers(true);
+ fixedCaps.setNumSamples(4);
fixedCaps.setRedBits(5);
fixedCaps.setGreenBits(6);
fixedCaps.setBlueBits(5);
fixedCaps.setDepthBits(16);
- fixedCaps.setSampleBuffers(true);
- fixedCaps.setNumSamples(4);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (3): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
throw new GLException("Graphics configuration failed [direct caps, eglGetConfig/chooser and fixed-caps(1-3)]");
}
if(ownEGLDisplay) {
- ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL
- EGLDisplayUtil.eglTerminate(eglDisplay);
+ ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL
+ eglDevice.close();
}
return res;
}
@@ -315,7 +325,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
final GLProfile glp = capsChosen.getGLProfile();
final boolean onscreen = capsChosen.isOnscreen();
final boolean usePBuffer = capsChosen.isPBuffer();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
List<GLCapabilitiesImmutable> availableCaps = null;
int recommendedIndex = -1;
long recommendedEGLConfig = -1;
@@ -328,8 +338,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) no configs");
}
if (DEBUG) {
- System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig maxConfigs: "+numConfigs.get(0));
- System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglDisplay "+toHexString(eglDisplay)+", "+capsChosen+", nativeVisualID "+toHexString(nativeVisualID));
+ System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig eglDisplay "+toHexString(eglDisplay)+", nativeVisualID "+toHexString(nativeVisualID)+", onscreen "+onscreen+", usePBuffer "+usePBuffer+", "+capsChosen+", numConfigs "+numConfigs.get(0));
}
final IntBuffer attrs = Buffers.newDirectIntBuffer(EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen));
@@ -368,7 +377,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: #2 Get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if (numConfigs.get(0) > 0) {
- availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
+ availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
}
}
@@ -376,6 +385,8 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(DEBUG) {
// FIXME: this happens on a ATI PC Emulation ..
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 Graphics configuration 1st choice and 2nd choice failed - no configs");
+ availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag);
+ printCaps("AllCaps", availableCaps, System.err);
}
return null;
}
@@ -434,27 +445,5 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
out.println(prefix+"["+i+"] "+caps.get(i));
}
}
-
- static EGLGraphicsConfiguration createOffscreenGraphicsConfiguration(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser) {
- if(capsChosen.isOnscreen()) {
- throw new GLException("Error: Onscreen set: "+capsChosen);
- }
-
- if(capsChosen.getDoubleBuffered()) {
- // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN
- GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable();
- caps2.setDoubleBuffered(false);
- capsChosen = caps2;
- }
-
- DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- EGLGraphicsConfiguration eglConfig = chooseGraphicsConfigurationStatic(capsChosen, capsReq, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
- if (null == eglConfig) {
- throw new GLException("Couldn't create EGLGraphicsConfiguration from "+screen);
- } else if(DEBUG) {
- System.err.println("Chosen eglConfig: "+eglConfig);
- }
- return eglConfig;
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
index 3768f1588..d54057775 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
@@ -54,8 +54,8 @@ public class EGLOnscreenDrawable extends EGLDrawable {
}
@Override
- protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) {
- return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null);
+ protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) {
+ return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
index b2217c095..4a36625bd 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
@@ -40,15 +40,11 @@
package jogamp.opengl.egl;
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
-import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
public class EGLPbufferDrawable extends EGLDrawable {
- private int texFormat;
protected static final boolean useTexture = false; // No yet ..
protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeSurface target) {
@@ -56,30 +52,12 @@ public class EGLPbufferDrawable extends EGLDrawable {
}
@Override
- protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) {
- final AbstractGraphicsConfiguration config = getNativeSurface().getGraphicsConfiguration();
- final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
-
- if(useTexture) {
- texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ;
- } else {
- texFormat = EGL.EGL_NO_TEXTURE;
- }
-
- if (DEBUG) {
- System.out.println("Pbuffer config: " + config);
- }
-
- NativeSurface nw = getNativeSurface();
- int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat);
- long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0);
- if (EGL.EGL_NO_SURFACE==surf) {
- throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+nw.getWidth()+"x"+nw.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError()));
- } else if(DEBUG) {
- System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf));
+ protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) {
+ final MutableSurface ms = (MutableSurface)getNativeSurface();
+ if(config != ms.getGraphicsConfiguration()) {
+ throw new InternalError("Not same: "+config.hashCode()+", "+ms.getGraphicsConfiguration()+": "+config+", "+ms.getGraphicsConfiguration());
}
- ((SurfaceChangeable)nw).setSurfaceHandle(surf);
- return surf;
+ return EGLDrawableFactory.createPBufferSurfaceImpl(ms, useTexture).getSurfaceHandle();
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
new file mode 100644
index 000000000..42c6e100e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
@@ -0,0 +1,56 @@
+package jogamp.opengl.egl;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLException;
+
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+
+public class EGLUpstreamSurfaceHook implements ProxySurface.UpstreamSurfaceHook {
+ private final NativeSurface upstreamSurface;
+
+ public EGLUpstreamSurfaceHook(NativeSurface upstream) {
+ upstreamSurface = upstream;
+ }
+
+ public final NativeSurface getUpstreamSurface() { return upstreamSurface; }
+
+ @Override
+ public final void create(ProxySurface surface) {
+ if(upstreamSurface instanceof ProxySurface) {
+ ((ProxySurface)upstreamSurface).createNotify();
+ if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) {
+ throw new GLException("Could not lock: "+upstreamSurface);
+ }
+ }
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
+ eglDevice.open();
+ }
+
+ @Override
+ public final void destroy(ProxySurface surface) {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
+ eglDevice.close();
+ if(upstreamSurface instanceof ProxySurface) {
+ upstreamSurface.unlockSurface();
+ ((ProxySurface)upstreamSurface).destroyNotify();
+ }
+ }
+
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return upstreamSurface.getWidth();
+ }
+
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return upstreamSurface.getHeight();
+ }
+
+ @Override
+ public String toString() {
+ final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": " + upstreamSurface ) : "nil";
+ return "EGLUpstreamSurfaceHook[upstream: "+us_s+"]";
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index aa66aa9d1..82525cfde 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -48,11 +48,13 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
+import javax.media.nativewindow.ProxySurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
@@ -63,6 +65,7 @@ import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
public abstract class MacOSXCGLContext extends GLContextImpl
{
@@ -252,9 +255,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
protected void makeCurrentImpl() throws GLException {
+ /** FIXME: won't work w/ special drawables (like FBO) - check for CGL mode regressions!
+ *
if (getOpenGLMode() != ((MacOSXCGLDrawable)drawable).getOpenGLMode()) {
setOpenGLMode(((MacOSXCGLDrawable)drawable).getOpenGLMode());
- }
+ } */
if (!impl.makeCurrent(contextHandle)) {
throw new GLException("Error making Context current: "+this);
}
@@ -338,8 +343,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals("GL_ARB_pbuffer") ||
- glExtensionName.equals("GL_ARB_pixel_format")) {
+ if (glExtensionName.equals(GLExtensions.ARB_pbuffer) ||
+ glExtensionName.equals(GLExtensions.ARB_pixel_format)) {
return true;
}
return super.isExtensionAvailable(glExtensionName);
@@ -426,10 +431,27 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public long create(long share, int ctp, int major, int minor) {
long ctx = 0;
- final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) MacOSXCGLContext.this.drawable;
- final NativeSurface surface = drawable.getNativeSurface();
+ final long nsViewHandle;
+ if(drawable instanceof MacOSXCGLDrawable) {
+ // we allow null here! (special pbuffer case)
+ nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle();
+ } else {
+ // we only allow a valid NSView here
+ final long aHandle = drawable.getHandle();
+ if( OSXUtil.isNSView(aHandle) ) {
+ nsViewHandle = aHandle;
+ } else {
+ throw new RuntimeException("Anonymous drawable instance's handle not of type NSView: "+drawable.getClass().getName()+", "+drawable);
+ }
+ }
+ final NativeSurface surface = drawable.getNativeSurface();
final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration();
final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
+
+ boolean allowIncompleteView = null != backingLayerHost;
+ if( !allowIncompleteView && surface instanceof ProxySurface ) {
+ allowIncompleteView = 0 != ( ProxySurface.INVISIBLE_WINDOW & ((ProxySurface)surface).getImplBitfield() ) ;
+ }
final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor);
if (pixelFormat == 0) {
@@ -443,13 +465,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl
screenVSyncTimeout = 1000000f / sRefreshRate;
if(DEBUG) {
System.err.println("NS create OSX>=lion "+isLionOrLater);
- System.err.println("NS create backendType: "+drawable.getOpenGLMode());
+ System.err.println("NS create allowIncompleteView: "+allowIncompleteView);
System.err.println("NS create backingLayerHost: "+backingLayerHost);
System.err.println("NS create share: "+share);
System.err.println("NS create chosenCaps: "+chosenCaps);
System.err.println("NS create pixelFormat: "+toHexString(pixelFormat));
System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle()));
- System.err.println("NS create drawable NSView-handle: "+toHexString(drawable.getNSViewHandle()));
+ System.err.println("NS create drawable NSView-handle: "+toHexString(nsViewHandle));
System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros");
// Thread.dumpStack();
}
@@ -457,7 +479,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
int[] viewNotReady = new int[1];
// Try to allocate a context with this
ctx = CGL.createContext(share,
- drawable.getNSViewHandle(), null!=backingLayerHost,
+ nsViewHandle, allowIncompleteView,
pixelFormat,
chosenCaps.isBackgroundOpaque(),
viewNotReady, 0);
@@ -473,10 +495,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
CGL.setContextOpacity(ctx, 0);
}
- if(DEBUG) {
- GLCapabilitiesImmutable caps0 = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(null, pixelFormat);
- System.err.println("NS create pixelformat2GLCaps: "+caps0);
- }
GLCapabilitiesImmutable fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat);
fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque());
config.setChosenCapabilities(fixedCaps);
@@ -502,10 +520,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl
texWidth = drawable.getWidth();
texHeight = drawable.getHeight();
}
- nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight);
if(0>=texWidth || 0>=texHeight || !drawable.isRealized()) {
throw new GLException("Drawable not realized yet or invalid texture size, texSize "+texWidth+"x"+texHeight+", "+drawable);
}
+ nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight);
if (DEBUG) {
System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", texSize "+texWidth+"x"+texHeight+", "+drawable);
}
@@ -528,11 +546,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl
System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer));
}
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
- if(null == ols) {
- throw new InternalError("XXX: "+ols);
+ if(null != ols && ols.isSurfaceLayerAttached()) {
+ // still having a valid OLS attached to surface (parent OLS could have been removed)
+ ols.detachSurfaceLayer();
}
- CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
- ols.detachSurfaceLayer(nsOpenGLLayer);
+ CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
CGL.deletePixelFormat(nsOpenGLLayerPFmt);
nsOpenGLLayerPFmt = 0;
nsOpenGLLayer = 0;
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
index 257635b8c..af767f0c3 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
@@ -105,7 +105,7 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
@Override
protected void setRealizedImpl() {
}
-
+
protected long getNSViewHandle() {
return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0;
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index 4e9d18fed..9689d9f64 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -50,8 +50,8 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
@@ -62,15 +62,19 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLProfile.ShutdownType;
+import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.nativewindow.WrappedSurface;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
+import com.jogamp.opengl.GLExtensions;
public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
private static DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper = null;
@@ -214,44 +218,39 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
- final GLCapabilities caps = new GLCapabilities(glp);
- caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
- caps.setDepthBits(5);
- caps.setDoubleBuffered(false);
- caps.setOnscreen(false);
- caps.setPBuffer(true);
- final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );
- if(null!=drawable) {
- drawable.setRealized(true);
- final GLContext context = drawable.createContext(null);
- if (null != context) {
- try {
- context.makeCurrent(); // could cause exception
- madeCurrent = context.isCurrent();
- if(madeCurrent) {
- GL gl = context.getGL();
- hasNPOTTextures = gl.isNPOTTextureAvailable();
- hasRECTTextures = gl.isExtensionAvailable("GL_EXT_texture_rectangle");
- hasAppleFloatPixels = gl.isExtensionAvailable("GL_APPLE_float_pixels");
- }
- } catch (GLException gle) {
- if (DEBUG) {
- System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:");
- gle.printStackTrace();
- }
- } finally {
- try {
- context.destroy();
- } catch (GLException gle) {
- if (DEBUG) {
- System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:");
- gle.printStackTrace();
- }
- }
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+ sharedDrawable.setRealized(true);
+
+ final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
+ if (null == sharedContext) {
+ throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
+ }
+
+ try {
+ sharedContext.makeCurrent(); // could cause exception
+ madeCurrent = sharedContext.isCurrent();
+ if(madeCurrent) {
+ GL gl = sharedContext.getGL();
+ hasNPOTTextures = gl.isNPOTTextureAvailable();
+ hasRECTTextures = gl.isExtensionAvailable(GLExtensions.EXT_texture_rectangle);
+ hasAppleFloatPixels = gl.isExtensionAvailable(GLExtensions.APPLE_float_pixels);
+ }
+ } catch (GLException gle) {
+ if (DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:");
+ gle.printStackTrace();
+ }
+ } finally {
+ try {
+ sharedContext.destroy();
+ } catch (GLException gle) {
+ if (DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:");
+ gle.printStackTrace();
}
}
- drawable.setRealized(false);
}
+ sharedDrawable.setRealized(false);
}
sr = new SharedResource(sharedDevice, madeCurrent, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels);
synchronized(sharedMap) {
@@ -332,18 +331,82 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX);
- WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true));
- ns.surfaceSizeChanged(width, height);
- return ns;
+ protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+ final MacOSXGraphicsDevice device;
+ if(createNewDevice) {
+ device = new MacOSXGraphicsDevice(deviceReq.getUnitID());
+ } else {
+ device = (MacOSXGraphicsDevice)deviceReq;
+ }
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
+ return new WrappedSurface(config, 0, width, height, lifecycleHook);
}
@Override
- protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true), windowHandle);
- return ns;
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook);
+ }
+ private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+ long nsWindow = 0;
+ @Override
+ public final void create(ProxySurface s) {
+ if(0 == nsWindow && 0 == s.getSurfaceHandle()) {
+ nsWindow = OSXUtil.CreateNSWindow(0, 0, s.getWidth(), s.getHeight());
+ if(0 == nsWindow) {
+ throw new GLException("Error NS window 0");
+ }
+ long nsView = OSXUtil.GetNSView(nsWindow);
+ if(0 == nsView) {
+ throw new GLException("Error NS view 0");
+ }
+ s.setSurfaceHandle(nsView);
+ s.setImplBitfield(ProxySurface.INVISIBLE_WINDOW);
+ if(DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+ }
+ }
+ }
+ @Override
+ public final void destroy(ProxySurface s) {
+ if(0 != nsWindow && 0 != s.getSurfaceHandle()) {
+ OSXUtil.DestroyNSWindow(nsWindow);
+ nsWindow = 0;
+ s.setSurfaceHandle(0);
+ if(DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.dummySurfaceLifecycleHook.destroy: "+s);
+ }
+ }
+ }
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return s.initialWidth;
+ }
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return s.initialHeight;
+ }
+
+ @Override
+ public String toString() {
+ return "MacOSXLSurfaceLifecycleHook[]";
+ }
+
+ };
+
+ @Override
+ protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final MacOSXGraphicsDevice device = new MacOSXGraphicsDevice(deviceReq.getUnitID());
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
+ final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true);
+ return new WrappedSurface(config, windowHandle, 0, 0, upstream);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
index 8393a688e..202644bb3 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
@@ -154,7 +154,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
case CGL.NSOpenGLPFASamples:
- ivalues[idx] = caps.getSampleBuffers() ? ivalues[idx] = caps.getNumSamples() : 0;
+ ivalues[idx] = caps.getNumSamples() ;
break;
default:
@@ -233,7 +233,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
return fmt.get(0);
}
- static GLCapabilitiesImmutable CGLPixelFormat2GLCapabilities(long pixelFormat) {
+ static GLCapabilitiesImmutable CGLPixelFormat2GLCapabilities(long pixelFormat) {
return PixelFormat2GLCapabilities(null, pixelFormat, false);
}
@@ -281,6 +281,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
glp = GLProfile.get(GLProfile.GL2);
}
GLCapabilities caps = new GLCapabilities(glp);
+ int alphaBits = 0;
for (int i = 0; i < len; i++) {
int attr = cglInternalAttributeToken[i+off];
switch (attr) {
@@ -317,7 +318,8 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
case CGL.NSOpenGLPFAAlphaSize:
- caps.setAlphaBits(ivalues[i]);
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
+ alphaBits = ivalues[i];
break;
case CGL.NSOpenGLPFADepthSize:
@@ -350,6 +352,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
}
}
+ caps.setAlphaBits(alphaBits);
return caps;
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
index 1a9070aef..f138e7557 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
@@ -50,14 +50,14 @@ import javax.media.opengl.GLCapabilitiesImmutable;
public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice.class, new MacOSXCGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice.class, GLCapabilitiesImmutable.class, new MacOSXCGLGraphicsConfigurationFactory());
}
private MacOSXCGLGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, absScreen, false);
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
index ad4c06af2..6be9e386d 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
@@ -114,8 +114,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext {
// set a fake marker stating a valid drawable
currentDrawable = 1;
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(currentDrawable);
+ WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, null);
return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle);
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
index 242cea068..8f2f386af 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
@@ -42,7 +42,7 @@ package jogamp.opengl.macosx.cgl;
import javax.media.nativewindow.DefaultGraphicsConfiguration;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2GL3;
@@ -94,11 +94,11 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
registerContext(ctx);
return ctx;
}
-
+
@Override
protected long getNSViewHandle() {
- // pbuffer handle is NSOpenGLPixelBuffer
- return 0;
+ // pbuffer handle is NSOpenGLPixelBuffer
+ return 0;
}
@Override
@@ -115,7 +115,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
NativeSurface ns = getNativeSurface();
impl.destroy(pBuffer);
this.pBuffer = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
}
@@ -174,7 +174,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
throw new GLException("pbuffer creation error: CGL.createPBuffer() failed");
}
- ((SurfaceChangeable)ns).setSurfaceHandle(pBuffer);
+ ((MutableSurface)ns).setSurfaceHandle(pBuffer);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
index a6fa01bad..edf9b7c84 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
@@ -58,14 +58,14 @@ import jogamp.opengl.macosx.cgl.MacOSXCGLGraphicsConfiguration;
public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
public static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new MacOSXAWTCGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, GLCapabilitiesImmutable.class, new MacOSXAWTCGLGraphicsConfigurationFactory());
}
private MacOSXAWTCGLGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
GraphicsDevice device = null;
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
@@ -103,9 +103,9 @@ public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigur
GraphicsConfiguration gc = device.getDefaultConfiguration();
MacOSXCGLGraphicsConfiguration macConfig = (MacOSXCGLGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(macDevice).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(macDevice, capsChosen).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, macScreen);
+ chooser, macScreen, nativeVisualID);
if (macConfig == null) {
throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+macScreen);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
index 31f13297b..6bf8839af 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
@@ -113,7 +113,7 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
// create EGLImage from texture
clientBuffer = null; // FIXME
nioTmp.put(0, EGL.EGL_NONE);
- image = eglExt.eglCreateImageKHR( eglDrawable.getDisplay(), eglCtx.getHandle(),
+ image = eglExt.eglCreateImageKHR( eglDrawable.getNativeSurface().getDisplayHandle(), eglCtx.getHandle(),
EGLExt.EGL_GL_TEXTURE_2D_KHR,
clientBuffer, nioTmp);
if (0==image) {
@@ -130,7 +130,7 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
// rendering the EGLImage texture before we tell OpenMAX to fill
// it with a new frame.
tmp[0] = EGL.EGL_NONE;
- sync = eglExt.eglCreateSyncKHR(eglDrawable.getDisplay(), EGLExt.EGL_SYNC_FENCE_KHR, tmp, 0);
+ sync = eglExt.eglCreateSyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), EGLExt.EGL_SYNC_FENCE_KHR, tmp, 0);
if (0==sync) {
throw new RuntimeException("EGLSync creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", err "+toHexString(EGL.eglGetError()));
}
@@ -159,10 +159,10 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
final EGLTextureFrame eglTex = (EGLTextureFrame) imgTex;
if(0!=eglTex.getImage()) {
- eglExt.eglDestroyImageKHR(eglDrawable.getDisplay(), eglTex.getImage());
+ eglExt.eglDestroyImageKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getImage());
}
if(0!=eglTex.getSync()) {
- eglExt.eglDestroySyncKHR(eglDrawable.getDisplay(), eglTex.getSync());
+ eglExt.eglDestroySyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getSync());
}
super.destroyTexImage(gl, imgTex);
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
index e255a0672..6a4ce5a4e 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
@@ -52,10 +52,11 @@ public class WGLGLCapabilities extends GLCapabilities {
public boolean setValuesByGDI() {
arb_pixelformat = -1;
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
setRedBits(pfd.getCRedBits());
setGreenBits(pfd.getCGreenBits());
setBlueBits(pfd.getCBlueBits());
- setAlphaBits(pfd.getCAlphaBits());
+ setAlphaBits(pfd.getCAlphaBits());
setAccumRedBits(pfd.getCAccumRedBits());
setAccumGreenBits(pfd.getCAccumGreenBits());
setAccumBlueBits(pfd.getCAccumBlueBits());
@@ -77,6 +78,7 @@ public class WGLGLCapabilities extends GLCapabilities {
public boolean setValuesByARB(final int[] iattribs, final int niattribs, final int[] iresults) {
arb_pixelformat = 1;
+ int alphaBits = 0;
for (int i = 0; i < niattribs; i++) {
int attr = iattribs[i];
switch (attr) {
@@ -143,7 +145,8 @@ public class WGLGLCapabilities extends GLCapabilities {
break;
case WGLExt.WGL_ALPHA_BITS_ARB:
- setAlphaBits(iresults[i]);
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
+ alphaBits = iresults[i];
break;
case WGLExt.WGL_ACCUM_RED_BITS_ARB:
@@ -174,6 +177,7 @@ public class WGLGLCapabilities extends GLCapabilities {
throw new GLException("Unknown pixel format attribute " + iattribs[i]);
}
}
+ setAlphaBits(alphaBits);
return true;
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
index 296d53ce3..cf6f43b1c 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
@@ -41,7 +41,7 @@
package jogamp.opengl.windows.wgl;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -139,7 +139,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
hbitmap = 0;
throw new GLException("Error creating device context for offscreen OpenGL context, werr "+werr);
}
- ((SurfaceChangeable)ns).setSurfaceHandle(hdc);
+ ((MutableSurface)ns).setSurfaceHandle(hdc);
if(DEBUG) {
System.err.println("WindowsBitmapWGLDrawable (2): "+ns);
}
@@ -164,7 +164,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
GDI.DeleteDC(ns.getSurfaceHandle());
origbitmap = 0;
hbitmap = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java
deleted file mode 100644
index 05d6d9862..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.windows.wgl;
-
-import javax.media.nativewindow.AbstractGraphicsScreen;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
-
-import jogamp.nativewindow.windows.GDI;
-import jogamp.nativewindow.windows.GDISurface;
-import jogamp.nativewindow.windows.GDIUtil;
-
-public class WindowsDummyWGLDrawable extends WindowsWGLDrawable {
- private long hwnd;
- private boolean handleHwndLifecycle;
-
- private WindowsDummyWGLDrawable(GLDrawableFactory factory, GDISurface ns, boolean handleHwndLifecycle) {
- super(factory, ns, true);
- this.handleHwndLifecycle = handleHwndLifecycle;
-
- if(NativeSurface.LOCK_SURFACE_NOT_READY >= ns.lockSurface()) {
- throw new GLException("WindowsDummyWGLDrawable: surface not ready (lockSurface)");
- }
- try {
- WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
- config.updateGraphicsConfiguration(factory, ns, null);
- if (DEBUG) {
- System.err.println("WindowsDummyWGLDrawable: "+config);
- }
- } catch (Throwable t) {
- setRealized(false);
- throw new GLException(t);
- } finally {
- unlockSurface();
- }
- }
-
- public static WindowsDummyWGLDrawable create(GLDrawableFactory factory, GLProfile glp, AbstractGraphicsScreen absScreen,
- long windowHandle, int width, int height, boolean handleWindowLifecycle) {
- if(0 == windowHandle) {
- throw new GLException("Error windowHandle 0, werr: "+GDI.GetLastError());
- }
- GLCapabilities caps = new GLCapabilities(glp);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(caps, absScreen);
- GDISurface ns = new GDISurface(cfg, windowHandle);
- ns.surfaceSizeChanged(width, height);
- return new WindowsDummyWGLDrawable(factory, ns, handleWindowLifecycle);
- }
-
- @Override
- public GLContext createContext(GLContext shareWith) {
- // FIXME: figure out how to hook back in the Java 2D / JOGL bridge
- return new WindowsWGLContext(this, shareWith);
- }
-
- @Override
- protected void setRealizedImpl() {
- super.setRealizedImpl();
- if(!realized) {
- if (handleHwndLifecycle && hwnd != 0) {
- GDI.ShowWindow(hwnd, GDI.SW_HIDE);
- GDIUtil.DestroyDummyWindow(hwnd);
- hwnd = 0;
- }
- }
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
index 86441c688..96c1187d3 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
@@ -55,7 +55,6 @@ import com.jogamp.nativewindow.WrappedSurface;
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLContextShareSet;
-
public class WindowsExternalWGLContext extends WindowsWGLContext {
private GLContext lastContext;
@@ -103,7 +102,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
System.err.println("WindowsExternalWGLContext valid hdc/pfd, retrieved cfg: " + cfg);
}
}
- return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc)), ctx, cfg);
+ return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc, 64, 64, null)), ctx, cfg);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
index 8f22aa60e..15bd005dc 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
@@ -50,6 +50,7 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import jogamp.nativewindow.windows.GDI;
+import jogamp.nativewindow.windows.GDIUtil;
import com.jogamp.nativewindow.WrappedSurface;
@@ -69,9 +70,9 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable {
throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat, werr " + GDI.GetLastError());
}
- AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true);
- return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc));
+ final AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
+ final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true);
+ return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc, 64, 64, null));
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
index a11d6e78e..7dda6a1f1 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
@@ -42,6 +42,8 @@ package jogamp.opengl.windows.wgl;
import javax.media.opengl.*;
+import com.jogamp.opengl.GLExtensions;
+
import jogamp.opengl.GLContextImpl;
public class WindowsPbufferWGLContext extends WindowsWGLContext {
@@ -112,7 +114,7 @@ public class WindowsPbufferWGLContext extends WindowsWGLContext {
} else {
hasRTT = true;
- if (rect && !gl.isExtensionAvailable("GL_NV_texture_rectangle")) {
+ if (rect && !gl.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
System.err.println("WindowsPbufferWGLContext: WARNING: GL_NV_texture_rectangle extension not " +
"supported; skipping requested render_to_texture_rectangle support for pbuffer");
rect = false;
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
index b00c796ec..175622343 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
@@ -42,7 +42,7 @@ package jogamp.opengl.windows.wgl;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -92,7 +92,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
if (wglExt.wglReleasePbufferDCARB(buffer, ns.getSurfaceHandle()) == 0) {
throw new GLException("Error releasing pbuffer device context: error code " + GDI.GetLastError());
}
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
if (!wglExt.wglDestroyPbufferARB(buffer)) {
throw new GLException("Error destroying pbuffer: error code " + GDI.GetLastError());
@@ -121,7 +121,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
}
try {
long sharedHdc = sharedSurface.getSurfaceHandle();
- WGLExt wglExt = sharedResource.getContext().getWGLExt();
+ WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt();
if (DEBUG) {
System.out.println("Pbuffer config: " + config);
@@ -131,7 +131,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
float[] fattributes = new float[1];
int[] floatModeTmp = new int[1];
int niattribs = 0;
- int width, height;
GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
GLProfile glProfile = chosenCaps.getGLProfile();
@@ -206,7 +205,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB;
iattributes[niattribs++] = GL.GL_FALSE;
- iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB;
+ iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; // exact
iattributes[niattribs++] = GL.GL_FALSE;
}
@@ -235,7 +234,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
NativeSurface ns = getNativeSurface();
// Set up instance variables
buffer = tmpBuffer;
- ((SurfaceChangeable)ns).setSurfaceHandle(tmpHdc);
+ ((MutableSurface)ns).setSurfaceHandle(tmpHdc);
cachedWGLExt = wglExt;
// Re-query chosen pixel format
@@ -249,14 +248,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
}
config.setCapsPFD(newCaps);
}
-
- // Determine the actual width and height we were able to create.
- int[] tmp = new int[1];
- wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB, tmp, 0 );
- width = tmp[0];
- wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 );
- height = tmp[0];
- ((SurfaceChangeable)ns).surfaceSizeChanged(width, height);
} finally {
sharedSurface.unlockSurface();
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index f143c158b..8825bad0a 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -53,6 +53,8 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
@@ -77,8 +79,8 @@ public class WindowsWGLContext extends GLContextImpl {
functionNameMap.put("glFreeMemoryNV", "wglFreeMemoryNV");
extensionNameMap = new HashMap<String, String>();
- extensionNameMap.put("GL_ARB_pbuffer", "WGL_ARB_pbuffer");
- extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format");
+ extensionNameMap.put(GLExtensions.ARB_pbuffer, WindowsWGLDrawableFactory.WGL_ARB_pbuffer);
+ extensionNameMap.put(GLExtensions.ARB_pixel_format, WindowsWGLDrawableFactory.WGL_ARB_pixel_format);
}
// FIXME: figure out how to hook back in the Java 2D / JOGL bridge
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 176d27a71..09e97ff79 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -51,9 +51,10 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -67,9 +68,11 @@ import jogamp.nativewindow.windows.GDISurface;
import jogamp.nativewindow.windows.GDIUtil;
import jogamp.nativewindow.windows.RegisteredClassFactory;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.JogampRuntimeException;
@@ -79,6 +82,7 @@ import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.WrappedSurface;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
+import com.jogamp.opengl.GLExtensions;
public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null;
@@ -203,8 +207,8 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
static class SharedResource implements SharedResourceRunner.Resource {
private WindowsGraphicsDevice device;
private AbstractGraphicsScreen screen;
- private WindowsDummyWGLDrawable drawable;
- private WindowsWGLContext context;
+ private GLDrawableImpl drawable;
+ private GLContextImpl context;
private boolean hasARBPixelFormat;
private boolean hasARBMultisample;
private boolean hasARBPBuffer;
@@ -214,7 +218,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private boolean isVendorNVIDIA;
private boolean needsCurrenContext4ARBPFDQueries;
- SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx,
+ SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, GLDrawableImpl draw, GLContextImpl ctx,
boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable, String glVendor) {
device = dev;
screen = scrn;
@@ -250,9 +254,9 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
@Override
final public AbstractGraphicsScreen getScreen() { return screen; }
@Override
- final public WindowsWGLDrawable getDrawable() { return drawable; }
+ final public GLDrawableImpl getDrawable() { return drawable; }
@Override
- final public WindowsWGLContext getContext() { return context; }
+ final public GLContextImpl getContext() { return context; }
final boolean hasARBPixelFormat() { return hasARBPixelFormat; }
final boolean hasARBMultisample() { return hasARBMultisample; }
@@ -302,21 +306,18 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
@Override
public SharedResourceRunner.Resource createSharedResource(String connection) {
- WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT);
+ final WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT);
sharedDevice.lock();
try {
- AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0);
- GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
+ final AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0);
+ final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
- final int f_dim = 64;
- long hwnd = GDIUtil.CreateDummyWindow(0, 0, f_dim, f_dim);
- WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(WindowsWGLDrawableFactory.this, glp, absScreen, hwnd, f_dim, f_dim, true);
- if (null == sharedDrawable) {
- throw new GLException("Couldn't create shared drawable for screen: "+absScreen+", "+glp);
- }
- WindowsWGLContext sharedContext = (WindowsWGLContext) sharedDrawable.createContext(null);
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+ sharedDrawable.setRealized(true);
+
+ final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
}
@@ -329,7 +330,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
try {
hasARBPixelFormat = sharedContext.isExtensionAvailable(WGL_ARB_pixel_format);
hasARBMultisample = sharedContext.isExtensionAvailable(WGL_ARB_multisample);
- hasARBPBuffer = sharedContext.isExtensionAvailable(GL_ARB_pbuffer);
+ hasARBPBuffer = sharedContext.isExtensionAvailable(GLExtensions.ARB_pbuffer);
hasARBReadDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) &&
sharedContext.isFunctionAvailable(wglMakeContextCurrent);
vendor = sharedContext.getGL().glGetString(GL.GL_VENDOR);
@@ -401,7 +402,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return false;
}
- final static String GL_ARB_pbuffer = "GL_ARB_pbuffer";
+ final static String WGL_ARB_pbuffer = "WGL_ARB_pbuffer";
final static String WGL_ARB_pixel_format = "WGL_ARB_pixel_format";
final static String WGL_ARB_multisample = "WGL_ARB_multisample";
final static String WGL_NV_float_buffer = "WGL_NV_float_buffer";
@@ -534,22 +535,89 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
- WrappedSurface ns = new WrappedSurface(WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsChosen, capsRequested, chooser, screen) );
- ns.surfaceSizeChanged(width, height);
- return ns;
+ protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+ final WindowsGraphicsDevice device;
+ if(createNewDevice) {
+ device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
+ } else {
+ device = (WindowsGraphicsDevice)deviceReq;
+ }
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
+ return new WrappedSurface(config, 0, width, height, lifecycleHook);
}
@Override
- protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- WindowsGraphicsDevice device = (WindowsGraphicsDevice) adevice;
- AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
- GDISurface ns = new GDISurface(cfg, windowHandle);
- return ns;
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final WindowsGraphicsDevice device;
+ if(createNewDevice) {
+ device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
+ } else {
+ device = (WindowsGraphicsDevice)deviceReq;
+ }
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(chosenCaps, requestedCaps, chooser, screen);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+requestedCaps+" on "+screen);
+ }
+ return new GDISurface(config, 0, width, height, dummySurfaceLifecycleHook);
+ }
+ private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) {
+ final GDISurface ms = (GDISurface)s;
+ if(0 == ms.getWindowHandle()) {
+ final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, s.getWidth(), s.getHeight());
+ if(0 == windowHandle) {
+ throw new GLException("Error windowHandle 0, werr: "+GDI.GetLastError());
+ }
+ ms.setWindowHandle(windowHandle);
+ if(DEBUG) {
+ System.err.println("WindowsWGLDrawableFactory.dummySurfaceLifecycleHook.create: "+ms);
+ }
+ }
+ }
+ @Override
+ public final void destroy(ProxySurface s) {
+ final GDISurface ms = (GDISurface)s;
+ if(0 != ms.getWindowHandle()) {
+ GDI.ShowWindow(ms.getWindowHandle(), GDI.SW_HIDE);
+ GDIUtil.DestroyDummyWindow(ms.getWindowHandle());
+ ms.setWindowHandle(0);
+ if(DEBUG) {
+ System.err.println("WindowsWGLDrawableFactory.dummySurfaceLifecycleHook.destroy: "+ms);
+ }
+ }
+ }
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return s.initialWidth;
+ }
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return s.initialHeight;
+ }
+
+ @Override
+ public String toString() {
+ return "GDISurfaceLifecycleHook[]";
+ }
+ };
+
+
+ @Override
+ protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final WindowsGraphicsDevice device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
+ final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
+ return new GDISurface(cfg, windowHandle, 0, 0, upstream);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
index 408d8b074..209589b29 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
@@ -48,11 +48,13 @@ import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.opengl.GLExtensions;
import jogamp.nativewindow.windows.DWM_BLURBEHIND;
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.MARGINS;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
@@ -160,7 +162,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
if (!WGLUtil.SetPixelFormat(hdc, caps.getPFDID(), caps.getPFD())) {
- throw new GLException("Unable to set pixel format " + caps +
+ throw new GLException("Unable to set pixel format " + caps.getPFDID() + " of " + caps +
" for device context " + toHexString(hdc) +
": error code " + GDI.GetLastError());
}
@@ -250,7 +252,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
if(sharedResource.hasARBPBuffer()) {
- WindowsWGLContext sharedCtx = sharedResource.getContext();
+ GLContextImpl sharedCtx = sharedResource.getContext();
if(null != sharedCtx && sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer)) {
// pbo float buffer
iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; // nvidia
@@ -313,12 +315,12 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes);
- if (!sharedResource.getContext().getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) {
+ if (!((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) {
throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID +
" of device context " + toHexString(hdc) + ", werr " + GDI.GetLastError());
}
List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(1);
- final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+ final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
if(AttribList2GLCapabilities(bucket, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits)) {
return (WGLGLCapabilities) bucket.get(0);
}
@@ -342,7 +344,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
int[] pformatsTmp = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS];
int[] numFormatsTmp = new int[1];
- if ( !sharedResource.getContext().getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0,
+ if ( !((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0,
fattributes, 0,
WindowsWGLGraphicsConfiguration.MAX_PFORMATS,
pformatsTmp, 0, numFormatsTmp, 0))
@@ -374,7 +376,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
static List<GLCapabilitiesImmutable> wglARBPFIDs2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource,
long hdc, int[] pfdIDs, GLProfile glp, boolean onscreen, boolean usePBuffer) {
- final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+ final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
return wglARBPFIDs2GLCapabilitiesImpl(sharedResource, hdc, pfdIDs, glp, winattrbits);
}
@@ -398,7 +400,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
for(int i = 0; i<numFormats; i++) {
if ( pfdIDs[i] >= 1 &&
- sharedResource.getContext().getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) {
+ ((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) {
AttribList2GLCapabilities(bucket, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits);
} else if (DEBUG) {
System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " +
@@ -507,9 +509,9 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified");
}
- WindowsWGLContext sharedCtx = sharedResource.getContext();
+ GLContextImpl sharedCtx = sharedResource.getContext();
if (rect) {
- if (!sharedCtx.isExtensionAvailable("GL_NV_texture_rectangle")) {
+ if (!sharedCtx.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension");
}
}
@@ -658,7 +660,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
static WGLGLCapabilities PFD2GLCapabilities(GLProfile glp, long hdc, int pfdID, boolean onscreen) {
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false, false);
List<GLCapabilitiesImmutable> capsBucket = new ArrayList<GLCapabilitiesImmutable>(1);
if( PFD2GLCapabilities(capsBucket, glp, hdc, pfdID, winattrmask) ) {
return (WGLGLCapabilities) capsBucket.get(0);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
index 850b64aa8..00ed91bb4 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
@@ -52,6 +52,7 @@ import javax.media.opengl.GLProfile;
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
+import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLGraphicsConfigurationFactory;
import jogamp.opengl.GLGraphicsConfigurationUtil;
@@ -68,13 +69,13 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
static VisualIDHolder.VIDComparator PfdIDComparator = new VisualIDHolder.VIDComparator(VisualIDHolder.VIDType.WIN32_PFD);
static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.windows.WindowsGraphicsDevice.class, new WindowsWGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.windows.WindowsGraphicsDevice.class, GLCapabilitiesImmutable.class, new WindowsWGLGraphicsConfigurationFactory());
}
private WindowsWGLGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (! (capsChosen instanceof GLCapabilitiesImmutable) ) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - chosen");
@@ -99,10 +100,10 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if(null==absScreen) {
absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
}
- AbstractGraphicsDevice absDevice = absScreen.getDevice();
-
+ final AbstractGraphicsDevice absDevice = absScreen.getDevice();
+ final GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory();
capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities(
- capsChosen, GLDrawableFactory.getDesktopFactory().canCreateGLPbuffer(absDevice) );
+ capsChosen, GLContext.isFBOAvailable(absDevice, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(absDevice) );
return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, (GLCapabilitiesChooser)chooser );
}
@@ -112,9 +113,9 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
- WindowsWGLDrawable sharedDrawable = sharedResource.getDrawable();
+ GLDrawableImpl sharedDrawable = sharedResource.getDrawable();
GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities();
- WindowsWGLContext sharedContext = sharedResource.getContext();
+ GLContext sharedContext = sharedResource.getContext();
List<GLCapabilitiesImmutable> availableCaps = null;
if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
@@ -150,7 +151,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesARB(long hdc, WindowsWGLDrawableFactory.SharedResource sharedResource, GLProfile glProfile) {
- int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedResource.getContext(), hdc);
+ int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs((WindowsWGLContext)sharedResource.getContext(), hdc);
return WindowsWGLGraphicsConfiguration.wglARBPFIDs2AllGLCapabilities(sharedResource, hdc, pformats, glProfile);
}
@@ -265,7 +266,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
AbstractGraphicsDevice device = config.getScreen().getDevice();
WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(device);
- WindowsWGLContext sharedContext = null;
+ GLContext sharedContext = null;
if (null != sharedResource && sharedResource.needsCurrentContext4ARBPFDQueries()) {
sharedContext = sharedResource.getContext();
if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
@@ -355,7 +356,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
System.err.println("updateGraphicsConfigurationARB: wglChoosePixelFormatARB failed with: "+capsChosen);
}
// 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available
- pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedResource.getContext(), hdc);
+ pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs((WindowsWGLContext)sharedResource.getContext(), hdc);
if (DEBUG) {
final int len = ( null != pformats ) ? pformats.length : 0;
System.err.println("updateGraphicsConfigurationARB: NumFormats (wglAllARBPFIDs) " + len);
@@ -451,7 +452,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if(null == pformats) {
pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc);
}
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false, false);
for (int i = 0; i < pformats.length; i++) {
WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(availableCaps, glProfile, hdc, pformats[i], winattrmask);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
index bd64b58a4..3b2ff133a 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
@@ -63,14 +63,14 @@ import javax.media.opengl.GLDrawableFactory;
public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
public static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new WindowsAWTWGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, GLCapabilitiesImmutable.class, new WindowsAWTWGLGraphicsConfigurationFactory());
}
private WindowsAWTWGLGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
GraphicsDevice device = null;
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
@@ -105,11 +105,11 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex());
- GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice);
+ GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice, capsChosen);
WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration)
configFactory.chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, winScreen);
+ chooser, winScreen, nativeVisualID);
if (winConfig == null) {
throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+winScreen);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java
deleted file mode 100644
index 8914e2db9..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package jogamp.opengl.x11.glx;
-
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLProfile;
-
-import jogamp.nativewindow.x11.X11Lib;
-
-import com.jogamp.nativewindow.WrappedSurface;
-import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import com.jogamp.nativewindow.x11.X11GraphicsScreen;
-
-public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable {
- private static final int f_dim = 64;
- private long dummyWindow = 0;
-
- /**
- * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277,
- * we cannot switch the Display as we please,
- * hence we reuse the target's screen configuration.
- */
- public X11DummyGLXDrawable(X11GraphicsScreen screen, GLDrawableFactory factory, GLCapabilitiesImmutable caps) {
- super(factory,
- new WrappedSurface(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- caps, caps, null, screen)));
- this.realized = true;
-
- WrappedSurface ns = (WrappedSurface) getNativeSurface();
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)ns.getGraphicsConfiguration();
-
- X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
- long dpy = device.getHandle();
- int scrn = screen.getIndex();
- int visualID = config.getXVisualID();
-
- dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID, f_dim, f_dim);
- ns.setSurfaceHandle( dummyWindow );
- ns.surfaceSizeChanged(f_dim, f_dim);
-
- updateHandle();
- }
-
- public static X11DummyGLXDrawable create(X11GraphicsScreen screen, GLDrawableFactory factory, GLProfile glp) {
- GLCapabilities caps = new GLCapabilities(glp);
- return new X11DummyGLXDrawable(screen, factory, caps);
- }
-
- public void setSize(int width, int height) {
- }
-
- @Override
- public int getWidth() {
- return 1;
- }
-
- @Override
- public int getHeight() {
- return 1;
- }
-
-
- @Override
- protected void setRealizedImpl() {
- super.setRealizedImpl();
- if(!realized) {
- if(0!=dummyWindow) {
- destroyHandle();
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
- X11Lib.DestroyDummyWindow(config.getScreen().getDevice().getHandle(), dummyWindow);
- }
- }
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
index 53776386c..1f3edbd8a 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
@@ -41,6 +41,7 @@
package jogamp.opengl.x11.glx;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -76,8 +77,15 @@ public class X11ExternalGLXContext extends X11GLXContext {
long drawable = GLX.glXGetCurrentDrawable();
if (drawable == 0) {
throw new GLException("Error: attempted to make an external GLDrawable without a drawable/context current");
- }
+ }
int[] val = new int[1];
+
+ int w, h;
+ GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val, 0);
+ w=val[0];
+ GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val, 0);
+ h=val[0];
+
GLX.glXQueryContext(display, ctx, GLX.GLX_SCREEN, val, 0);
X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0], false);
@@ -87,9 +95,9 @@ public class X11ExternalGLXContext extends X11GLXContext {
// of 0, which doesn't work in a subsequent call to glXChooseFBConfig; if this happens,
// create and use a default config (this has been observed when running on CentOS 5.5 inside
// of VMWare Server 2.0 with the Mesa 6.5.1 drivers)
- if( X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val[0]) ) {
+ if( VisualIDHolder.VID_UNDEFINED == val[0] || !X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val[0]) ) {
GLCapabilities glcapsDefault = new GLCapabilities(GLProfile.getDefault());
- cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(glcapsDefault, glcapsDefault, null, x11Screen);
+ cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(glcapsDefault, glcapsDefault, null, x11Screen, VisualIDHolder.VID_UNDEFINED);
if(DEBUG) {
System.err.println("X11ExternalGLXContext invalid FBCONFIG_ID "+val[0]+", using default cfg: " + cfg);
}
@@ -97,8 +105,7 @@ public class X11ExternalGLXContext extends X11GLXContext {
cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]);
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(drawable);
+ final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, null);
return new X11ExternalGLXContext(new Drawable(factory, ns), ctx);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
index 3fabe7a13..8652e2d4a 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
@@ -87,10 +87,7 @@ public class X11ExternalGLXDrawable extends X11GLXDrawable {
System.err.println("X11ExternalGLXDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts (current 0x"+Integer.toHexString(val[0])+")");
}
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(drawable);
- ns.surfaceSizeChanged(w, h);
- return new X11ExternalGLXDrawable(factory, ns);
+ return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, null));
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index 0afadc677..e1e25be67 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -61,6 +61,7 @@ import jogamp.opengl.GLDrawableImpl;
import com.jogamp.common.nio.Buffers;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
public abstract class X11GLXContext extends GLContextImpl {
private static final Map<String, String> functionNameMap;
@@ -83,8 +84,8 @@ public abstract class X11GLXContext extends GLContextImpl {
functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV");
extensionNameMap = new HashMap<String, String>();
- extensionNameMap.put("GL_ARB_pbuffer", "GLX_SGIX_pbuffer");
- extensionNameMap.put("GL_ARB_pixel_format", "GLX_SGIX_pbuffer"); // good enough
+ extensionNameMap.put(GLExtensions.ARB_pbuffer, X11GLXDrawableFactory.GLX_SGIX_pbuffer);
+ extensionNameMap.put(GLExtensions.ARB_pixel_format, X11GLXDrawableFactory.GLX_SGIX_pbuffer); // good enough
}
X11GLXContext(GLDrawableImpl drawable,
@@ -151,7 +152,7 @@ public abstract class X11GLXContext extends GLContextImpl {
throw new InternalError("Given readDrawable but no driver support");
}
} catch (RuntimeException re) {
- if(TRACE_SWITCH) {
+ if(DEBUG || TRACE_SWITCH) {
System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+
"dpy "+toHexString(dpy)+
", write "+toHexString(writeDrawable)+
@@ -508,8 +509,8 @@ public abstract class X11GLXContext extends GLContextImpl {
@Override
public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals("GL_ARB_pbuffer") ||
- glExtensionName.equals("GL_ARB_pixel_format")) {
+ if (glExtensionName.equals(GLExtensions.ARB_pbuffer) ||
+ glExtensionName.equals(GLExtensions.ARB_pixel_format)) {
return getGLDrawable().getFactory().canCreateGLPbuffer(
drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice() );
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 9a563bdb8..b2e74f9d4 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -49,6 +49,9 @@ import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -64,6 +67,7 @@ import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.util.VersionNumber;
@@ -79,6 +83,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
public static final VersionNumber versionOneThree = new VersionNumber(1, 3, 0);
public static final VersionNumber versionOneFour = new VersionNumber(1, 4, 0);
+ static final String GLX_SGIX_pbuffer = "GLX_SGIX_pbuffer";
+
private static DesktopGLDynamicLookupHelper x11GLXDynamicLookupHelper = null;
public X11GLXDrawableFactory() {
@@ -153,8 +159,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
static class SharedResource implements SharedResourceRunner.Resource {
X11GraphicsDevice device;
X11GraphicsScreen screen;
- X11DummyGLXDrawable drawable;
- X11GLXContext context;
+ GLDrawableImpl drawable;
+ GLContextImpl context;
String glXServerVendorName;
boolean isGLXServerVendorATI;
boolean isGLXServerVendorNVIDIA;
@@ -164,7 +170,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
boolean glXMultisampleAvailable;
SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn,
- X11DummyGLXDrawable draw, X11GLXContext ctx,
+ GLDrawableImpl draw, GLContextImpl ctx,
VersionNumber glXServerVer, String glXServerVendor, boolean glXServerMultisampleAvail) {
device = dev;
screen = scrn;
@@ -224,13 +230,15 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
@Override
public SharedResourceRunner.Resource createSharedResource(String connection) {
- X11GraphicsDevice sharedDevice =
+ final X11GraphicsDevice sharedDevice =
new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT,
- true); // own non-shared display connection, no locking
+ true); // own non-shared display connection, w/ locking
// new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT,
- // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, no locking
+ // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, w/o locking
sharedDevice.lock();
try {
+ final X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0);
+
if(!GLXUtil.isGLXAvailableOnServer(sharedDevice)) {
throw new GLException("GLX not available on device/server: "+sharedDevice);
}
@@ -242,20 +250,20 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
X11Util.setMarkAllDisplaysUnclosable(true);
X11Util.markDisplayUncloseable(sharedDevice.getHandle());
}
- X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0);
-
- GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
+
+ final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
- X11DummyGLXDrawable sharedDrawable = X11DummyGLXDrawable.create(sharedScreen, X11GLXDrawableFactory.this, glp);
- if (null == sharedDrawable) {
- throw new GLException("Couldn't create shared drawable for screen: "+sharedScreen+", "+glp);
- }
- X11GLXContext sharedContext = (X11GLXContext) sharedDrawable.createContext(null);
+
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+ sharedDrawable.setRealized(true);
+
+ final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
}
+
boolean madeCurrent = false;
sharedContext.makeCurrent();
try {
@@ -298,7 +306,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
if (null != sr.context) {
// may cause JVM SIGSEGV:
- sr.context.destroy();
+ sr.context.destroy(); // will also pull the dummy MutuableSurface
sr.context = null;
}
@@ -394,7 +402,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- return new X11OnscreenGLXDrawable(this, target);
+ return new X11OnscreenGLXDrawable(this, target, false);
}
@Override
@@ -495,40 +503,98 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
- if(null == deviceReq) {
- throw new InternalError("deviceReq is null");
- }
- final SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(deviceReq);
- if(null==sr) {
- throw new InternalError("No SharedResource for: "+deviceReq);
+ protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+ final X11GraphicsDevice device;
+ if(createNewDevice) {
+ // Null X11 locking, due to private non-shared Display handle
+ device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true);
+ } else {
+ device = (X11GraphicsDevice)deviceReq;
}
- final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sr.getScreen();
- final AbstractGraphicsDevice sharedDevice = sharedScreen.getDevice(); // should be same ..
-
- // create screen/device pair - Null X11 locking, due to private non-shared Display handle
- final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(sharedDevice.getConnection()), AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), true);
- final X11GraphicsScreen screen = new X11GraphicsScreen(device, sharedScreen.getIndex());
-
- WrappedSurface ns = new WrappedSurface(
- X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen) );
- if(ns != null) {
- ns.surfaceSizeChanged(width, height);
+ final X11GraphicsScreen screen = new X11GraphicsScreen(device, 0);
+ final X11GLXGraphicsConfiguration config = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
}
- return ns;
+ return new WrappedSurface( config, 0, width, height, lifecycleHook);
}
@Override
- protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- X11GraphicsDevice device = (X11GraphicsDevice) adevice;
- X11GraphicsScreen screen = new X11GraphicsScreen(device, 0);
- X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
- WrappedSurface ns = new WrappedSurface(cfg, windowHandle);
- return ns;
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook);
+ }
+ private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) {
+ if( 0 == s.getSurfaceHandle() ) {
+ final X11GLXGraphicsConfiguration cfg = (X11GLXGraphicsConfiguration) s.getGraphicsConfiguration();
+ final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen();
+ final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
+ if(0 == device.getHandle()) {
+ device.open();
+ s.setImplBitfield(ProxySurface.OWN_DEVICE);
+ }
+ final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), s.getWidth(), s.getHeight());
+ if(0 == windowHandle) {
+ throw new GLException("Creating dummy window failed w/ "+cfg+", "+s.getWidth()+"x"+s.getHeight());
+ }
+ s.setSurfaceHandle(windowHandle);
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+ }
+ }
+ }
+ @Override
+ public final void destroy(ProxySurface s) {
+ if(0 != s.getSurfaceHandle()) {
+ final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) s.getGraphicsConfiguration();
+ final X11GraphicsDevice device = (X11GraphicsDevice) config.getScreen().getDevice();
+ X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(0);
+ if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) {
+ device.close();
+ }
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.dummySurfaceLifecycleHook.destroy: "+s);
+ }
+ }
+ }
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return s.initialWidth;
+ }
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return s.initialHeight;
+ }
+ @Override
+ public String toString() {
+ return "X11SurfaceLifecycleHook[]";
+ }
+ };
+
+
+ @Override
+ protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true);
+ final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx);
+ final int xvisualID = X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
+ if(VisualIDHolder.VID_UNDEFINED == xvisualID) {
+ throw new GLException("Undefined VisualID of window 0x"+Long.toHexString(windowHandle)+", window probably invalid");
+ }
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": visualID 0x"+Integer.toHexString(xvisualID));
+ }
+ final X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, xvisualID);
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": "+cfg);
+ }
+ return new WrappedSurface(cfg, windowHandle, 0, 0, upstream);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index b54b5150c..b458fffe1 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
@@ -36,12 +36,16 @@ package jogamp.opengl.x11.glx;
import java.util.ArrayList;
import java.util.List;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
@@ -67,7 +71,8 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) {
- final long display = x11Screen.getDevice().getHandle();
+ final AbstractGraphicsDevice device = x11Screen.getDevice();
+ final long display = device.getHandle();
if(0==display) {
throw new GLException("Display null of "+x11Screen);
}
@@ -80,7 +85,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
glp = GLProfile.getDefault(x11Screen.getDevice());
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(x11Screen.getDevice()));
+ final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, device, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(device));
if(null==caps) {
throw new GLException("GLCapabilities null of "+toHexString(fbcfg));
}
@@ -99,16 +104,25 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
void updateGraphicsConfiguration() {
- X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(
- getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen());
- if(null!=newConfig) {
- // FIXME: setScreen( ... );
- setXVisualInfo(newConfig.getXVisualInfo());
- setChosenCapabilities(newConfig.getChosenCapabilities());
- if(DEBUG) {
- System.err.println("updateGraphicsConfiguration: "+this);
+ final CapabilitiesImmutable aChosenCaps = getChosenCapabilities();
+ if( !(aChosenCaps instanceof X11GLCapabilities) || VisualIDHolder.VID_UNDEFINED == aChosenCaps.getVisualID(VIDType.X11_XVISUAL) ) {
+ // This case is actually quite impossible, since on X11 the visualID and hence GraphicsConfiguration
+ // must be determined _before_ window creation!
+ final X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration)
+ GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), aChosenCaps).chooseGraphicsConfiguration(
+ aChosenCaps, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED);
+ if(null!=newConfig) {
+ // FIXME: setScreen( ... );
+ setXVisualInfo(newConfig.getXVisualInfo());
+ setChosenCapabilities(newConfig.getChosenCapabilities());
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.updateGraphicsConfiguration updated:"+this);
+ }
+ } else {
+ throw new GLException("No native VisualID pre-chosen and update failed: "+this);
}
+ } else if (DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.updateGraphicsConfiguration kept:"+this);
}
}
@@ -233,11 +247,11 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
return true;
}
- static int FBCfgDrawableTypeBits(final long display, final long fbcfg) {
+ static int FBCfgDrawableTypeBits(final AbstractGraphicsDevice device, GLProfile glp, final long fbcfg) {
int val = 0;
int[] tmp = new int[1];
- int fbtype = glXGetFBConfig(display, fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0);
+ int fbtype = glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0);
if ( 0 != ( fbtype & GLX.GLX_WINDOW_BIT ) ) {
val |= GLGraphicsConfigurationUtil.WINDOW_BIT;
@@ -248,17 +262,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
if ( 0 != ( fbtype & GLX.GLX_PBUFFER_BIT ) ) {
val |= GLGraphicsConfigurationUtil.PBUFFER_BIT;
}
+ if ( GLContext.isFBOAvailable(device, glp) ) {
+ val |= GLGraphicsConfigurationUtil.FBO_BIT;
+ }
return val;
}
- static X11GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg,
+ static X11GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, AbstractGraphicsDevice device, long fbcfg,
boolean relaxed, boolean onscreen, boolean usePBuffer,
boolean isMultisampleAvailable) {
ArrayList<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
- if( GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, winattrmask, isMultisampleAvailable) ) {
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
+ if( GLXFBConfig2GLCapabilities(bucket, glp, device, fbcfg, winattrmask, isMultisampleAvailable) ) {
return (X11GLCapabilities) bucket.get(0);
- } else if ( relaxed && GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
+ } else if ( relaxed && GLXFBConfig2GLCapabilities(bucket, glp, device, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
return (X11GLCapabilities) bucket.get(0);
}
return null;
@@ -273,11 +290,12 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
static boolean GLXFBConfig2GLCapabilities(List<GLCapabilitiesImmutable> capsBucket,
- GLProfile glp, long display, long fbcfg,
+ GLProfile glp, AbstractGraphicsDevice device, long fbcfg,
int winattrmask, boolean isMultisampleAvailable) {
- final int allDrawableTypeBits = FBCfgDrawableTypeBits(display, fbcfg);
+ final int allDrawableTypeBits = FBCfgDrawableTypeBits(device, glp, fbcfg);
int drawableTypeBits = winattrmask & allDrawableTypeBits;
-
+
+ final long display = device.getHandle();
int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
if(null == visualInfo) {
@@ -301,19 +319,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp);
- res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0);
- res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0);
- res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG);
- res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0));
- res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0));
- res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0));
- res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0));
- res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0));
- res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0));
- res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
- res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
- res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
- res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
if (isMultisampleAvailable) {
res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0);
res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0));
@@ -329,6 +334,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
res.setTransparentBlueValue(xrmask.getBlueMask());
res.setTransparentAlphaValue(alphaMask);
}
+ // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
+ res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0);
+ res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0);
+ res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG);
+ res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0));
+ res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0));
+ res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0));
+ res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0));
+ res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
+ res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
+ res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
+ res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
+ res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0));
+ res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0));
try {
res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE);
@@ -422,18 +441,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
// Note: use of hardware acceleration is determined by
// glXCreateContext, not by the XVisualInfo. Optimistically claim
// that all GLCapabilities have the capability to be hardware
- // accelerated.
- res.setHardwareAccelerated(true);
- res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0));
- res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0));
- res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0));
- res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0));
- res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0));
- res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0));
- res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
- res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
- res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
- res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
+ // accelerated.
if (isMultisampleEnabled) {
res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0);
res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp, 0));
@@ -449,6 +457,18 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
res.setTransparentBlueValue(xrmask.getBlueMask());
res.setTransparentAlphaValue(alphaMask);
}
+ // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
+ res.setHardwareAccelerated(true);
+ res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0));
+ res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0));
+ res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0));
+ res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0));
+ res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0));
+ res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0));
+ res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
+ res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
+ res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
+ res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
index 8377d2453..234b06bdb 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
@@ -40,10 +40,12 @@ import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
@@ -73,20 +75,24 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
static GraphicsConfigurationFactory fallbackX11GraphicsConfigurationFactory = null;
static void registerFactory() {
final GraphicsConfigurationFactory newFactory = new X11GLXGraphicsConfigurationFactory();
- final GraphicsConfigurationFactory oldFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, newFactory);
+ final GraphicsConfigurationFactory oldFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, newFactory);
if(oldFactory == newFactory) {
throw new InternalError("GraphicsConfigurationFactory lifecycle impl. error");
}
- if(null == oldFactory) {
- throw new InternalError("Missing fallback GraphicsConfigurationFactory");
+ if(null != oldFactory) {
+ fallbackX11GraphicsConfigurationFactory = oldFactory;
+ } else {
+ fallbackX11GraphicsConfigurationFactory = GraphicsConfigurationFactory.getFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class);
+ if( null == fallbackX11GraphicsConfigurationFactory ) {
+ throw new InternalError("Missing fallback GraphicsConfigurationFactory");
+ }
}
- fallbackX11GraphicsConfigurationFactory = oldFactory;
}
private X11GLXGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (!(absScreen instanceof X11GraphicsScreen)) {
throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here");
}
@@ -108,12 +114,12 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
if(DEBUG) {
System.err.println("No GLX available, fallback to "+fallbackX11GraphicsConfigurationFactory.getClass().getSimpleName()+" for: "+absScreen);
}
- return fallbackX11GraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen);
+ return fallbackX11GraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, VisualIDHolder.VID_UNDEFINED);
}
throw new InternalError("No GLX and no fallback GraphicsConfigurationFactory available for: "+absScreen);
}
return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested,
- (GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen);
+ (GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen, nativeVisualID);
}
protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(X11GLXDrawableFactory factory, AbstractGraphicsDevice device) {
@@ -161,7 +167,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
return null;
}
for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
+ if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
}
@@ -198,7 +204,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
static X11GLXGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
if (x11Screen == null) {
throw new IllegalArgumentException("AbstractGraphicsScreen is null");
}
@@ -209,24 +215,24 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(x11Device) );
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(x11Device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(x11Device) );
boolean usePBuffer = capsChosen.isPBuffer();
X11GLXGraphicsConfiguration res = null;
if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) {
- res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen);
+ res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen, xvisualID);
}
if(null==res) {
if(usePBuffer) {
- throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for "+capsChosen);
+ throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for visualID "+toHexString(xvisualID)+", "+capsChosen);
}
- res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen);
+ res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen, xvisualID);
}
if(null==res) {
- throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for "+capsChosen);
+ throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for visualID "+toHexString(xvisualID)+", "+x11Screen+", "+capsChosen);
}
if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic("+x11Screen+","+capsChosen+"): "+res);
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic(visualID "+toHexString(xvisualID)+", "+x11Screen+","+capsChosen+"): "+res);
}
return res;
}
@@ -245,19 +251,20 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(absDevice));
+ final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, absDevice, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(absDevice));
return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser());
}
private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
int recommendedIndex = -1;
PointerBuffer fbcfgsL = null;
GLProfile glProfile = capsChosen.getGLProfile();
boolean onscreen = capsChosen.isOnscreen();
boolean usePBuffer = capsChosen.isPBuffer();
+ boolean useFBO = capsChosen.isFBO();
// Utilizing FBConfig
//
@@ -270,13 +277,15 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen);
int[] count = { -1 };
List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
-
- // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice
- fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, useFBO);
+ // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice,
+ // skipped if xvisualID is given
+ if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
+ fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0);
+ }
if (fbcfgsL != null && fbcfgsL.limit()>0) {
for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
+ if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (1): ("+x11Screen+","+capsChosen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
}
@@ -309,13 +318,40 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
+ if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
}
}
}
}
+
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: got configs: "+availableCaps.size());
+ for(int i=0; i<availableCaps.size(); i++) {
+ System.err.println(i+": "+availableCaps.get(i));
+ }
+ }
+
+ if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
+ for(int i=0; i<availableCaps.size(); ) {
+ VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i);
+ if(vidh.getVisualID(VIDType.X11_XVISUAL) != xvisualID ) {
+ availableCaps.remove(i);
+ } else {
+ i++;
+ }
+ }
+ if(0==availableCaps.size()) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: post filter visualID "+toHexString(xvisualID )+" no config found, failed - return null");
+ }
+ return null;
+ } else if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: post filter visualID "+toHexString(xvisualID)+" got configs: "+availableCaps.size());
+ }
+ }
+
int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
if ( 0 > chosenIndex ) {
if (DEBUG) {
@@ -332,13 +368,13 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
if (chooser == null) {
chooser = new DefaultGLCapabilitiesChooser();
}
GLProfile glProfile = capsChosen.getGLProfile();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */, false);
List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
int recommendedIndex = -1;
@@ -350,14 +386,18 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice);
int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, false, isMultisampleAvailable, display, screen);
+ XVisualInfo recommendedVis = null;
// 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice
- XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0);
- if (DEBUG) {
- System.err.print("glXChooseVisual recommended ");
- if (recommendedVis == null) {
- System.err.println("null visual");
- } else {
- System.err.println("visual id " + toHexString(recommendedVis.getVisualid()));
+ // skipped if xvisualID is given
+ if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
+ recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0);
+ if (DEBUG) {
+ System.err.print("glXChooseVisual recommended ");
+ if (recommendedVis == null) {
+ System.err.println("null visual");
+ } else {
+ System.err.println("visual id " + toHexString(recommendedVis.getVisualid()));
+ }
}
}
@@ -383,6 +423,32 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
}
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: got configs: "+availableCaps.size());
+ for(int i=0; i<availableCaps.size(); i++) {
+ System.err.println(i+": "+availableCaps.get(i));
+ }
+ }
+
+ if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
+ for(int i=0; i<availableCaps.size(); ) {
+ VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i);
+ if(vidh.getVisualID(VIDType.X11_XVISUAL) != xvisualID ) {
+ availableCaps.remove(i);
+ } else {
+ i++;
+ }
+ }
+ if(0==availableCaps.size()) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: post filter visualID "+toHexString(xvisualID )+" no config found, failed - return null");
+ }
+ return null;
+ } else if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: post filter visualID "+toHexString(xvisualID)+" got configs: "+availableCaps.size());
+ }
+ }
+
int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
if ( 0 > chosenIndex ) {
if (DEBUG) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
index 9e22afa6d..363299321 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
@@ -51,10 +51,13 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
long glXWindow; // GLXWindow, a GLXDrawable representation
boolean useGLXWindow;
- protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component) {
- super(factory, component, false);
+ protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component, boolean realized) {
+ super(factory, component, realized);
glXWindow=0;
useGLXWindow=false;
+ if(realized) {
+ updateHandle();
+ }
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
index cdf81ebd3..e1fe2f27e 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
@@ -43,7 +43,7 @@ package jogamp.opengl.x11.glx;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -77,7 +77,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
if (ns.getSurfaceHandle() != 0) {
GLX.glXDestroyPbuffer(ns.getDisplayHandle(), ns.getSurfaceHandle());
}
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
private void createPbuffer() {
@@ -108,12 +108,14 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
// Create the p-buffer.
int niattribs = 0;
- int[] iattributes = new int[5];
+ int[] iattributes = new int[7];
iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH;
iattributes[niattribs++] = ns.getWidth();
iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT;
iattributes[niattribs++] = ns.getHeight();
+ iattributes[niattribs++] = GLX.GLX_LARGEST_PBUFFER; // exact
+ iattributes[niattribs++] = 0;
iattributes[niattribs++] = 0;
long pbuffer = GLX.glXCreatePbuffer(display, config.getFBConfig(), iattributes, 0);
@@ -123,15 +125,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
}
// Set up instance variables
- ((SurfaceChangeable)ns).setSurfaceHandle(pbuffer);
-
- // Determine the actual width and height we were able to create.
- int[] tmp = new int[1];
- GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_WIDTH, tmp, 0);
- int width = tmp[0];
- GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_HEIGHT, tmp, 0);
- int height = tmp[0];
- ((SurfaceChangeable)ns).surfaceSizeChanged(width, height);
+ ((MutableSurface)ns).setSurfaceHandle(pbuffer);
if (DEBUG) {
System.err.println("Created pbuffer " + this);
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
index 1e7b89828..04627724c 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
@@ -43,7 +43,7 @@ package jogamp.opengl.x11.glx;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
@@ -93,7 +93,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
pixmap = 0;
throw new GLException("glXCreateGLXPixmap failed");
}
- ((SurfaceChangeable)ns).setSurfaceHandle(drawable);
+ ((MutableSurface)ns).setSurfaceHandle(drawable);
if (DEBUG) {
System.err.println("Created pixmap " + toHexString(pixmap) +
", GLXPixmap " + toHexString(drawable) +
@@ -133,7 +133,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
X11Lib.XFreePixmap(display, pixmap);
drawable = 0;
pixmap = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
display = 0;
}
}
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m
index 776284cfc..b81b43e54 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m
@@ -32,7 +32,6 @@
int texWidth;
int texHeight;
GLuint textureID;
- struct timespec lastWaitTime;
#ifdef HAS_CADisplayLink
CADisplayLink* displayLink;
#else
@@ -41,6 +40,7 @@
int tc;
struct timespec t0;
@public
+ struct timespec lastWaitTime;
GLint swapInterval;
GLint swapIntervalCounter;
pthread_mutex_t renderLock;
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
index 8ac9f4700..f774f8f4a 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
@@ -503,7 +503,7 @@ NSView* getNSView(NSOpenGLContext* ctx) {
NSOpenGLContext* createContext(NSOpenGLContext* share,
NSView* view,
- Bool isBackingLayerView,
+ Bool allowIncompleteView,
NSOpenGLPixelFormat* fmt,
Bool opaque,
int* viewNotReady)
@@ -512,13 +512,13 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
getRendererInfo();
- DBG_PRINT("createContext.0: share %p, view %p, isBackingLayer %d, pixfmt %p, opaque %d\n",
- share, view, (int)isBackingLayerView, fmt, opaque);
+ DBG_PRINT("createContext.0: share %p, view %p, allowIncompleteView %d, pixfmt %p, opaque %d\n",
+ share, view, (int)allowIncompleteView, fmt, opaque);
- if (view != NULL) {
+ if (view != nil) {
Bool viewReady = true;
- if(!isBackingLayerView) {
+ if(!allowIncompleteView) {
if ([view lockFocusIfCanDraw] == NO) {
DBG_PRINT("createContext.1 [view lockFocusIfCanDraw] failed\n");
viewReady = false;
@@ -527,7 +527,7 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
if(viewReady) {
NSRect frame = [view frame];
if ((frame.size.width == 0) || (frame.size.height == 0)) {
- if(!isBackingLayerView) {
+ if(!allowIncompleteView) {
[view unlockFocus];
}
DBG_PRINT("createContext.2 view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height);
@@ -558,7 +558,7 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
[ctx setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity];
}
[ctx setView:view];
- if(!isBackingLayerView) {
+ if(!allowIncompleteView) {
[view unlockFocus];
}
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java
index 04f616daf..b7f6ba45d 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java
@@ -30,51 +30,49 @@ package com.jogamp.nativewindow;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.SurfaceChangeable;
+public class WrappedSurface extends ProxySurface {
+ protected long surfaceHandle;
-public class WrappedSurface extends ProxySurface implements SurfaceChangeable {
- protected long surfaceHandle;
-
- public WrappedSurface(AbstractGraphicsConfiguration cfg) {
- this(cfg, 0);
- }
-
- public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle) {
- super(cfg);
+ public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) {
+ super(cfg, initialWidth, initialHeight, upstream);
surfaceHandle=handle;
}
@Override
- protected final void invalidateImpl() {
+ protected void invalidateImpl() {
surfaceHandle = 0;
}
@Override
- final public long getSurfaceHandle() {
+ public final long getSurfaceHandle() {
return surfaceHandle;
}
@Override
- final public void setSurfaceHandle(long surfaceHandle) {
+ public final void setSurfaceHandle(long surfaceHandle) {
this.surfaceHandle=surfaceHandle;
}
-
+
@Override
- final protected int lockSurfaceImpl() {
- return LOCK_SUCCESS;
+ protected final int lockSurfaceImpl() {
+ return LOCK_SUCCESS;
}
@Override
- final protected void unlockSurfaceImpl() {
+ protected final void unlockSurfaceImpl() {
}
@Override
public String toString() {
+ final UpstreamSurfaceHook ush = getUpstreamSurfaceHook();
+ final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil";
+
return "WrappedSurface[config " + getPrivateGraphicsConfiguration()+
", displayHandle 0x" + Long.toHexString(getDisplayHandle()) +
", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle()) +
", size " + getWidth() + "x" + getHeight() +
- ", surfaceLock "+surfaceLock+"]";
+ ", surfaceLock "+surfaceLock+
+ ", upstreamSurfaceHook "+ush_s+"]";
}
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
index 61d5e5c0d..2a152ff35 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
@@ -95,8 +95,8 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration();
capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsRequested, gc);
}
- final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(awtDevice);
- final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, null, awtScreen);
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(awtDevice, capsChosen);
+ final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, null, awtScreen, VisualIDHolder.VID_UNDEFINED);
if(config instanceof AWTGraphicsConfiguration) {
return (AWTGraphicsConfiguration) config;
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index cffe495f7..d4b927cf1 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -81,6 +81,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
protected long drawable;
protected Rectangle bounds;
protected Insets insets;
+ private long offscreenSurfaceLayer;
private long drawable_old;
@@ -106,6 +107,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
invalidate();
this.component = windowObject;
this.isApplet = false;
+ this.offscreenSurfaceLayer = 0;
}
@Override
@@ -196,6 +198,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
System.err.println("JAWTWindow.attachSurfaceHandle(): 0x"+Long.toHexString(layerHandle) + ", bounds "+bounds);
}
attachSurfaceLayerImpl(layerHandle);
+ offscreenSurfaceLayer = layerHandle;
} finally {
unlockSurface();
}
@@ -206,25 +209,34 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
* {@inheritDoc}
*/
@Override
- public final void detachSurfaceLayer(final long layerHandle) throws NativeWindowException {
+ public final void detachSurfaceLayer() throws NativeWindowException {
if( !isOffscreenLayerSurfaceEnabled() ) {
throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface");
}
+ if( 0 == offscreenSurfaceLayer) {
+ throw new NativeWindowException("No offscreen layer attached: "+this);
+ }
int lockRes = lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
throw new NativeWindowException("Could not lock (offscreen layer): "+this);
}
try {
if(DEBUG) {
- System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(layerHandle));
+ System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(offscreenSurfaceLayer));
}
- detachSurfaceLayerImpl(layerHandle);
+ detachSurfaceLayerImpl(offscreenSurfaceLayer);
+ offscreenSurfaceLayer = 0;
} finally {
unlockSurface();
}
}
protected abstract void detachSurfaceLayerImpl(final long layerHandle);
+ @Override
+ public final boolean isSurfaceLayerAttached() {
+ return 0 != offscreenSurfaceLayer;
+ }
+
//
// SurfaceUpdateListener
//
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
index 4ee336176..389949e90 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
@@ -36,25 +36,84 @@ import javax.media.nativewindow.*;
/** Encapsulates a graphics device on EGL platforms.
*/
-
public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- boolean closeDisplay = false;
+ final long nativeDisplayID;
+ final EGLDisplayLifecycleCallback eglLifecycleCallback;
/**
+ * Hack to allow inject a EGL termination call.
+ * <p>
+ * FIXME: This shall be removed when relocated EGL to the nativewindow package,
+ * since then it can be utilized directly.
+ * </p>
+ */
+ public interface EGLDisplayLifecycleCallback {
+ /**
+ * Implementation should issue an <code>EGL.eglGetDisplay(nativeDisplayID)</code>
+ * inclusive <code>EGL.eglInitialize(eglDisplayHandle, ..)</code> call.
+ * @param eglDisplayHandle
+ */
+ public long eglGetAndInitDisplay(long nativeDisplayID);
+
+ /**
+ * Implementation should issue an <code>EGL.eglTerminate(eglDisplayHandle)</code> call.
+ * @param eglDisplayHandle
+ */
+ void eglTerminate(long eglDisplayHandle);
+ }
+
+ /**
* Note that this is not an open connection, ie no native display handle exist.
* This constructor exist to setup a default device connection/unit.<br>
*/
public EGLGraphicsDevice(String connection, int unitID) {
super(NativeWindowFactory.TYPE_EGL, connection, unitID);
+ this.nativeDisplayID = 0 ; // EGL.EGL_DEFAULT_DISPLAY
+ this.eglLifecycleCallback = null;
}
- /** Constructs a new EGLGraphicsDevice corresponding to the given EGL display handle. */
- public EGLGraphicsDevice(long eglDisplay, String connection, int unitID) {
+ public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLDisplayLifecycleCallback eglLifecycleCallback) {
super(NativeWindowFactory.TYPE_EGL, connection, unitID, eglDisplay);
+ this.nativeDisplayID = nativeDisplayID;
+ this.eglLifecycleCallback = eglLifecycleCallback;
}
+ public long getNativeDisplayID() { return nativeDisplayID; }
+
+ @Override
public Object clone() {
return super.clone();
}
+
+ @Override
+ public boolean open() {
+ if(null != eglLifecycleCallback && 0 == handle) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.open(): "+this);
+ }
+ handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID);
+ if(0 == handle) {
+ throw new NativeWindowException("EGLGraphicsDevice.open() failed: "+this);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean close() {
+ if(null != eglLifecycleCallback && 0 != handle) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.close(): "+this);
+ }
+ eglLifecycleCallback.eglTerminate(handle);
+ }
+ return super.close();
+ }
+
+ @Override
+ public String toString() {
+ return "EGLGraphicsDevice[type EGL, connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", nativeDisplayID 0x"+Long.toHexString(nativeDisplayID)+"]";
+ }
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index 735d85fb1..ba07d97dc 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -34,17 +34,21 @@ import java.lang.reflect.Method;
import org.eclipse.swt.graphics.GCData;
import org.eclipse.swt.widgets.Control;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.VisualIDHolder;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
-import jogamp.common.awt.AWTEDTExecutor;
import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.nativewindow.x11.X11Lib;
public class SWTAccessor {
static final Field swt_control_handle;
@@ -204,8 +208,6 @@ public class SWTAccessor {
if( null != OS_gtk_class ) {
long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
long displayHandle = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, widgedHandle);
- // FIXME: May think about creating a private non-shared X11 Display handle, like we use to for AWT
- // to avoid locking problems !
return new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, false);
}
if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) {
@@ -216,6 +218,26 @@ public class SWTAccessor {
}
throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false));
}
+ public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) {
+ if( null != OS_gtk_class ) {
+ return new X11GraphicsScreen((X11GraphicsDevice)device, screen);
+ }
+ if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ||
+ NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) {
+ return new DefaultGraphicsScreen(device, screen);
+ }
+ throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false));
+ }
+ public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) {
+ if( null != OS_gtk_class ) {
+ return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
+ }
+ if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ||
+ NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) {
+ return VisualIDHolder.VID_UNDEFINED;
+ }
+ throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false));
+ }
public static long getWindowHandle(Control swtControl) {
long handle = getHandle(swtControl);
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index 308756b54..5e4d6f41a 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -33,7 +33,6 @@
package com.jogamp.nativewindow.x11;
-import jogamp.nativewindow.Debug;
import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
@@ -46,8 +45,7 @@ import javax.media.nativewindow.ToolkitLock;
*/
public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- public static final boolean DEBUG = Debug.debug("GraphicsDevice");
- final boolean closeDisplay;
+ final boolean handleOwner;
/** Constructs a new X11GraphicsDevice corresponding to the given connection and default
* {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.<br>
@@ -57,7 +55,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
*/
public X11GraphicsDevice(String connection, int unitID) {
super(NativeWindowFactory.TYPE_X11, connection, unitID);
- closeDisplay = false;
+ handleOwner = false;
}
/** Constructs a new X11GraphicsDevice corresponding to the given native display handle and default
@@ -70,7 +68,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
if(0==display) {
throw new NativeWindowException("null display");
}
- closeDisplay = owner;
+ handleOwner = owner;
}
/**
@@ -83,16 +81,39 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
if(0==display) {
throw new NativeWindowException("null display");
}
- closeDisplay = owner;
+ handleOwner = owner;
}
+ public int getDefaultVisualID() {
+ // It still could be an AWT hold handle ..
+ final long display = getHandle();
+ final int scrnIdx = X11Lib.DefaultScreen(display);
+ return X11Lib.DefaultVisualID(display, scrnIdx);
+ }
+
+ @Override
public Object clone() {
return super.clone();
}
+ @Override
+ public boolean open() {
+ if(handleOwner && 0 == handle) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName() + " - X11GraphicsDevice.open(): "+this);
+ }
+ handle = X11Util.openDisplay(connection);
+ if(0 == handle) {
+ throw new NativeWindowException("X11GraphicsDevice.open() failed: "+this);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public boolean close() {
- // FIXME: shall we respect the unitID ?
- if(closeDisplay && 0 != handle) {
+ if(handleOwner && 0 != handle) {
if(DEBUG) {
System.err.println(Thread.currentThread().getName() + " - X11GraphicsDevice.close(): "+this);
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
index 94013ec38..5f3c220ca 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
@@ -56,13 +56,11 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl
return new X11GraphicsScreen(new X11GraphicsDevice(display, AbstractGraphicsDevice.DEFAULT_UNIT, owner), screenIdx);
}
- public long getDefaultVisualID() {
+ public int getVisualID() {
// It still could be an AWT hold handle ..
- long display = getDevice().getHandle();
- int scrnIdx = X11Lib.DefaultScreen(display);
- return X11Lib.DefaultVisualID(display, scrnIdx);
+ return X11Lib.DefaultVisualID(getDevice().getHandle(), getIndex());
}
-
+
private static int fetchScreen(X11GraphicsDevice device, int screen) {
// It still could be an AWT hold handle ..
if(X11Util.XineramaIsEnabled(device.getHandle())) {
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
index 1dd01a274..756e4451b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
@@ -40,11 +40,15 @@
package javax.media.nativewindow;
+import jogamp.nativewindow.Debug;
+
/** A interface describing a graphics device in a
toolkit-independent manner.
*/
public interface AbstractGraphicsDevice extends Cloneable {
+ public static final boolean DEBUG = Debug.debug("GraphicsDevice");
+
/** Dummy connection value for a default connection where no native support for multiple devices is available */
public static String DEFAULT_CONNECTION = "decon";
@@ -109,16 +113,33 @@ public interface AbstractGraphicsDevice extends Cloneable {
*/
public void unlock();
+ /**
+ * Optionally [re]opening the device if handle is <code>null</code>.
+ * <p>
+ * The default implementation is a <code>NOP</code>.
+ * </p>
+ * <p>
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
+ * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
+ * issue the native open operation in case handle is <code>null</code>.
+ * </p>
+ *
+ * @return true if the handle was <code>null</code> and opening was successful, otherwise false.
+ */
+ public boolean open();
+
/**
- * Optionally closing the device.
+ * Optionally closing the device if handle is not <code>null</code>.
* <p>
* The default implementation is a <code>NOP</code>, just setting the handle to <code>null</code>.
* </p>
- * The specific implementing, ie {@link com.jogamp.nativewindow.x11.X11GraphicsDevice},
- * shall have a enable/disable like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice#setCloseDisplay(boolean, boolean)},<br>
- * which shall be invoked at creation time to determine ownership/role of freeing the resource.<br>
+ * <p>
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
+ * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
+ * issue the native close operation or skip it depending on the handles's ownership.
+ * </p>
*
- * @return true if the handle was not <code>null</code>, otherwise false.
+ * @return true if the handle was not <code>null</code> and closing was successful, otherwise false.
*/
public boolean close();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
index 196f23598..cb33aec5e 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
@@ -211,9 +211,18 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
return alphaBits;
}
- /** Sets the number of bits requested for the color buffer's alpha
- component. On some systems only the color depth, which is the
- sum of the red, green, and blue bits, is considered. */
+ /**
+ * Sets the number of bits requested for the color buffer's alpha
+ * component. On some systems only the color depth, which is the
+ * sum of the red, green, and blue bits, is considered.
+ * <p>
+ * <b>Note:</b> If alpha bits are <code>zero</code>, they are set to <code>one</code>
+ * by {@link #setBackgroundOpaque(boolean)} and it's OpenGL specialization <code>GLCapabilities::setSampleBuffers(boolean)</code>.<br/>
+ * Ensure to call this method after the above to ensure a <code>zero</code> value.</br>
+ * The above automated settings takes into account, that the user calls this method to <i>request</i> alpha bits,
+ * not to <i>reflect</i> a current state. Nevertheless if this is the case - call it at last.
+ * </p>
+ */
public void setAlphaBits(int alphaBits) {
this.alphaBits = alphaBits;
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 187959a67..583fde07f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -97,22 +97,27 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
}
}
+ @Override
public final String getType() {
return type;
}
+ @Override
public final String getConnection() {
return connection;
}
+ @Override
public final int getUnitID() {
return unitID;
}
+ @Override
public final String getUniqueID() {
return uniqueID;
}
+ @Override
public final long getHandle() {
return handle;
}
@@ -124,6 +129,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock)
*/
+ @Override
public final void lock() {
toolkitLock.lock();
}
@@ -135,10 +141,17 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock)
*/
+ @Override
public final void unlock() {
toolkitLock.unlock();
}
+
+ @Override
+ public boolean open() {
+ return false;
+ }
+ @Override
public boolean close() {
if(0 != handle) {
handle = 0;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
index 2610f2cfa..c3fdc6798 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
@@ -36,9 +36,15 @@ package javax.media.nativewindow;
import com.jogamp.common.util.ReflectionUtil;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.DefaultGraphicsConfigurationFactoryImpl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Provides the mechanism by which the graphics configuration for a
@@ -59,8 +65,43 @@ import java.util.Map;
public abstract class GraphicsConfigurationFactory {
protected static final boolean DEBUG;
- private static Map<Class<?>, GraphicsConfigurationFactory> registeredFactories;
- private static Class<?> abstractGraphicsDeviceClass;
+ private static class DeviceCapsType {
+ public final Class<?> deviceType;
+ public final Class<?> capsType;
+ private final int hash32;
+
+ public DeviceCapsType(Class<?> deviceType, Class<?> capsType) {
+ this.deviceType = deviceType;
+ this.capsType = capsType;
+
+ // 31 * x == (x << 5) - x
+ int hash32 = 31 + deviceType.hashCode();
+ hash32 = ((hash32 << 5) - hash32) + capsType.hashCode();
+ this.hash32 = hash32;
+ }
+
+ public final int hashCode() {
+ return hash32;
+ }
+
+ public final boolean equals(Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof DeviceCapsType) {
+ DeviceCapsType dct = (DeviceCapsType)obj;
+ return deviceType == dct.deviceType && capsType == dct.capsType;
+ }
+ return false;
+ }
+
+ @Override
+ public final String toString() {
+ return "DeviceCapsType["+deviceType.getName()+", "+capsType.getName()+"]";
+ }
+
+ }
+
+ private static final Map<DeviceCapsType, GraphicsConfigurationFactory> registeredFactories;
+ private static final DeviceCapsType defaultDeviceCapsType;
static boolean initialized = false;
static {
@@ -69,7 +110,8 @@ public abstract class GraphicsConfigurationFactory {
System.err.println(Thread.currentThread().getName()+" - Info: GraphicsConfigurationFactory.<init>");
// Thread.dumpStack();
}
- abstractGraphicsDeviceClass = javax.media.nativewindow.AbstractGraphicsDevice.class;
+ registeredFactories = Collections.synchronizedMap(new HashMap<DeviceCapsType, GraphicsConfigurationFactory>());
+ defaultDeviceCapsType = new DeviceCapsType(AbstractGraphicsDevice.class, CapabilitiesImmutable.class);
}
public static synchronized void initSingleton() {
@@ -79,14 +121,13 @@ public abstract class GraphicsConfigurationFactory {
if(DEBUG) {
System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.initSingleton()");
}
- registeredFactories = Collections.synchronizedMap(new HashMap<Class<?>, GraphicsConfigurationFactory>());
// Register the default no-op factory for arbitrary
// AbstractGraphicsDevice implementations, including
// AWTGraphicsDevice instances -- the OpenGL binding will take
// care of handling AWTGraphicsDevices on X11 platforms (as
// well as X11GraphicsDevices in non-AWT situations)
- registerFactory(abstractGraphicsDeviceClass, new DefaultGraphicsConfigurationFactoryImpl());
+ registerFactory(defaultDeviceCapsType.deviceType, defaultDeviceCapsType.capsType, new DefaultGraphicsConfigurationFactoryImpl());
if (NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) {
try {
@@ -112,7 +153,6 @@ public abstract class GraphicsConfigurationFactory {
System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.shutdown()");
}
registeredFactories.clear();
- registeredFactories = null;
}
}
@@ -133,74 +173,175 @@ public abstract class GraphicsConfigurationFactory {
protected GraphicsConfigurationFactory() {
}
- /** Returns the factory for use with the given type of
- AbstractGraphicsDevice. */
- public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device) {
+ /**
+ * Returns the graphics configuration factory for use with the
+ * given device and capability.
+ *
+ * @see #getFactory(Class, Class)
+ */
+ public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device, CapabilitiesImmutable caps) {
if (device == null) {
- return getFactory(AbstractGraphicsDevice.class);
+ throw new IllegalArgumentException("null device");
+ }
+ if (caps == null) {
+ throw new IllegalArgumentException("null caps");
}
- return getFactory(device.getClass());
+ return getFactory(device.getClass(), caps.getClass());
}
/**
* Returns the graphics configuration factory for use with the
- * given class, which must implement the {@link
- * AbstractGraphicsDevice} interface.
+ * given device and capability class.
+ * <p>
+ * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
+ * </p>
+ *
+ * <p>
+ * Pseudo code for finding a suitable factory is:
+ * <pre>
+ For-All devT := getTopDownDeviceTypes(deviceType)
+ For-All capsT := getTopDownCapabilitiesTypes(capabilitiesType)
+ f = factory.get(devT, capsT);
+ if(f) { return f; }
+ end
+ end
+ * </pre>
+ * </p>
*
- * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice
+ * @param deviceType the minimum capabilities class type accepted, must implement or extend {@link AbstractGraphicsDevice}
+ * @param capabilitiesType the minimum capabilities class type accepted, must implement or extend {@link CapabilitiesImmutable}
+ *
+ * @throws IllegalArgumentException if the deviceType does not implement {@link AbstractGraphicsDevice} or
+ * capabilitiesType does not implement {@link CapabilitiesImmutable}
*/
- public static GraphicsConfigurationFactory getFactory(Class<?> abstractGraphicsDeviceImplementor)
+ public static GraphicsConfigurationFactory getFactory(Class<?> deviceType, Class<?> capabilitiesType)
throws IllegalArgumentException, NativeWindowException
{
- if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) {
+ if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(deviceType))) {
throw new IllegalArgumentException("Given class must implement AbstractGraphicsDevice");
}
-
- GraphicsConfigurationFactory factory = null;
- Class<?> clazz = abstractGraphicsDeviceImplementor;
- while (clazz != null) {
- factory = registeredFactories.get(clazz);
- if (factory != null) {
- if(DEBUG) {
- System.err.println("GraphicsConfigurationFactory.getFactory() "+abstractGraphicsDeviceImplementor+" -> "+factory);
+ if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) {
+ throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable");
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ System.err.println("GraphicsConfigurationFactory.getFactory: "+deviceType.getName()+", "+capabilitiesType.getName());
+ dumpFactories();
+ }
+
+ final List<Class<?>> deviceTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.deviceType, deviceType, false);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() deviceTypes: " + deviceTypes);
+ }
+ final List<Class<?>> capabilitiesTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.capsType, capabilitiesType, true);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() capabilitiesTypes: " + capabilitiesTypes);
+ }
+ for(int j=0; j<deviceTypes.size(); j++) {
+ final Class<?> interfaceDevice = deviceTypes.get(j);
+ for(int i=0; i<capabilitiesTypes.size(); i++) {
+ Class<?> interfaceCaps = capabilitiesTypes.get(i);
+ final DeviceCapsType dct = new DeviceCapsType(interfaceDevice, interfaceCaps);
+ final GraphicsConfigurationFactory factory = registeredFactories.get(dct);
+ if (factory != null) {
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() found "+dct+" -> "+factory);
+ }
+ return factory;
}
- return factory;
}
- clazz = clazz.getSuperclass();
}
// Return the default
- factory = registeredFactories.get(abstractGraphicsDeviceClass);
+ final GraphicsConfigurationFactory factory = registeredFactories.get(defaultDeviceCapsType);
if(DEBUG) {
- System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+abstractGraphicsDeviceClass+" -> "+factory);
+ System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+defaultDeviceCapsType+" -> "+factory);
}
return factory;
}
+ private static ArrayList<Class<?>> getAllAssignableClassesFrom(Class<?> superClassOrInterface, Class<?> fromClass, boolean interfacesOnly) {
+ // Using a todo list avoiding a recursive loop!
+ final ArrayList<Class<?>> inspectClasses = new ArrayList<Class<?>>();
+ final ArrayList<Class<?>> resolvedInterfaces = new ArrayList<Class<?>>();
+ inspectClasses.add(fromClass);
+ for(int j=0; j<inspectClasses.size(); j++) {
+ final Class<?> clazz = inspectClasses.get(j);
+ getAllAssignableClassesFrom(superClassOrInterface, clazz, interfacesOnly, resolvedInterfaces, inspectClasses);
+ }
+ return resolvedInterfaces;
+ }
+ private static void getAllAssignableClassesFrom(Class<?> superClassOrInterface, Class<?> fromClass, boolean interfacesOnly, List<Class<?>> resolvedInterfaces, List<Class<?>> inspectClasses) {
+ final ArrayList<Class<?>> types = new ArrayList<Class<?>>();
+ if( superClassOrInterface.isAssignableFrom(fromClass) && !resolvedInterfaces.contains(fromClass)) {
+ if( !interfacesOnly || fromClass.isInterface() ) {
+ types.add(fromClass);
+ }
+ }
+ types.addAll(Arrays.asList(fromClass.getInterfaces()));
+
+ for(int i=0; i<types.size(); i++) {
+ final Class<?> iface = types.get(i);
+ if( superClassOrInterface.isAssignableFrom(iface) && !resolvedInterfaces.contains(iface) ) {
+ resolvedInterfaces.add(iface);
+ if( !superClassOrInterface.equals(iface) && !inspectClasses.contains(iface) ) {
+ inspectClasses.add(iface); // safe add to todo list, avoiding a recursive nature
+ }
+ }
+ }
+ final Class<?> parentClass = fromClass.getSuperclass();
+ if( null != parentClass && superClassOrInterface.isAssignableFrom(parentClass) && !inspectClasses.contains(parentClass) ) {
+ inspectClasses.add(parentClass); // safe add to todo list, avoiding a recursive nature
+ }
+ }
+ private static void dumpFactories() {
+ Set<DeviceCapsType> dcts = registeredFactories.keySet();
+ int i=0;
+ for(Iterator<DeviceCapsType> iter = dcts.iterator(); iter.hasNext(); ) {
+ DeviceCapsType dct = iter.next();
+ System.err.println("Factory #"+i+": "+dct+" -> "+registeredFactories.get(dct));
+ i++;
+ }
+ }
- /** Registers a GraphicsConfigurationFactory handling graphics
- * device objects of the given class. This does not need to be
- * called by end users, only implementors of new
+ /**
+ * Registers a GraphicsConfigurationFactory handling
+ * the given graphics device and capability class.
+ * <p>
+ * This does not need to be called by end users, only implementors of new
* GraphicsConfigurationFactory subclasses.
- *
+ * </p>
+ *
+ * <p>
+ * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
+ * </p>
+ *
+ * <p>See {@link #getFactory(Class, Class)} for a description of the find algorithm.</p>
+ *
+ * @param deviceType the minimum capabilities class type accepted, must implement or extend interface {@link AbstractGraphicsDevice}
+ * @param capabilitiesType the minimum capabilities class type accepted, must extend interface {@link CapabilitiesImmutable}
* @return the previous registered factory, or null if none
* @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice
*/
- protected static GraphicsConfigurationFactory registerFactory(Class<?> abstractGraphicsDeviceImplementor, GraphicsConfigurationFactory factory)
+ protected static GraphicsConfigurationFactory registerFactory(Class<?> abstractGraphicsDeviceImplementor, Class<?> capabilitiesType, GraphicsConfigurationFactory factory)
throws IllegalArgumentException
{
- if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) {
- throw new IllegalArgumentException("Given class must implement AbstractGraphicsDevice");
+ if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(abstractGraphicsDeviceImplementor))) {
+ throw new IllegalArgumentException("Given device class must implement AbstractGraphicsDevice");
}
+ if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) {
+ throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable");
+ }
+ final DeviceCapsType dct = new DeviceCapsType(abstractGraphicsDeviceImplementor, capabilitiesType);
final GraphicsConfigurationFactory prevFactory;
if(null == factory) {
- prevFactory = registeredFactories.remove(abstractGraphicsDeviceImplementor);
+ prevFactory = registeredFactories.remove(dct);
if(DEBUG) {
- System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+abstractGraphicsDeviceImplementor+
+ System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+dct+
", deleting: "+prevFactory);
}
} else {
- prevFactory = registeredFactories.put(abstractGraphicsDeviceImplementor, factory);
+ prevFactory = registeredFactories.put(dct, factory);
if(DEBUG) {
- System.err.println("GraphicsConfigurationFactory.registerFactory() put "+abstractGraphicsDeviceImplementor+" -> "+factory+
+ System.err.println("GraphicsConfigurationFactory.registerFactory() put "+dct+" -> "+factory+
", overridding: "+prevFactory);
}
}
@@ -244,6 +385,7 @@ public abstract class GraphicsConfigurationFactory {
* @param capsRequested the original requested capabilities
* @param chooser the choosing implementation
* @param screen the referring Screen
+ * @param nativeVisualID if not {@link VisualIDHolder#VID_UNDEFINED} it reflects a pre-chosen visualID of the native platform's windowing system.
* @return the complete GraphicsConfiguration
*
* @throws IllegalArgumentException if the data type of the passed
@@ -258,7 +400,7 @@ public abstract class GraphicsConfigurationFactory {
public final AbstractGraphicsConfiguration
chooseGraphicsConfiguration(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
CapabilitiesChooser chooser,
- AbstractGraphicsScreen screen)
+ AbstractGraphicsScreen screen, int nativeVisualID)
throws IllegalArgumentException, NativeWindowException {
if(null==capsChosen) {
throw new NativeWindowException("Chosen Capabilities are null");
@@ -275,7 +417,7 @@ public abstract class GraphicsConfigurationFactory {
}
device.lock();
try {
- return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen);
+ return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen, nativeVisualID);
} finally {
device.unlock();
}
@@ -283,7 +425,7 @@ public abstract class GraphicsConfigurationFactory {
protected abstract AbstractGraphicsConfiguration
chooseGraphicsConfigurationImpl(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen screen)
+ CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID)
throws IllegalArgumentException, NativeWindowException;
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
new file mode 100644
index 000000000..ff53c8109
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow;
+
+/**
+ * Provides a {@link NativeSurface} with a mutable <code>surfaceHandle</code>
+ * via {@link #setSurfaceHandle(long)}.
+ *
+ * @see NativeSurface
+ */
+public interface MutableSurface extends NativeSurface {
+
+ /**
+ * Sets the surface handle which is created outside of this implementation.
+ */
+ public void setSurfaceHandle(long surfaceHandle);
+}
+
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index b85ad47f2..6faa9890c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -561,4 +561,21 @@ public abstract class NativeWindowFactory {
}
return null;
}
+
+ /**
+ * Returns true if the given visualID is valid for further processing, i.e. OpenGL usage,
+ * otherwise return false.
+ * <p>
+ * On certain platforms, i.e. X11, a valid visualID is required at window creation.
+ * Other platforms may determine it later on, e.g. OSX and Windows. </p>
+ * <p>
+ * If the visualID is {@link VisualIDHolder#VID_UNDEFINED} and the platform requires it
+ * at creation time (see above), it is not valid for further processing.
+ * </p>
+ */
+ public static boolean isNativeVisualIDValidForProcessing(int visualID) {
+ return NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(false) ||
+ VisualIDHolder.VID_UNDEFINED != visualID ;
+ }
+
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
index dd36509ba..f7dbc6c27 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
@@ -42,7 +42,12 @@ public interface OffscreenLayerSurface {
* Detaches a previously attached offscreen layer from this offscreen layer surface.
* @see #attachSurfaceLayer(long)
* @see #isOffscreenLayerSurfaceEnabled()
- * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
+ * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
+ * or no surface layer is attached.
*/
- public void detachSurfaceLayer(final long layerHandle) throws NativeWindowException;
+ public void detachSurfaceLayer() throws NativeWindowException;
+
+ /** Returns true if a surface layer is attached, otherwise false. */
+ public boolean isSurfaceLayerAttached();
+
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
index 1dabc3dcd..7fc9789c2 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
@@ -28,38 +28,108 @@
package javax.media.nativewindow;
-
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.SurfaceUpdatedHelper;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
-public abstract class ProxySurface implements NativeSurface {
+public abstract class ProxySurface implements NativeSurface, MutableSurface {
public static final boolean DEBUG = Debug.debug("ProxySurface");
+
+ /**
+ * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}.
+ * @see #setImplBitfield(int)
+ * @see #getImplBitfield()
+ */
+ public static final int OWN_DEVICE = 1 << 7;
+
+ /**
+ * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete.
+ * @see #setImplBitfield(int)
+ * @see #getImplBitfield()
+ */
+ public static final int INVISIBLE_WINDOW = 1 << 8;
- private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
- private AbstractGraphicsConfiguration config; // control access due to delegation
- protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */
+ public interface UpstreamSurfaceHook {
+ /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */
+ public void create(ProxySurface s);
+ /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */
+ public void destroy(ProxySurface s);
+
+ /** Returns the width of the upstream surface */
+ public int getWidth(ProxySurface s);
+ /** Returns the height of the upstream surface */
+ public int getHeight(ProxySurface s);
+ }
+
+ private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+ private final AbstractGraphicsConfiguration config; // control access due to delegation
+ private final UpstreamSurfaceHook upstream;
+ public final int initialWidth;
+ public final int initialHeight;
private long surfaceHandle_old;
+ protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
protected long displayHandle;
- protected int height;
protected int scrnIndex;
- protected int width;
+ protected int implBitfield;
- public ProxySurface(AbstractGraphicsConfiguration cfg) {
- invalidate();
- config = cfg;
- displayHandle=cfg.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
- surfaceHandle_old = 0;
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param initialWidth the initial width
+ * @param initialHeight the initial height
+ */
+ protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) {
+ if(null == cfg) {
+ throw new IllegalArgumentException("null config");
+ }
+ this.config = cfg;
+ this.upstream = upstream;
+ this.initialWidth = initialWidth;
+ this.initialHeight = initialHeight;
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.surfaceHandle_old = 0;
+ this.implBitfield = 0;
}
- void invalidate() {
- displayHandle = 0;
- invalidateImpl();
+ public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
+
+ /**
+ * If a valid {@link UpstreamSurfaceHook} instance is passed in the
+ * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor},
+ * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set.
+ */
+ public void createNotify() {
+ if(null != upstream) {
+ upstream.create(this);
+ }
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.surfaceHandle_old = 0;
}
- protected abstract void invalidateImpl();
-
+
+ /**
+ * If a valid {@link UpstreamSurfaceHook} instance is passed in the
+ * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor},
+ * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared.
+ */
+ public void destroyNotify() {
+ if(null != upstream) {
+ upstream.destroy(this);
+ invalidateImpl();
+ }
+ this.displayHandle = 0;
+ this.surfaceHandle_old = 0;
+ }
+
+ /**
+ * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed.
+ * @see #destroyNotify()
+ */
+ protected void invalidateImpl() {
+ throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
+ }
+
@Override
public final long getDisplayHandle() {
return displayHandle;
@@ -83,18 +153,22 @@ public abstract class ProxySurface implements NativeSurface {
public abstract long getSurfaceHandle();
@Override
+ public abstract void setSurfaceHandle(long surfaceHandle);
+
+ @Override
public final int getWidth() {
- return width;
+ if(null != upstream) {
+ return upstream.getWidth(this);
+ }
+ return initialWidth;
}
@Override
public final int getHeight() {
- return height;
- }
-
- public void surfaceSizeChanged(int width, int height) {
- this.width = width;
- this.height = height;
+ if(null != upstream) {
+ return upstream.getHeight(this);
+ }
+ return initialHeight;
}
@Override
@@ -187,7 +261,10 @@ public abstract class ProxySurface implements NativeSurface {
public final Thread getSurfaceLockOwner() {
return surfaceLock.getOwner();
}
-
+
@Override
public abstract String toString();
+
+ public int getImplBitfield() { return implBitfield; }
+ public void setImplBitfield(int v) { implBitfield=v; }
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java
deleted file mode 100644
index 956e68e61..000000000
--- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package javax.media.nativewindow;
-
-public interface SurfaceChangeable {
-
- /** Sets the surface handle which is created outside of this implementation */
- public void setSurfaceHandle(long surfaceHandle);
-
- /**
- * The surface's size has been determined or changed.
- * Implementation shall update the stored surface size with the given ones.
- */
- public void surfaceSizeChanged(int width, int height);
-
-}
-
diff --git a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
index f34b740d4..52e9c8308 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
@@ -37,7 +37,7 @@ import javax.media.nativewindow.*;
public class DefaultGraphicsConfigurationFactoryImpl extends GraphicsConfigurationFactory {
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen) {
+ CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) {
return new DefaultGraphicsConfiguration(screen, capsChosen, capsRequested);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
index 4877d5c4f..4f68c6945 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
@@ -34,8 +34,8 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
- private Object surfaceUpdatedListenersLock = new Object();
- private ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>();
+ private final Object surfaceUpdatedListenersLock = new Object();
+ private final ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>();
//
// Management Utils
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index 42fd08df1..e81d61e0f 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -48,7 +48,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.Capabilities;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.util.Point;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
@@ -62,7 +62,7 @@ import jogamp.nativewindow.jawt.JAWT_DrawingSurfaceInfo;
import jogamp.nativewindow.jawt.macosx.JAWT_MacOSXDrawingSurfaceInfo;
import jogamp.nativewindow.macosx.OSXUtil;
-public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable {
+public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
public MacOSXJAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
super(comp, config);
if(DEBUG) {
@@ -103,24 +103,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable {
if(DEBUG) {
System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
}
- sscSet &= 0 != surfaceHandle; // reset ssc flag if NULL surfaceHandle, ie. back to JAWT
this.surfaceHandle = surfaceHandle;
}
- public void surfaceSizeChanged(int width, int height) {
- sscSet = true;
- sscWidth = width;
- sscHeight = height;
- }
-
- public int getWidth() {
- return sscSet ? sscWidth : super.getWidth();
- }
-
- public int getHeight() {
- return sscSet ? sscHeight: super.getHeight();
- }
-
protected JAWT fetchJAWTImpl() throws NativeWindowException {
// use offscreen if supported and [ applet or requested ]
return JAWTUtil.getJAWT(getShallUseOffscreenLayer() || isApplet());
@@ -280,8 +265,6 @@ public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable {
private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer
private long surfaceHandle = 0;
- private int sscWidth, sscHeight;
- private boolean sscSet = false;
// Workaround for instance of 4796548
private boolean firstLock = true;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index 4d472b01a..894084fce 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -28,6 +28,7 @@
package jogamp.nativewindow.macosx;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
import jogamp.nativewindow.Debug;
@@ -59,23 +60,52 @@ public class OSXUtil {
return false;
}
- public static Point GetLocationOnScreen(long windowOrView, int src_x, int src_y) {
- return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
+ public static boolean isNSView(long object) {
+ return isNSView0(object);
}
- public static long CreateNSView(int x, int y, int width, int height) {
- return CreateNSView0(x, y, width, height);
+ /**
+ * In case the <code>windowOrView</code> is top-level,
+ * you shall set <code>topLevel</code> to true where
+ * insets gets into account to compute the client position as follows:
+ * <pre>
+ if(topLevel) {
+ // top-level position -> client window position
+ final Insets insets = GetInsets(windowOrView);
+ los.setX(los.getX() + insets.getLeftWidth());
+ los.setY(los.getY() + insets.getTopHeight());
+ }
+ * </pre>
+ * @param windowOrView
+ * @param topLevel
+ * @param src_x
+ * @param src_y
+ * @return the client position
+ */
+ public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) {
+ final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
+ if(topLevel) {
+ // top-level position -> client window position
+ final Insets insets = GetInsets(windowOrView);
+ los.setX(los.getX() + insets.getLeftWidth());
+ los.setY(los.getY() + insets.getTopHeight());
+ }
+ return los;
}
- public static void DestroyNSView(long nsView) {
- DestroyNSView0(nsView);
+
+ public static Insets GetInsets(long windowOrView) {
+ return (Insets) GetInsets0(windowOrView);
}
-
+
public static long CreateNSWindow(int x, int y, int width, int height) {
return CreateNSWindow0(x, y, width, height);
}
public static void DestroyNSWindow(long nsWindow) {
DestroyNSWindow0(nsWindow);
}
+ public static long GetNSView(long nsWindow) {
+ return GetNSView0(nsWindow);
+ }
public static long CreateCALayer(int x, int y, int width, int height) {
return CreateCALayer0(x, y, width, height);
@@ -133,11 +163,12 @@ public class OSXUtil {
} */
private static native boolean initIDs0();
+ private static native boolean isNSView0(long object);
private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
- private static native long CreateNSView0(int x, int y, int width, int height);
- private static native void DestroyNSView0(long nsView);
+ private static native Object GetInsets0(long windowOrView);
private static native long CreateNSWindow0(int x, int y, int width, int height);
private static native void DestroyNSWindow0(long nsWindow);
+ private static native long GetNSView0(long nsWindow);
private static native long CreateCALayer0(int x, int y, int width, int height);
private static native void AddCASublayer0(long rootCALayer, long subCALayer);
private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
index c24f64b32..e368aa6a1 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
@@ -31,6 +31,7 @@ package jogamp.nativewindow.windows;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
/**
@@ -43,22 +44,49 @@ public class GDISurface extends ProxySurface {
protected long windowHandle;
protected long surfaceHandle;
- public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle) {
- super(cfg);
- if(0 == windowHandle) {
- throw new NativeWindowException("Error hwnd 0, werr: "+GDI.GetLastError());
- }
+ public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) {
+ super(cfg, initialWidth, initialHeight, upstream);
this.windowHandle=windowHandle;
+ this.surfaceHandle=0;
}
@Override
- protected final void invalidateImpl() {
- windowHandle=0;
- surfaceHandle=0;
+ protected void invalidateImpl() {
+ if(0 != surfaceHandle) {
+ throw new NativeWindowException("didn't release surface Handle: "+this);
+ }
+ windowHandle = 0;
+ // surfaceHandle = 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived
+ * from it at {@link #lockSurface()}.
+ * </p>
+ */
+ @Override
+ public final void setSurfaceHandle(long surfaceHandle) {
+ this.windowHandle = surfaceHandle;
+ }
+
+ /**
+ * Sets the window handle (HWND).
+ */
+ public final void setWindowHandle(long windowHandle) {
+ this.windowHandle = windowHandle;
+ }
+
+ public final long getWindowHandle() {
+ return windowHandle;
}
@Override
final protected int lockSurfaceImpl() {
+ if (0 == windowHandle) {
+ throw new NativeWindowException("null window handle: "+this);
+ }
if (0 != surfaceHandle) {
throw new InternalError("surface not released");
}
@@ -89,12 +117,15 @@ public class GDISurface extends ProxySurface {
@Override
final public String toString() {
- return "GDISurface[config "+getPrivateGraphicsConfiguration()+
+ final UpstreamSurfaceHook ush = getUpstreamSurfaceHook();
+ final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil";
+ return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+
", displayHandle 0x"+Long.toHexString(getDisplayHandle())+
", windowHandle 0x"+Long.toHexString(windowHandle)+
", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+
", size "+getWidth()+"x"+getHeight()+
- ", surfaceLock "+surfaceLock+"]";
+ ", surfaceLock "+surfaceLock+
+ ", upstreamSurfaceHook "+ush_s+"]";
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
index 070f87216..b11dd1df1 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
@@ -39,33 +39,39 @@ import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
import com.jogamp.nativewindow.x11.X11GraphicsConfiguration;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactory {
public static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, new X11GraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class, new X11GraphicsConfigurationFactory());
}
private X11GraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen)
+ CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID)
throws IllegalArgumentException, NativeWindowException {
if(!(screen instanceof X11GraphicsScreen)) {
throw new NativeWindowException("Only valid X11GraphicsScreen are allowed");
}
- final X11Capabilities x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, capsChosen));
- AbstractGraphicsConfiguration res = new X11GraphicsConfiguration((X11GraphicsScreen)screen, x11CapsChosen, capsRequested, x11CapsChosen.getXVisualInfo());
+ final X11Capabilities x11CapsChosen;
+ if(VisualIDHolder.VID_UNDEFINED == nativeVisualID) {
+ x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, capsChosen));
+ } else {
+ x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, nativeVisualID));
+ }
+ final AbstractGraphicsConfiguration res = new X11GraphicsConfiguration((X11GraphicsScreen)screen, x11CapsChosen, capsRequested, x11CapsChosen.getXVisualInfo());
if(DEBUG) {
- System.err.println("X11GraphicsConfigurationFactory.chooseGraphicsConfigurationImpl("+screen+","+capsChosen+"): "+res);
+ System.err.println("X11GraphicsConfigurationFactory.chooseGraphicsConfigurationImpl(visualID 0x"+Integer.toHexString(nativeVisualID)+", "+screen+","+capsChosen+"): "+res);
}
return res;
}
- public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, long visualID)
+ public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, int visualID)
{
XVisualInfo xvi_temp = XVisualInfo.create();
xvi_temp.setVisualid(visualID);
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index fcc374751..7b46a1df0 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -255,7 +255,7 @@ public class X11Util {
*/
public static int shutdown(boolean realXCloseOpenAndPendingDisplays, boolean verbose) {
int num=0;
- if(DEBUG||verbose||pendingDisplayList.size() > 0) {
+ if(DEBUG || verbose || openDisplayMap.size() > 0 || pendingDisplayList.size() > 0) {
System.err.println("X11Util.Display: Shutdown (close open / pending Displays: "+realXCloseOpenAndPendingDisplays+
", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
", pending (not closed, marked uncloseable): "+pendingDisplayList.size()+")");
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
index b6bf63d44..1de03e8be 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
@@ -61,14 +61,14 @@ import jogamp.nativewindow.x11.X11Util;
public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFactory {
public static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new X11AWTGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, CapabilitiesImmutable.class, new X11AWTGraphicsConfigurationFactory());
}
private X11AWTGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects");
@@ -77,18 +77,18 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
absScreen = AWTGraphicsScreen.createDefault();
}
- return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, (AWTGraphicsScreen)absScreen);
+ return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, (AWTGraphicsScreen)absScreen, nativeVisualID);
}
public static AWTGraphicsConfiguration chooseGraphicsConfigurationStatic(
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AWTGraphicsScreen awtScreen) {
+ CapabilitiesChooser chooser, AWTGraphicsScreen awtScreen, int nativeVisualID) {
if(DEBUG) {
System.err.println("X11AWTGraphicsConfigurationFactory: got "+awtScreen);
}
final GraphicsDevice device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice();
-
+
final long displayHandleAWT = X11SunJDKReflection.graphicsDeviceGetDisplay(device);
final long displayHandle;
boolean owner = false;
@@ -121,8 +121,8 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
System.err.println("X11AWTGraphicsConfigurationFactory: made "+x11Screen);
}
- final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device);
- AbstractGraphicsConfiguration aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen);
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device, capsChosen);
+ AbstractGraphicsConfiguration aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen, nativeVisualID);
if (aConfig == null) {
throw new NativeWindowException("Unable to choose a GraphicsConfiguration (1): "+capsChosen+",\n\t"+chooser+"\n\t"+x11Screen);
}
@@ -160,7 +160,7 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
// try again using an AWT Colormodel compatible configuration
GraphicsConfiguration gc = device.getDefaultConfiguration();
capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsChosen, gc);
- aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen);
+ aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen, nativeVisualID);
if (aConfig == null) {
throw new NativeWindowException("Unable to choose a GraphicsConfiguration (2): "+capsChosen+",\n\t"+chooser+"\n\t"+x11Screen);
}
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index e010fc440..2c853a43d 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -52,12 +52,18 @@
static const char * const ClazzNameRunnable = "java/lang/Runnable";
static jmethodID runnableRunID = NULL;
-static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
static const char * const ClazzAnyCstrName = "<init>";
+
+static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
static const char * const ClazzNamePointCstrSignature = "(II)V";
static jclass pointClz = NULL;
static jmethodID pointCstr = NULL;
+static const char * const ClazzNameInsets = "javax/media/nativewindow/util/Insets";
+static const char * const ClazzNameInsetsCstrSignature = "(IIII)V";
+static jclass insetsClz = NULL;
+static jmethodID insetsCstr = NULL;
+
static int _initialized=0;
JNIEXPORT jboolean JNICALL
@@ -79,6 +85,21 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
+ c = (*env)->FindClass(env, ClazzNameInsets);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameInsets);
+ }
+ insetsClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==insetsClz) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNameInsets);
+ }
+ insetsCstr = (*env)->GetMethodID(env, insetsClz, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
+ if(NULL==insetsCstr) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s",
+ ClazzNameInsets, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
+ }
+
c = (*env)->FindClass(env, ClazzNameRunnable);
if(NULL==c) {
NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameRunnable);
@@ -92,6 +113,12 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
return JNI_TRUE;
}
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ return [nsObj isMemberOfClass:[NSView class]];
+}
+
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: getLocationOnScreen0
@@ -150,33 +177,45 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: CreateNSView0
- * Signature: (IIIIZ)J
+ * Method: getInsets0
+ * Signature: (J)Ljavax/media/nativewindow/util/Insets;
*/
-JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSView0
- (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height)
+JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
+ (JNIEnv *env, jclass unused, jlong winOrView)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSRect rect = NSMakeRect(x, y, width, height);
- NSView * view = [[NSView alloc] initWithFrame: rect] ;
- [view setCanDrawConcurrently: YES];
- [pool release];
- return (jlong) (intptr_t) view;
-}
+ NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
+ NSWindow* win = NULL;
+ NSView* view = NULL;
+ jint il,ir,it,ib;
+
+ if( [nsObj isKindOfClass:[NSWindow class]] ) {
+ win = (NSWindow*) nsObj;
+ view = [win contentView];
+ } else if( nsObj != NULL && [nsObj isKindOfClass:[NSView class]] ) {
+ view = (NSView*) nsObj;
+ win = [view window];
+ } else {
+ NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj);
+ }
+
+ NSRect frameRect = [win frame];
+ NSRect contentRect = [win contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ il = (jint)l; // l
+ ir = (jint)(frameRect.size.width - (contentRect.size.width + l)); // r
+ it = (jint)(frameRect.size.height - contentRect.size.height); // t
+ ib = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+
+ jobject res = (*env)->NewObject(env, insetsClz, insetsCstr, il, ir, it, ib);
-/*
- * Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: DestroyNSView0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSView0
- (JNIEnv *env, jclass unused, jlong nsView)
-{
- NSView* view = (NSView*) (intptr_t) nsView;
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- [view release];
[pool release];
+
+ return res;
}
/*
@@ -197,6 +236,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0
defer: YES];
[myWindow setReleasedWhenClosed: YES]; // default
[myWindow setPreservesContentDuringLiveResize: YES];
+ // Remove animations
+NS_DURING
+ // Available >= 10.7 - Removes default animations
+ [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone];
+NS_HANDLER
+NS_ENDHANDLER
// invisible ..
[myWindow setOpaque: NO];
@@ -224,6 +269,27 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSWindow0
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetNSView0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0
+ (JNIEnv *env, jclass unused, jlong window)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+
+ DBG_PRINT( "contentView0 - window: %p (START)\n", win);
+
+ jlong res = (jlong) ((intptr_t) [win contentView]);
+
+ DBG_PRINT( "contentView0 - window: %p (END)\n", win);
+
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: CreateCALayer0
* Signature: (IIII)J
*/
@@ -233,7 +299,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
CALayer* layer = [[CALayer alloc] init];
- DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, x, y, width, height, (int)[layer retainCount]);
+ DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, (int)x, (int)y, (int)width, (int)height, (int)[layer retainCount]);
// avoid zero size
if(0 == width) { width = 32; }
if(0 == height) { height = 32; }
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 21771c9aa..fcba8580c 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -362,14 +362,40 @@ Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Lja
return jbyteCopy;
}
-JNIEXPORT jlong JNICALL
+JNIEXPORT jint JNICALL
+Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _unused, jlong display, jlong window) {
+ Display * dpy = (Display *)(intptr_t)display;
+ Window w = (Window) window;
+ XWindowAttributes xwa;
+ jlong r = 0; // undefinded
+
+ if(NULL==dpy) {
+ NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
+ return;
+ }
+
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 1);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa);
+ if(NULL != xwa.visual) {
+ r = (jint) XVisualIDFromVisual( xwa.visual );
+ } else {
+ r = 0;
+ }
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+
+ return r;
+}
+
+
+JNIEXPORT jint JNICALL
Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused, jlong display, jint screen) {
jlong r;
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 1, 0, 0);
- r = (jlong) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
+ r = (jint) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0);
return r;
}
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 7b6849a30..1e9a0e9eb 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -141,6 +141,23 @@ public abstract class Display {
*/
public abstract String getType();
+ /**
+ * Sets a new {@link EDTUtil} and returns the previous one.
+ * <p>
+ * If <code>newEDTUtil</code> is <code>null</code>,
+ * the device's default EDTUtil is created and used.
+ * </p>
+ * <p>
+ * If a previous one exists and it differs from the new one,
+ * it's being stopped, wait-until-idle and reset to allow restart.
+ * </p>
+ * <p>
+ * If <code>newEDTUtil</code> is not null and equals the previous one,
+ * <code>null</code> is returned and no change is being made.
+ * </p>
+ */
+ public abstract EDTUtil setEDTUtil(EDTUtil newEDTUtil);
+
public abstract EDTUtil getEDTUtil();
public abstract boolean isEDTRunning();
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index 71e86d520..e8537fec5 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -40,8 +40,20 @@ import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.WindowClosingProtocol;
/**
- * Specifying the public Window functionality for the
- * using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}.
+ * Specifying NEWT's Window functionality:
+ * <ul>
+ * <li>On- and offscreen windows</li>
+ * <li>Keyboard and multi-pointer input</li>
+ * <li>Native reparenting</li>
+ * <li>Toggable fullscreen and decoration mode</li>
+ * <li>Transparency</li>
+ * <li>... and more</li>
+ * </ul>
+ * <p>
+ * One use case is {@link com.jogamp.newt.opengl.GLWindow}, which delegates
+ * window operation to an instance of this interface while providing OpenGL
+ * functionality.
+ * </p>
*/
public interface Window extends NativeWindow, WindowClosingProtocol {
public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent");
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 9af4a02ae..6f0028a77 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -42,7 +42,9 @@ import java.security.PrivilegedAction;
import java.util.Set;
import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerOption;
+import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.swing.MenuSelectionManager;
@@ -261,17 +263,35 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
private final FocusPropertyChangeListener focusPropertyChangeListener = new FocusPropertyChangeListener();
private volatile KeyboardFocusManager keyboardFocusManager = null;
- /** sets a new NEWT child, provoking reparenting. */
- private NewtCanvasAWT setNEWTChild(Window child) {
- if(newtChild!=child) {
- newtChild = child;
- if(isDisplayable()) {
- // reparent right away, addNotify has been called already
- final java.awt.Container cont = AWTMisc.getContainer(this);
- reparentWindow( (null!=child) ? true : false, cont );
- }
+ /**
+ * Sets a new NEWT child, provoking reparenting.
+ * <p>
+ * A previously detached <code>newChild</code> will be released to top-level status
+ * and made invisible.
+ * </p>
+ * <p>
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
+ * </p>
+ * @return the previous attached newt child.
+ */
+ public Window setNEWTChild(Window newChild) {
+ final Window prevChild = newtChild;
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
+ }
+ final java.awt.Container cont = AWTMisc.getContainer(this);
+ // remove old one
+ if(null != newtChild) {
+ reparentWindow( false, cont );
+ newtChild = null;
}
- return this;
+ // add new one, reparent only if ready
+ newtChild = newChild;
+ if( isDisplayable() && null != newChild) {
+ reparentWindow( true, cont );
+ }
+ return prevChild;
}
/** @return the current NEWT child */
@@ -304,13 +324,13 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
awtKeyAdapter.removeFrom(this);
awtKeyAdapter = null;
}
- newtChild.setKeyboardFocusHandler(null);
if(null != keyboardFocusManager) {
keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
keyboardFocusManager = null;
}
if( null != newtChild ) {
+ newtChild.setKeyboardFocusHandler(null);
if(attach) {
if(null == jawtWindow.getGraphicsConfiguration()) {
throw new InternalError("XXX");
@@ -358,7 +378,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
// if ( isShowing() == true ) -> Container is already visible.
System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+
", displayable "+isDisplayable()+" -> "+cont);
- }
+ }
reparentWindow(true, cont);
}
@@ -368,7 +388,17 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
if(DEBUG) {
System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont);
}
+ final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(newtChild, true);
+ if(null != ols && ols.isSurfaceLayerAttached()) {
+ ols.detachSurfaceLayer();
+ }
reparentWindow(false, cont);
+
+ if(null != jawtWindow) {
+ NewtFactoryAWT.destroyNativeWindow(jawtWindow);
+ jawtWindow=null;
+ }
+
super.removeNotify();
}
@@ -376,14 +406,19 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
if(null==newtChild) {
return; // nop
}
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
newtChild.setFocusAction(null); // no AWT focus traversal ..
if(add) {
- jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
- jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
if(DEBUG) {
System.err.println("NewtCanvasAWT.reparentWindow: newtChild: "+newtChild);
}
+ if(null == jawtWindow) {
+ jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
+ jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
+ }
final int w;
final int h;
if(isPreferredSizeSet()) {
@@ -407,19 +442,17 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
newtChild.setVisible(true);
configureNewtChild(true);
newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
- newtChild.windowRepaint(0, 0, w, h);
// force this AWT Canvas to be focus-able,
// since this it is completely covered by the newtChild (z-order).
setFocusable(true);
} else {
- configureNewtChild(false);
+ configureNewtChild(false);
newtChild.setVisible(false);
newtChild.reparentWindow(null);
- if(null != jawtWindow) {
- NewtFactoryAWT.destroyNativeWindow(jawtWindow);
- jawtWindow=null;
- }
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
}
}
@@ -563,5 +596,12 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
}
}
}
+
+ static String newtWinHandleToHexString(Window w) {
+ return null != w ? toHexString(w.getWindowHandle()) : "nil";
+ }
+ static String toHexString(long l) {
+ return "0x"+Long.toHexString(l);
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
index 44fcea49c..4db661eeb 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
@@ -43,7 +43,7 @@ public class KeyEvent extends InputEvent
this.keyChar=keyChar;
}
- /** Only valid if delivered via {@link KeyListener#keyPressed(KeyEvent)} */
+ /** Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)} */
public char getKeyChar() {
return keyChar;
}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index f08fbc8fa..0fc1b4e89 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -53,6 +53,7 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import jogamp.newt.WindowImpl;
@@ -62,6 +63,7 @@ import jogamp.opengl.GLDrawableImpl;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
import com.jogamp.newt.Window;
@@ -87,13 +89,6 @@ import com.jogamp.opengl.JoglVersion;
* you can inject {@link javax.media.opengl.GLRunnable} objects
* via {@link #invoke(boolean, javax.media.opengl.GLRunnable)} to the OpenGL command stream.<br>
* </p>
- * <p>
- * NOTE: [MT-0] Methods utilizing [volatile] drawable/context are not synchronized.
- In case any of the methods are called outside of a locked state
- extra care should be added. Maybe we shall expose locking facilities to the user.
- However, since the user shall stick to the GLEventListener model while utilizing
- GLAutoDrawable implementations, she is safe due to the implicit locked state.
- * </p>
*/
public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Window, NEWTEventConsumer, FPSCounter {
private final WindowImpl window;
@@ -102,7 +97,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
* Constructor. Do not call this directly -- use {@link #create()} instead.
*/
protected GLWindow(Window window) {
- super(null, null);
+ super(null, null, false);
this.window = (WindowImpl) window;
this.window.setHandleDestroyNotify(false);
window.addWindowListener(new WindowAdapter() {
@@ -124,6 +119,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
this.window.setLifecycleHook(new GLLifecycleHook());
}
+ @Override
+ public final Object getUpstreamWidget() {
+ return window;
+ }
+
/**
* Creates a new GLWindow attaching a new Window referencing a
* new default Screen and default Display with the given GLCapabilities.
@@ -426,23 +426,23 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
@Override
public synchronized void destroyActionInLock() {
if(Window.DEBUG_IMPLEMENTATION) {
- String msg = "GLWindow.destroy() "+Thread.currentThread()+", start";
+ String msg = "GLWindow.destroy() "+WindowImpl.getThreadName()+", start";
System.err.println(msg);
//Exception e1 = new Exception(msg);
//e1.printStackTrace();
}
- defaultDestroyOp();
+ destroyImplInLock();
if(Window.DEBUG_IMPLEMENTATION) {
- System.err.println("GLWindow.destroy() "+Thread.currentThread()+", fin");
+ System.err.println("GLWindow.destroy() "+WindowImpl.getThreadName()+", fin");
}
}
@Override
public synchronized void resetCounter() {
if(Window.DEBUG_IMPLEMENTATION) {
- System.err.println("GLWindow.resetCounter() "+Thread.currentThread());
+ System.err.println("GLWindow.resetCounter() "+WindowImpl.getThreadName());
}
GLWindow.this.resetFPSCounter();
}
@@ -452,7 +452,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
long t0;
if(Window.DEBUG_IMPLEMENTATION) {
t0 = System.nanoTime();
- System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+Thread.currentThread()+", start");
+ System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", start");
} else {
t0 = 0;
}
@@ -479,7 +479,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
context.setContextCreationFlags(additionalCtxCreationFlags);
}
if(Window.DEBUG_IMPLEMENTATION) {
- System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+Thread.currentThread()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms");
+ System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms");
}
}
@@ -509,6 +509,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
private GLContext sharedContext = null;
+ @Override
+ protected final RecursiveLock getLock() {
+ return window.getLock();
+ }
+
/**
* Specifies an {@link javax.media.opengl.GLContext OpenGL context} to share with.<br>
* At native creation, {@link #setVisible(boolean) setVisible(true)},
@@ -531,19 +536,18 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
return;
}
- window.lockWindow(); // sync: context/drawable could have been recreated/destroyed while animating
+ final RecursiveLock lock = window.getLock();
+ lock.lock(); // sync: context/drawable could have been recreated/destroyed while animating
try {
- if( null == context && 0<getWidth()*getHeight() ) {
- // retry drawable and context creation
- setVisible(true);
- }
-
if( null != context ) {
// surface is locked/unlocked implicit by context's makeCurrent/release
helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
+ } else if( 0<getWidth()*getHeight() ) {
+ // retry drawable and context creation, will itself issue resize -> display
+ setVisible(true);
}
} finally {
- window.unlockWindow();
+ lock.unlock();
}
}
@@ -553,7 +557,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
private GLDrawableFactory factory;
@Override
- public GLDrawableFactory getFactory() {
+ public final GLDrawableFactory getFactory() {
return factory;
}
@@ -561,6 +565,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
public final void setRealized(boolean realized) {
}
+ @Override
+ public final void swapBuffers() throws GLException {
+ defaultSwapBuffers();
+ }
+
//----------------------------------------------------------------------
// NEWTEventConsumer
//
@@ -762,7 +771,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
System.err.println(GlueGenVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
final GLProfile glp = GLProfile.getDefault();
final GLCapabilitiesImmutable caps = new GLCapabilities( glp );
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
new file mode 100644
index 000000000..f45b864fa
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -0,0 +1,508 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+
+package com.jogamp.newt.swt;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.SurfaceUpdatedListener;
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.Point;
+
+import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.newt.Debug;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.util.EDTUtil;
+
+public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
+ private static final boolean DEBUG = Debug.debug("Window");
+ private static final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false);
+
+ /** SWT EDTUtil associated w/ parent's SWT Display */
+ private final EDTUtil swtEDTUtil;
+
+ private final AbstractGraphicsScreen screen;
+
+ private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE;
+ private volatile Rectangle clientArea;
+
+ private volatile SWTNativeWindow nativeWindow;
+ private volatile Window newtChild = null;
+
+ /**
+ * Creates an instance using {@link #NewtCanvasSWT(Composite, int, Window)}
+ * on the SWT thread.
+ *
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ *
+ * @param parent the SWT composite
+ * @param style additional styles to SWT#NO_BACKGROUND
+ * @param child optional preassigned {@link #Window}, maybe null
+ * @return a new instance
+ */
+ public static NewtCanvasSWT create(final Composite parent, final int style, final Window child) {
+ final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null };
+ parent.getDisplay().syncExec( new Runnable() {
+ public void run() {
+ res[0] = new NewtCanvasSWT( parent, style, child);
+ }
+ });
+ return res[0];
+ }
+
+ /**
+ * Instantiates a NewtCanvas with a NEWT child.
+ *
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ *
+ * @param parent the SWT composite
+ * @param style additional styles to SWT#NO_BACKGROUND
+ * @param child optional preassigned {@link #Window}, maybe null
+ */
+ public NewtCanvasSWT(final Composite parent, final int style, Window child) {
+ super(parent, style | SWT.NO_BACKGROUND);
+
+ swtEDTUtil = new SWTEDTUtil(parent.getDisplay());
+
+ SWTAccessor.setRealized(this, true);
+
+ clientArea = getClientArea();
+
+ final AbstractGraphicsDevice device = SWTAccessor.getDevice(this);
+ screen = SWTAccessor.getScreen(device, 0);
+ nativeWindow = null;
+
+ if(null != child) {
+ setNEWTChild(child);
+ }
+
+ /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
+ /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(final PaintEvent arg0) {
+ if( null != nativeWindow || validateNative() ) {
+ if( null !=newtChild ) {
+ newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
+ }
+ }
+ }
+ });
+
+ addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(final ControlEvent arg0) {
+ updateSizeCheck();
+ }
+ });
+ }
+
+ /** assumes nativeWindow == null ! */
+ protected final boolean validateNative() {
+ if( isDisposed() ) {
+ return false;
+ }
+ updateSizeCheck();
+ final Rectangle nClientArea = clientArea;
+ if(0 == nClientArea.width * nClientArea.height) {
+ return false;
+ }
+
+ /* Native handle for the control, used to associate with GLContext */
+ final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+ final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle);
+ final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID);
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid);
+ }
+ if( visualIDValid ) {
+ /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
+ * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
+ final CapabilitiesImmutable caps = new Capabilities();
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps);
+ final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID );
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config);
+ // Thread.dumpStack();
+ }
+ if (null == config) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+
+ nativeWindow = new SWTNativeWindow(config, nativeWindowHandle);
+ reparentWindow( true );
+ }
+
+ return null != nativeWindow;
+ }
+
+ protected final void updateSizeCheck() {
+ final Rectangle oClientArea = clientArea;
+ final Rectangle nClientArea = getClientArea();
+ if ( nClientArea != null &&
+ ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
+ ) {
+ clientArea = nClientArea; // write back new value
+ if( null != newtChild ) {
+ newtChild.setSize(clientArea.width, clientArea.height);
+ }
+ }
+ }
+
+ @Override
+ public void update() {
+ // don't paint background etc .. nop avoids flickering
+ }
+
+ /**
+ * Destroys this resource:
+ * <ul>
+ * <li> Make the NEWT Child invisible </li>
+ * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
+ * <li> Issues <code>destroy()</code> on the NEWT Child</li>
+ * <li> Remove reference to the NEWT Child</li>
+ * </ul>
+ * @see Window#destroy()
+ */
+ @Override
+ public void dispose() {
+ if( null != newtChild ) {
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.dispose.0: EDTUtil cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+ ",\n\t"+newtChild);
+ }
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null);
+ newtChild.destroy();
+ newtChild = null;
+ }
+ nativeWindow = null;
+ super.dispose();
+ }
+
+ /** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */
+ public NativeWindow getNativeWindow() { return nativeWindow; }
+
+ public WindowClosingMode getDefaultCloseOperation() {
+ return newtChildCloseOp; // FIXME
+ }
+
+ public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ return newtChildCloseOp = op; // FIXME
+ }
+
+
+ boolean isParent() {
+ return null!=newtChild ;
+ }
+
+ boolean isFullscreen() {
+ return null != newtChild && newtChild.isFullscreen();
+ }
+
+ /**
+ * Sets a new NEWT child, provoking reparenting.
+ * <p>
+ * A previously detached <code>newChild</code> will be released to top-level status
+ * and made invisible.
+ * </p>
+ * <p>
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
+ * </p>
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ * @return the previous attached newt child.
+ */
+ public Window setNEWTChild(final Window newChild) {
+ final Window prevChild = newtChild;
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
+ }
+ // remove old one
+ if(null != newtChild) {
+ reparentWindow( false );
+ newtChild = null;
+ }
+ // add new one, reparent only if ready
+ newtChild = newChild;
+ if(null != nativeWindow && null != newChild) {
+ reparentWindow( true );
+ }
+ return prevChild;
+ }
+
+ /** @return the current NEWT child */
+ public Window getNEWTChild() {
+ return newtChild;
+ }
+
+ @Override
+ public boolean setParent(Composite parent) {
+ return super.setParent(parent);
+ }
+
+ /* package */ void configureNewtChild(boolean attach) {
+
+ if( null != newtChild ) {
+ newtChild.setKeyboardFocusHandler(null);
+ if(attach) {
+ newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ } else {
+ newtChild.setFocusAction(null);
+ newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ }
+ }
+ }
+
+ void reparentWindow(boolean add) {
+ if( null == newtChild ) {
+ return; // nop
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+
+ newtChild.setFocusAction(null); // no AWT focus traversal ..
+ if(add) {
+ updateSizeCheck();
+ final int w = clientArea.width;
+ final int h = clientArea.height;
+
+ newtChild.getScreen().getDisplay().setEDTUtil(swtEDTUtil);
+
+ newtChild.setSize(w, h);
+ newtChild.reparentWindow(nativeWindow);
+ newtChild.setVisible(true);
+ configureNewtChild(true);
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+
+ // force this SWT Canvas to be focus-able,
+ // since this it is completely covered by the newtChild (z-order).
+ setEnabled(true);
+ } else {
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null);
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+ }
+
+ private final void requestFocusNEWTChild() {
+ if( null != newtChild ) {
+ newtChild.setFocusAction(null);
+ newtChild.requestFocus();
+ }
+ }
+
+ @Override
+ public boolean forceFocus() {
+ final boolean res = NewtCanvasSWT.super.forceFocus();
+ requestFocusNEWTChild();
+ return res;
+ }
+
+ private class SWTNativeWindow implements NativeWindow {
+ private final AbstractGraphicsConfiguration config;
+ private final long nativeWindowHandle;
+ private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX
+
+ public SWTNativeWindow(AbstractGraphicsConfiguration config, long nativeWindowHandle) {
+ this.config = config;
+ this.nativeWindowHandle = nativeWindowHandle;
+ if(isOSX) {
+ this.insets = OSXUtil.GetInsets(nativeWindowHandle);
+ } else {
+ this.insets = new Insets(0, 0, 0, 0);
+ }
+ }
+
+ @Override
+ public int lockSurface() throws NativeWindowException, RuntimeException {
+ return NativeSurface.LOCK_SUCCESS;
+ }
+
+ @Override
+ public void unlockSurface() { }
+
+ @Override
+ public boolean isSurfaceLockedByOtherThread() {
+ return false;
+ }
+
+ @Override
+ public Thread getSurfaceLockOwner() {
+ return null;
+ }
+
+ @Override
+ public boolean surfaceSwap() {
+ return false;
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { }
+
+ @Override
+ public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ }
+
+ @Override
+ public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { }
+
+ @Override
+ public long getSurfaceHandle() {
+ return 0;
+ }
+
+ @Override
+ public int getWidth() {
+ return clientArea.width;
+ }
+
+ @Override
+ public int getHeight() {
+ return clientArea.height;
+ }
+
+ @Override
+ public AbstractGraphicsConfiguration getGraphicsConfiguration() {
+ return config;
+ }
+
+ @Override
+ public long getDisplayHandle() {
+ return config.getScreen().getDevice().getHandle();
+ }
+
+ @Override
+ public int getScreenIndex() {
+ return config.getScreen().getIndex();
+ }
+
+ @Override
+ public void surfaceUpdated(Object updater, NativeSurface ns, long when) { }
+
+ @Override
+ public void destroy() { }
+
+ @Override
+ public NativeWindow getParent() {
+ return null;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ return nativeWindowHandle;
+ }
+
+ @Override
+ public InsetsImmutable getInsets() {
+ return insets;
+ }
+
+ @Override
+ public int getX() {
+ return 0;
+ }
+
+ @Override
+ public int getY() {
+ return 0;
+ }
+
+ @Override
+ public Point getLocationOnScreen(Point point) {
+ if( isOSX ) {
+ final Point los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0);
+ // top-level position -> client window position
+ los.setX(los.getX() + insets.getLeftWidth());
+ los.setY(los.getY() + insets.getTopHeight());
+ if(null!=point) {
+ return point.translate(los);
+ } else {
+ return los;
+ }
+ } else {
+ // client position on 'normal' windowing systems is 0/0
+ if(null == point) {
+ point = new Point(0, 0);
+ }
+ return point;
+ }
+ }
+
+ @Override
+ public boolean hasFocus() {
+ return isFocusControl();
+ }
+ };
+
+ static String newtWinHandleToHexString(Window w) {
+ return null != w ? toHexString(w.getWindowHandle()) : "nil";
+ }
+ static String toHexString(long l) {
+ return "0x"+Long.toHexString(l);
+ }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
new file mode 100644
index 000000000..3538caad2
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.newt.swt;
+
+import org.eclipse.swt.widgets.Display;
+
+import com.jogamp.newt.util.EDTUtil;
+
+/**
+ * Simple {@link EDTUtil} implementation utilizing the SWT UI thread
+ * of the given {@link Display}.
+ */
+public class SWTEDTUtil implements EDTUtil {
+ private final Display swtDisplay;
+
+ public SWTEDTUtil(Display swtDisplay) {
+ this.swtDisplay = swtDisplay;
+ }
+
+ public final Display getDisplay() {
+ return swtDisplay;
+ }
+
+ @Override
+ public long getPollPeriod() {
+ return 0;
+ }
+
+ @Override
+ public void setPollPeriod(long ms) {
+ }
+
+ @Override
+ public void reset() {
+ }
+
+ @Override
+ public void start() {
+ }
+
+ @Override
+ public boolean isCurrentThreadEDT() {
+ return swtDisplay.getThread() == Thread.currentThread();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return true;
+ }
+
+ @Override
+ public void invokeStop(Runnable finalTask) {
+ swtDisplay.syncExec(finalTask);
+ }
+
+ @Override
+ public void invoke(boolean wait, Runnable task) {
+ if(wait) {
+ swtDisplay.syncExec(task);
+ } else {
+ swtDisplay.asyncExec(task);
+ }
+ }
+
+ @Override
+ public void waitUntilIdle() {
+ // all sync ..
+ }
+
+ @Override
+ public void waitUntilStopped() {
+ // all sync ..
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
index fd757fba6..bdbe96070 100644
--- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
@@ -340,7 +340,7 @@ public class DefaultEDTUtil implements EDTUtil {
}
}
if(DEBUG) {
- System.err.println(getName()+": EDT run() EXIT "+ getName()+", "+error);
+ System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error);
}
if(null!=error) {
throw error;
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index a0bbcc264..b178bb5d3 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -101,7 +101,9 @@ public abstract class DisplayImpl extends Display {
display.hashCode = display.fqname.hashCode();
displayList.add(display);
}
- display.createEDTUtil();
+ if(null == display.edtUtil) {
+ display.setEDTUtil(null); // device's default if EDT is used, or null
+ }
if(DEBUG) {
System.err.println("Display.create() NEW: "+display+" "+getThreadName());
}
@@ -168,15 +170,45 @@ public abstract class DisplayImpl extends Display {
return true;
}
- protected void createEDTUtil() {
+ protected EDTUtil createEDTUtil() {
+ final EDTUtil def;
if(NewtFactory.useEDT()) {
- edtUtil = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable);
+ def = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable);
if(DEBUG) {
- System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName());
+ System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName());
}
+ } else {
+ def = null;
}
+ return def;
}
+ @Override
+ public EDTUtil setEDTUtil(EDTUtil newEDTUtil) {
+ if(null == newEDTUtil) {
+ newEDTUtil = createEDTUtil();
+ }
+ if( newEDTUtil == edtUtil ) {
+ if(DEBUG) {
+ System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!");
+ }
+ return null; // no change
+ }
+ final EDTUtil oldEDTUtil = edtUtil;
+ if(DEBUG) {
+ System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil);
+ }
+ if(null != oldEDTUtil) {
+ stopEDT( new Runnable() { public void run() {} } );
+ // ready for restart ..
+ oldEDTUtil.waitUntilStopped();
+ oldEDTUtil.reset();
+ }
+ edtUtil = newEDTUtil;
+ return oldEDTUtil;
+ }
+
+ @Override
public final EDTUtil getEDTUtil() {
return edtUtil;
}
@@ -355,24 +387,39 @@ public abstract class DisplayImpl extends Display {
DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable();
final void dispatchMessage(final NEWTEventTask eventTask) {
- NEWTEvent event = eventTask.get();
- if(null == event) {
- // Ooops ?
- System.err.println("Warning: event of eventTask is NULL");
- Thread.dumpStack();
- return;
- }
- Object source = event.getSource();
- if(source instanceof NEWTEventConsumer) {
- NEWTEventConsumer consumer = (NEWTEventConsumer) source ;
- if(!consumer.consumeEvent(event)) {
- // enqueue for later execution
- enqueueEvent(false, event);
+ final NEWTEvent event = eventTask.get();
+ try {
+ if(null == event) {
+ // Ooops ?
+ System.err.println("Warning: event of eventTask is NULL");
+ Thread.dumpStack();
+ return;
+ }
+ final Object source = event.getSource();
+ if(source instanceof NEWTEventConsumer) {
+ final NEWTEventConsumer consumer = (NEWTEventConsumer) source ;
+ if(!consumer.consumeEvent(event)) {
+ // enqueue for later execution
+ enqueueEvent(false, event);
+ }
+ } else {
+ throw new RuntimeException("Event source not NEWT: "+source.getClass().getName()+", "+source);
+ }
+ } catch (Throwable t) {
+ final RuntimeException re;
+ if(t instanceof RuntimeException) {
+ re = (RuntimeException) t;
+ } else {
+ re = new RuntimeException(t);
+ }
+ if( eventTask.isCallerWaiting() ) {
+ // propagate exception to caller
+ eventTask.setException(re);
+ } else {
+ throw re;
}
- } else {
- throw new RuntimeException("Event source not NEWT: "+source.getClass().getName()+", "+source);
}
- eventTask.notifyIssuer();
+ eventTask.notifyCaller();
}
public void dispatchMessages() {
@@ -423,8 +470,8 @@ public abstract class DisplayImpl extends Display {
return;
}
- Object lock = new Object();
- NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null);
+ final Object lock = new Object();
+ final NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null);
synchronized(lock) {
synchronized(eventsLock) {
events.add(eTask);
@@ -437,7 +484,10 @@ public abstract class DisplayImpl extends Display {
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
- }
+ if( null != eTask.getException() ) {
+ throw eTask.getException();
+ }
+ }
}
}
diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java
index 050e24b6c..ba98ca3af 100644
--- a/src/newt/classes/jogamp/newt/OffscreenWindow.java
+++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java
@@ -34,15 +34,25 @@
package jogamp.newt;
-import javax.media.nativewindow.*;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
-public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
+public class OffscreenWindow extends WindowImpl implements MutableSurface {
long surfaceHandle = 0;
-
+ ProxySurface.UpstreamSurfaceHook upstreamHook;
+ ProxySurface dummySurface;
+
public OffscreenWindow() {
+ upstreamHook = null;
+ dummySurface = null;
}
static long nextWindowHandle = 0x100; // start here - a marker
@@ -52,8 +62,19 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
throw new NativeWindowException("Capabilities is onscreen");
}
final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen();
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, aScreen);
+ /** Cannot use OpenGL here ..
+ if(capsRequested instanceof GLCapabilitiesImmutable) {
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) capsRequested;
+ if(caps.isFBO() && GLContext.isFBOAvailable(aScreen.getDevice(), caps.getGLProfile()) ) {
+ final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(caps);
+ final ProxySurface dummySurface = factory.createDummySurfaceImpl(aScreen.getDevice(), false, dummyCaps, null, 64, 64);
+ upstreamHook = dummySurface.getUpstreamSurfaceHook();
+ dummySurface.createNotify();
+ }
+ } */
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
@@ -68,13 +89,14 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
// nop
}
- public void surfaceSizeChanged(int width, int height) {
- sizeChanged(false, width, height, false);
- }
-
@Override
public synchronized void destroy() {
super.destroy();
+ if(null != dummySurface) {
+ dummySurface.destroyNotify();
+ dummySurface = null;
+ upstreamHook = null;
+ }
surfaceHandle = 0;
}
@@ -84,8 +106,12 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
@Override
public long getSurfaceHandle() {
+ if(null != dummySurface) {
+ return dummySurface.getSurfaceHandle();
+ // return upstreamHook.getWidth();
+ }
return surfaceHandle;
- }
+ }
protected void requestFocusImpl(boolean reparented) {
}
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index e49f91abd..606101ade 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -445,9 +445,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
protected abstract void closeNativeImpl();
/**
- * The native implementation must invoke {@link #focusChanged(boolean, boolean)}
- * to change the focus state, if <code>force == false</code>.
- * This may happen asynchronous within {@link #TIMEOUT_NATIVEWINDOW}.
+ * Async request which shall be performed within {@link #TIMEOUT_NATIVEWINDOW}.
+ * <p>
+ * If if <code>force == false</code> the native implementation
+ * may only request focus if not yet owner.</p>
+ * <p>
+ * {@link #focusChanged(boolean, boolean)} should be called
+ * to notify about the focus traversal.
+ * </p>
*
* @param force if true, bypass {@link #focusChanged(boolean, boolean)} and force focus request
*/
@@ -564,9 +569,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
@Override
public final int lockSurface() throws NativeWindowException, RuntimeException {
- windowLock.lock();
- surfaceLock.lock();
- int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
+ final RecursiveLock _wlock = windowLock;
+ final RecursiveLock _slock = surfaceLock;
+ _wlock.lock();
+ _slock.lock();
+ int res = _slock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
if ( LOCK_SURFACE_NOT_READY == res ) {
try {
@@ -583,8 +590,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
} finally {
if (LOCK_SURFACE_NOT_READY >= res) {
- surfaceLock.unlock();
- windowLock.unlock();
+ _slock.unlock();
+ _wlock.unlock();
}
}
}
@@ -593,10 +600,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
@Override
public final void unlockSurface() {
- surfaceLock.validateLocked();
- windowLock.validateLocked();
+ final RecursiveLock _slock = surfaceLock;
+ final RecursiveLock _wlock = windowLock;
+ _slock.validateLocked();
+ _wlock.validateLocked();
- if (surfaceLock.getHoldCount() == 1) {
+ if (_slock.getHoldCount() == 1) {
final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
try {
unlockSurfaceImpl();
@@ -604,8 +613,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
adevice.unlock();
}
}
- surfaceLock.unlock();
- windowLock.unlock();
+ _slock.unlock();
+ _wlock.unlock();
}
@Override
@@ -618,21 +627,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return surfaceLock.getOwner();
}
- public final void lockWindow() {
- windowLock.lock();
- }
- public final void unlockWindow() {
- windowLock.unlock();
+ public final RecursiveLock getLock() {
+ return windowLock;
}
- public final boolean isWindowLockedByOtherThread() {
- return windowLock.isLockedByOtherThread();
- }
-
- public final Thread getWindowLockOwner() {
- return windowLock.getOwner();
- }
-
public long getSurfaceHandle() {
return windowHandle; // default: return window handle
}
@@ -670,11 +668,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
public Point getLocationOnScreen(Point storage) {
if(isNativeValid()) {
Point d;
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
d = getLocationOnScreenImpl(0, 0);
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
if(null!=d) {
if(null!=storage) {
@@ -717,7 +716,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
boolean nativeWindowCreated = false;
boolean madeVisible = false;
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(null!=lifecycleHook) {
lifecycleHook.resetCounter();
@@ -739,7 +739,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
madeVisible = nativeWindowCreated;
}
// always flag visible, allowing a retry ..
- WindowImpl.this.visible = true;
+ WindowImpl.this.visible = true;
} else if(WindowImpl.this.visible != visible) {
if(isNativeValid()) {
setVisibleImpl(visible, getX(), getY(), getWidth(), getHeight());
@@ -766,7 +766,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println("Window setVisible: END ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+WindowImpl.this.visible+", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible);
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
if( nativeWindowCreated || madeVisible ) {
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
@@ -801,7 +801,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
public final void run() {
boolean recreate = false;
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) {
recreate = isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
@@ -842,7 +843,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(recreate) {
screen.removeReference(); // bring back ref-count
}
- windowLock.unlock();
+ _lock.unlock();
}
}
}
@@ -863,7 +864,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(null!=lifecycleHook) {
lifecycleHook.destroyActionPreLock();
}
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window DestroyAction() "+getThreadName());
@@ -917,7 +919,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
hasFocus = false;
parentWindowHandle = 0;
- windowLock.unlock();
+ _lock.unlock();
}
if(animatorPaused) {
lifecycleHook.resumeRenderingAction();
@@ -1002,8 +1004,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
int width = getWidth();
int height = getHeight();
boolean wasVisible;
-
- windowLock.lock();
+
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(isNativeValid()) {
// force recreation if offscreen, since it may become onscreen
@@ -1220,7 +1223,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println("Window.reparentWindow: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height);
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
if(wasVisible) {
switch (operation) {
@@ -1245,7 +1248,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class ReparentActionRecreate implements Runnable {
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
visible = true;
if(DEBUG_IMPLEMENTATION) {
@@ -1253,7 +1257,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
setVisible(true); // native creation
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
}
}
@@ -1291,7 +1295,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(WindowImpl.this.undecorated != undecorated) {
// set current state
@@ -1311,7 +1316,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
@@ -1333,7 +1338,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(WindowImpl.this.alwaysOnTop != alwaysOnTop) {
// set current state
@@ -1353,7 +1359,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
@@ -1545,7 +1551,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
"\n, ParentWindow "+parentWindow+
"\n, ParentWindowHandle "+toHexString(parentWindowHandle)+" ("+(0!=getParentWindowHandle())+")"+
"\n, WindowHandle "+toHexString(getWindowHandle())+
- "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+isWindowLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+
+ "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+windowLock.isLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+
"\n, Pos "+getX()+"/"+getY()+" (auto "+autoPosition()+"), size "+getWidth()+"x"+getHeight()+
"\n, Visible "+isVisible()+", focus "+hasFocus()+
"\n, Undecorated "+undecorated+" ("+isUndecorated()+")"+
@@ -1675,7 +1681,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle));
@@ -1689,7 +1696,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
}
}
@@ -1718,7 +1725,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
public boolean fsOn() { return fullscreen; }
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
// set current state
WindowImpl.this.fullscreen = fullscreen;
@@ -1795,7 +1803,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
@@ -1805,8 +1813,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
public boolean setFullscreen(boolean fullscreen) {
synchronized(fullScreenAction) {
if( fullScreenAction.init(fullscreen) ) {
- if(fullScreenAction.fsOn() &&
- isOffscreenInstance(WindowImpl.this, parentWindow)) {
+ if(fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow)) {
// enable fullscreen on offscreen instance
if(null != parentWindow) {
nfs_parent = parentWindow;
@@ -1918,7 +1925,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// special repaint treatment
case WindowEvent.EVENT_WINDOW_REPAINT:
// queue repaint event in case window is locked, ie in operation
- if( null != getWindowLockOwner() ) {
+ if( null != windowLock.getOwner() ) {
// make sure only one repaint event is queued
if(!repaintQueued) {
repaintQueued=true;
@@ -1937,7 +1944,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// common treatment
case WindowEvent.EVENT_WINDOW_RESIZED:
// queue event in case window is locked, ie in operation
- if( null != getWindowLockOwner() ) {
+ if( null != windowLock.getOwner() ) {
final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
index ce8ed7c49..747e2368e 100644
--- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
+++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
@@ -34,6 +34,7 @@ import javax.media.nativewindow.NativeWindow;
import jogamp.newt.driver.DriverUpdatePosition;
+import com.jogamp.newt.Window;
import com.jogamp.newt.event.awt.AWTAdapter;
import com.jogamp.newt.event.awt.AWTWindowAdapter;
@@ -92,19 +93,20 @@ public class AWTParentWindowAdapter
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentResized: "+comp);
}
- getNewtWindow().runOnEDTIfAvail(false, new Runnable() {
+ final Window newtWindow = getNewtWindow();
+ newtWindow.runOnEDTIfAvail(false, new Runnable() {
public void run() {
int cw = comp.getWidth();
int ch = comp.getHeight();
if( 0 < cw * ch ) {
- if( getNewtWindow().getWidth() != cw || getNewtWindow().getHeight() != ch ) {
- getNewtWindow().setSize(cw, ch);
- if(comp.isVisible() != getNewtWindow().isVisible()) {
- getNewtWindow().setVisible(comp.isVisible());
+ if( newtWindow.getWidth() != cw || newtWindow.getHeight() != ch ) {
+ newtWindow.setSize(cw, ch);
+ if(comp.isVisible() != newtWindow.isVisible()) {
+ newtWindow.setVisible(comp.isVisible());
}
}
- } else if(getNewtWindow().isVisible()) {
- getNewtWindow().setVisible(false);
+ } else if(newtWindow.isVisible()) {
+ newtWindow.setVisible(false);
}
}});
}
@@ -113,8 +115,9 @@ public class AWTParentWindowAdapter
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentMoved: "+e);
}
- if(getNewtWindow().getDelegatedWindow() instanceof DriverUpdatePosition) {
- ((DriverUpdatePosition)getNewtWindow().getDelegatedWindow()).updatePosition();
+ final Window newtWindow = getNewtWindow();
+ if(newtWindow.getDelegatedWindow() instanceof DriverUpdatePosition) {
+ ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition();
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java b/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java
index 3f360f20f..0a43c9b8f 100644
--- a/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java
+++ b/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java
@@ -32,9 +32,6 @@ import jogamp.newt.*;
import jogamp.opengl.egl.*;
import javax.media.nativewindow.*;
-import javax.media.opengl.GLException;
-
-import com.jogamp.nativewindow.egl.*;
public class AndroidDisplay extends jogamp.newt.DisplayImpl {
static {
@@ -55,20 +52,11 @@ public class AndroidDisplay extends jogamp.newt.DisplayImpl {
protected void createNativeImpl() {
// EGL Device
- final long eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError()));
- }
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed eglDisplay 0x"+Long.toHexString(eglDisplay)+", error 0x"+Integer.toHexString(EGL.eglGetError()));
- }
- aDevice = new EGLGraphicsDevice(eglDisplay, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
}
protected void closeNativeImpl() {
- if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) {
- EGLDisplayUtil.eglTerminate(aDevice.getHandle());
- }
+ aDevice.close();
}
protected void dispatchMessagesNative() {
diff --git a/src/newt/classes/jogamp/newt/driver/android/MD.java b/src/newt/classes/jogamp/newt/driver/android/MD.java
index 403eae383..f2f30937b 100644
--- a/src/newt/classes/jogamp/newt/driver/android/MD.java
+++ b/src/newt/classes/jogamp/newt/driver/android/MD.java
@@ -43,7 +43,7 @@ public class MD {
.append(JoglVersion.getInstance()).append(Platform.NEWLINE)
.append(Platform.NEWLINE);
- JoglVersion.getDefaultOpenGLInfo(sb, true);
+ JoglVersion.getDefaultOpenGLInfo(null, sb, true);
return sb.toString();
}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
index 5a49dd57c..a7950048a 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
@@ -46,6 +46,7 @@ import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
@@ -53,6 +54,7 @@ import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
import com.jogamp.newt.Window;
+@SuppressWarnings("serial")
public class AWTCanvas extends Canvas {
private GraphicsDevice device;
private GraphicsConfiguration chosen;
@@ -252,9 +254,9 @@ public class AWTCanvas extends Canvas {
AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT):
AWTGraphicsScreen.createDefault();
AWTGraphicsConfiguration config = (AWTGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, capsChosen.getClass()).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, aScreen);
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
if (config == null) {
throw new NativeWindowException("Error: Couldn't fetch AWTGraphicsConfiguration");
}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java
index 166da5c1c..65f8b4715 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java
@@ -36,6 +36,7 @@ package jogamp.newt.driver.awt;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.util.EDTUtil;
import jogamp.newt.DisplayImpl;
@@ -54,13 +55,17 @@ public class AWTDisplay extends DisplayImpl {
protected void closeNativeImpl() { }
@Override
- protected void createEDTUtil() {
+ protected EDTUtil createEDTUtil() {
+ final EDTUtil def;
if(NewtFactory.useEDT()) {
- edtUtil = AWTEDTUtil.getSingleton();
+ def = AWTEDTUtil.getSingleton();
if(DEBUG) {
- System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName());
+ System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName());
}
+ } else {
+ def = null;
}
+ return def;
}
protected void dispatchMessagesNative() { /* nop */ }
diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Display.java b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Display.java
index f90c62ff4..e3f50b7e0 100644
--- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Display.java
+++ b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Display.java
@@ -61,11 +61,11 @@ public class Display extends jogamp.newt.DisplayImpl {
}
protected void createNativeImpl() {
- long handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight);
+ final long handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight);
if (handle == EGL.EGL_NO_DISPLAY) {
throw new NativeWindowException("BC EGL CreateDisplay failed");
}
- aDevice = new EGLGraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice = new EGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, null);
}
protected void closeNativeImpl() {
diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java
index ed1d0511a..223ad6484 100644
--- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java
+++ b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java
@@ -37,6 +37,7 @@ package jogamp.newt.driver.broadcom.egl;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -57,8 +58,8 @@ public class Window extends jogamp.newt.WindowImpl {
}
// query a good configuration, however chose the final one by the native queried egl-cfg-id
// after creation at {@link #windowCreated(int, int, int)}.
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen());
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java
index 09e0e3016..d5c75abd4 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java
@@ -54,8 +54,8 @@ public class Window extends jogamp.newt.WindowImpl {
final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen();
final AbstractGraphicsDevice aDevice = getScreen().getDisplay().getGraphicsDevice();
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, aScreen);
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice, capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDDisplay.java b/src/newt/classes/jogamp/newt/driver/kd/KDDisplay.java
index 73bbe0b5b..07b031841 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/KDDisplay.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/KDDisplay.java
@@ -42,8 +42,6 @@ import jogamp.newt.NEWTJNILibLoader;
import jogamp.opengl.egl.EGL;
import jogamp.opengl.egl.EGLDisplayUtil;
-import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
-
public class KDDisplay extends DisplayImpl {
static {
@@ -64,20 +62,11 @@ public class KDDisplay extends DisplayImpl {
protected void createNativeImpl() {
// FIXME: map name to EGL_*_DISPLAY
- long handle = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- if (handle == EGL.EGL_NO_DISPLAY) {
- throw new NativeWindowException("eglGetDisplay failed");
- }
- if (!EGLDisplayUtil.eglInitialize(handle, null, null)) {
- throw new NativeWindowException("eglInitialize failed");
- }
- aDevice = new EGLGraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
}
protected void closeNativeImpl() {
- if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) {
- EGLDisplayUtil.eglTerminate(aDevice.getHandle());
- }
+ aDevice.close();
}
protected void dispatchMessagesNative() {
diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java b/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java
index bb76d21ff..9f9d6948e 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java
@@ -37,6 +37,7 @@ package jogamp.newt.driver.kd;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
@@ -59,8 +60,8 @@ public class KDWindow extends WindowImpl {
if(0!=getParentWindowHandle()) {
throw new RuntimeException("Window parenting not supported (yet)");
}
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen());
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
index 942994c13..27d7a1679 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
@@ -38,7 +38,8 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
@@ -50,7 +51,7 @@ import jogamp.newt.driver.DriverUpdatePosition;
import com.jogamp.newt.event.KeyEvent;
-public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverClearFocus, DriverUpdatePosition {
+public class MacWindow extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition {
static {
MacDisplay.initSingleton();
@@ -61,8 +62,8 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl
@Override
protected void createNativeImpl() {
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen());
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
@@ -131,10 +132,6 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl
}
}
- public void surfaceSizeChanged(int width, int height) {
- sizeChanged(false, width, height, false);
- }
-
@Override
protected void setTitleImpl(final String title) {
setTitle0(getWindowHandle(), title);
@@ -153,7 +150,7 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl
System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance);
}
if(!isOffscreenInstance) {
- requestFocusParent0(getWindowHandle());
+ resignFocus0(getWindowHandle());
} else {
focusChanged(false, false);
}
@@ -363,7 +360,6 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl
if(recreate && 0==surfaceHandle) {
throw new NativeWindowException("Internal Error - recreate, window but no view");
}
- orderOut0(getWindowHandle());
close0(getWindowHandle());
setWindowHandle(0);
} else {
@@ -400,7 +396,7 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl
private native boolean lockSurface0(long window);
private native void unlockSurface0(long window);
private native void requestFocus0(long window, boolean force);
- private native void requestFocusParent0(long window);
+ private native void resignFocus0(long window);
/** in case of a child window, it actually only issues orderBack(..) */
private native void orderOut0(long window);
private native void orderFront0(long window);
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
index 5e636d982..6a8c81f3d 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
@@ -41,6 +41,7 @@ import jogamp.newt.WindowImpl;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
@@ -119,8 +120,8 @@ public class WindowsWindow extends WindowImpl {
protected void createNativeImpl() {
final WindowsScreen screen = (WindowsScreen) getScreen();
final WindowsDisplay display = (WindowsDisplay) screen.getDisplay();
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen());
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
@@ -150,8 +151,8 @@ public class WindowsWindow extends WindowImpl {
}
protected void closeNativeImpl() {
- if (hdc != 0) {
- if(windowHandleClose != 0) {
+ if(windowHandleClose != 0) {
+ if (hdc != 0) {
try {
GDI.ReleaseDC(windowHandleClose, hdc);
} catch (Throwable t) {
@@ -161,11 +162,8 @@ public class WindowsWindow extends WindowImpl {
}
}
}
- hdc = 0;
- hdc_old = 0;
- }
- if(windowHandleClose != 0) {
try {
+ GDI.SetParent(windowHandleClose, 0); // detach first, experience hang w/ SWT parent
GDI.DestroyWindow(windowHandleClose);
} catch (Throwable t) {
if(DEBUG_IMPLEMENTATION) {
@@ -176,6 +174,8 @@ public class WindowsWindow extends WindowImpl {
windowHandleClose = 0;
}
}
+ hdc = 0;
+ hdc_old = 0;
}
protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
index 9a5074c29..5501f5a3c 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
@@ -63,9 +63,9 @@ public class X11Window extends WindowImpl {
protected void createNativeImpl() {
final X11Screen screen = (X11Screen) getScreen();
final X11Display display = (X11Display) screen.getDisplay();
- final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice());
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested);
final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen());
+ capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
if(DEBUG_IMPLEMENTATION) {
System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+cfg);
}
diff --git a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
index fae6560b4..93d5e2fb9 100644
--- a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
+++ b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
@@ -35,17 +35,22 @@ import com.jogamp.newt.event.NEWTEvent;
* which notifies after sending the event for the <code>invokeAndWait()</code> semantics.
*/
public class NEWTEventTask {
- NEWTEvent event;
- Object notifyObject;
+ private NEWTEvent event;
+ private Object notifyObject;
+ private RuntimeException exception;
public NEWTEventTask(NEWTEvent event, Object notifyObject) {
this.event = event ;
this.notifyObject = notifyObject ;
+ this.exception = null;
}
- public NEWTEvent get() { return event; }
+ public final NEWTEvent get() { return event; }
+ public final void setException(RuntimeException e) { exception = e; }
+ public final RuntimeException getException() { return exception; }
+ public final boolean isCallerWaiting() { return null != notifyObject; }
- public void notifyIssuer() {
+ public void notifyCaller() {
if(null != notifyObject) {
synchronized (notifyObject) {
notifyObject.notifyAll();
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index 01cbd80ec..bbadc9dd0 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -599,6 +599,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0
}
DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]);
+ // Remove animations for child windows
+ if(NULL != parentWindow) {
+NS_DURING
+ // Available >= 10.7 - Removes default animations
+ [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone];
+NS_HANDLER
+NS_ENDHANDLER
+ }
+
#ifdef VERBOSE_ON
int dbgIdx = 1;
#endif
@@ -734,7 +743,7 @@ NS_ENDHANDLER
if(NULL!=pWin) {
[mWin detachFromParent: pWin];
}
- [mWin orderOut: mWin];
+ [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n",
mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin);
@@ -742,11 +751,6 @@ NS_ENDHANDLER
// Only release window, if release is not yet in process.
// E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked.
if(!destroyNotifySent) {
- // '[mWin close]' causes a crash at exit.
- // This probably happens b/c it sends events to the main loop
- // but our resources are gone ?!
- // However, issuing a simple release seems to work quite well.
- // [mWin release];
[mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
}
@@ -806,11 +810,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0
DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus);
[mWin makeFirstResponder: nil];
- [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES];
- [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderFrontRegardless];
- // [mWin makeKeyWindow];
+ [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
+ [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force);
@@ -819,26 +820,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0
/*
* Class: jogamp_newt_driver_macosx_MacWindow
- * Method: requestFocusParent0
+ * Method: resignFocus0
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_resignFocus0
(JNIEnv *env, jobject window, jlong w)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) w);
NSWindow* pWin = [mWin parentWindow];
-#ifdef VERBOSE_ON
BOOL hasFocus = [mWin isKeyWindow];
-#endif
- DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
- if(NULL != pWin) {
- [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [pWin makeKeyWindow];
+ DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
+ if( hasFocus ) {
+ if(NULL != pWin) {
+ // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO];
+ [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
+ } else {
+ [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO];
+ }
}
- DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin);
+ DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin);
[pool release];
}
@@ -856,9 +858,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0
DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
- [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [win orderFrontRegardless];
+ [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
@@ -880,13 +880,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0
DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin);
if(NULL == pWin) {
- [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderOut: mWin];
+ [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
} else {
- [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderBack: mWin];
+ [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO];
}
DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index f914467af..b58b99e38 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -972,7 +972,7 @@ static jint mods2JavaMods(NSUInteger mods)
NSView* nsview = [self contentView];
if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
+ return NO;
}
NewtView* view = (NewtView *) nsview;
@@ -981,14 +981,14 @@ static jint mods2JavaMods(NSUInteger mods)
DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject);
if (javaWindowObject == NULL) {
DBG_PRINT("windowWillClose: null javaWindowObject\n");
- return;
+ return NO;
}
int shallBeDetached = 0;
JavaVM *jvmHandle = [view getJVMHandle];
JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
if(NULL==env) {
DBG_PRINT("windowWillClose: null JNIEnv\n");
- return;
+ return NO;
}
[view setDestroyNotifySent: true]; // earmark assumption of being closed
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
index a09cc76ac..b22be0a93 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
@@ -194,7 +194,7 @@ public class TestTextRendererNEWT00 extends UITestCase {
pw.printf("%s-%03dx%03d-T%04d", objName, drawable.getWidth(), drawable.getHeight(), texSize[0]);
final String filename = dir + sw +".png";
- if(screenshot.readPixels(drawable.getGL(), drawable, false)) {
+ if(screenshot.readPixels(drawable.getGL(), false)) {
screenshot.write(new File(filename));
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
index a3182a30f..6378c1ee3 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
@@ -194,7 +194,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener {
pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize[0], objName);
final String filename = dir + tech + sw +".png";
- if(screenshot.readPixels(drawable.getGL(), drawable, false)) {
+ if(screenshot.readPixels(drawable.getGL(), false)) {
screenshot.write(new File(filename));
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
index d0093ad0c..15daf70cd 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
@@ -180,7 +180,7 @@ public abstract class UIListenerBase01 implements GLEventListener {
pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), 0, objName);
final String filename = dir + tech + sw +".png";
- if(screenshot.readPixels(drawable.getGL(), drawable, false)) {
+ if(screenshot.readPixels(drawable.getGL(), false)) {
screenshot.write(new File(filename));
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java
new file mode 100644
index 000000000..7977347a7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java
@@ -0,0 +1,272 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.GLFBODrawableImpl;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.OffscreenAutoDrawable;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+public class TestFBODrawableNEWT extends UITestCase {
+
+ static final int widthStep = 800/4;
+ static final int heightStep = 600/4;
+ volatile int szStep = 2;
+
+ @Test
+ public void testGL2ES2_Demo1Normal() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ testGLFBODrawableImpl(caps, new GearsES2(0));
+ }
+
+ @Test
+ public void testGL2ES2_Demo1MSAA4() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(4);
+ testGLFBODrawableImpl(caps, new GearsES2(0));
+ }
+
+ @Test
+ public void testGL2ES2_Demo2Normal() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ testGLFBODrawableImpl(caps, new MultisampleDemoES2(false));
+ }
+
+ @Test
+ public void testGL2ES2_Demo2MSAA4() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(4);
+ testGLFBODrawableImpl(caps, new MultisampleDemoES2(true));
+ }
+
+ @Test
+ public void testGL2ES2_FBODemoNormal() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0);
+ demo.setDoRotation(false);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ testGLFBODrawableImpl(caps, demo);
+ }
+
+ @Test
+ public void testGL2ES2_FBODemoMSAA4() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0);
+ demo.setDoRotation(false);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(4);
+ testGLFBODrawableImpl(caps, demo);
+ }
+
+ @Test
+ public void testEGLES2_Demo0Normal() throws InterruptedException {
+ if( GLProfile.isAvailable(GLProfile.GLES2) ) {
+ final GLProfile glp = GLProfile.get(GLProfile.GLES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ testGLFBODrawableImpl(caps, new GearsES2(0));
+ } else {
+ System.err.println("EGL ES2 n/a");
+ }
+ }
+
+ @Test
+ public void testEGLES2_Demo0MSAA4() throws InterruptedException {
+ if( GLProfile.isAvailable(GLProfile.GLES2) ) {
+ final GLProfile glp = GLProfile.get(GLProfile.GLES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(4);
+ testGLFBODrawableImpl(caps, new GearsES2(0));
+ } else {
+ System.err.println("EGL ES2 n/a");
+ }
+ }
+
+ boolean skipShot = false;
+
+ void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
+ caps.setFBO(true);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep);
+ Assert.assertNotNull(fboDrawable);
+ Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl);
+
+ fboDrawable.setRealized(true);
+ Assert.assertTrue(fboDrawable.isRealized());
+
+ final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject();
+
+ System.out.println("Realized: "+fboDrawable);
+ System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities());
+ System.out.println("Realized: "+fbo);
+
+ final GLContext context = fboDrawable.createContext(null);
+ Assert.assertNotNull(context);
+
+ int res = context.makeCurrent();
+ Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
+ context.release();
+
+ System.out.println("Post Create-Ctx: "+fbo);
+ final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0);
+ Assert.assertNotNull(colorA);
+ final FBObject.RenderAttachment depthA = fbo.getDepthAttachment();
+ Assert.assertNotNull(depthA);
+
+ final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, true);
+
+ glad.addGLEventListener(demo);
+ glad.addGLEventListener(new GLEventListener() {
+ volatile int displayCount=0;
+ volatile int reshapeCount=0;
+ public void init(GLAutoDrawable drawable) {}
+ public void dispose(GLAutoDrawable drawable) {}
+ public void display(GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight());
+ // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo);
+ // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO());
+ // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer());
+ if(skipShot) {
+ skipShot=false;
+ } else {
+ snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null);
+ }
+ Assert.assertEquals(drawable.getWidth(), widthStep*szStep);
+ Assert.assertEquals(drawable.getHeight(), heightStep*szStep);
+ displayCount++;
+ }
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight());
+ Assert.assertEquals(drawable.getWidth(), widthStep*szStep);
+ Assert.assertEquals(drawable.getHeight(), heightStep*szStep);
+ reshapeCount++;
+ }
+ });
+
+ // 0 - szStep = 2
+ glad.display();
+
+ // 1, 2 (resize + display)
+ szStep = 1;
+ skipShot=true;
+ glad.setSize(widthStep*szStep, heightStep*szStep);
+ glad.display();
+ Assert.assertEquals(glad.getWidth(), widthStep*szStep);
+ Assert.assertEquals(glad.getHeight(), heightStep*szStep);
+ {
+ // Check whether the attachment reference are still valid!
+ FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0);
+ Assert.assertNotNull(_colorA);
+ Assert.assertTrue(colorA == _colorA);
+ Assert.assertTrue(colorA.equals(_colorA));
+ FBObject.RenderAttachment _depthA = fbo.getDepthAttachment();
+ Assert.assertNotNull(_depthA);
+ Assert.assertTrue(depthA == _depthA);
+ Assert.assertTrue(depthA.equals(_depthA));
+
+ _colorA = fbo.getColorbuffer(colorA);
+ Assert.assertNotNull(_colorA);
+ Assert.assertTrue(colorA == _colorA);
+ Assert.assertTrue(colorA.equals(_colorA));
+ }
+
+ // 3, 4 (resize + display)
+ szStep = 4;
+ skipShot=true;
+ glad.setSize(widthStep*szStep, heightStep*szStep);
+ glad.display();
+ Assert.assertEquals(glad.getWidth(), widthStep*szStep);
+ Assert.assertEquals(glad.getHeight(), heightStep*szStep);
+ {
+ // Check whether the attachment reference are still valid!
+ FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0);
+ Assert.assertNotNull(_colorA);
+ Assert.assertTrue(colorA == _colorA);
+ final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment();
+ Assert.assertNotNull(_depthA);
+ Assert.assertTrue(depthA == _depthA);
+
+ _colorA = fbo.getColorbuffer(colorA);
+ Assert.assertNotNull(_colorA);
+ Assert.assertTrue(colorA == _colorA);
+ }
+
+ // 5
+ glad.display();
+ Assert.assertEquals(glad.getWidth(), widthStep*szStep);
+ Assert.assertEquals(glad.getHeight(), heightStep*szStep);
+
+ // 6, 7 (resize + display)
+ szStep = 3;
+ skipShot=true;
+ glad.setSize(widthStep*szStep, heightStep*szStep);
+ glad.display();
+ Assert.assertEquals(glad.getWidth(), widthStep*szStep);
+ Assert.assertEquals(glad.getHeight(), heightStep*szStep);
+
+ glad.destroy();
+ System.out.println("Fin: "+fboDrawable);
+
+ // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context);
+ }
+
+ public static void main(String args[]) throws IOException {
+ org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java
index 1b33866d7..f7c83a03b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestFBOMRTNEWT01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java
@@ -25,14 +25,18 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package com.jogamp.opengl.test.junit.jogl.glsl;
+package com.jogamp.opengl.test.junit.jogl.acore;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.texture.TextureIO;
+import com.jogamp.opengl.FBObject.Attachment.Type;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.NEWTGLContext;
@@ -40,6 +44,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import java.io.IOException;
+import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
@@ -53,17 +58,20 @@ import org.junit.Assert;
import org.junit.Test;
public class TestFBOMRTNEWT01 extends UITestCase {
- static long durationPerTest = 10; // ms
+ static long durationPerTest = 10*40*2; // ms
@Test
public void test01() throws InterruptedException {
+ final int step = 4;
+ final int width = 800;
+ final int height = 600;
// preset ..
if(!GLProfile.isAvailable(GLProfile.GL2GL3)) {
System.err.println("Test requires GL2/GL3 profile.");
return;
}
final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
- new GLCapabilities(GLProfile.getGL2GL3()), 640, 480, true);
+ new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true);
final GLDrawable drawable = winctx.context.getGLDrawable();
GL2GL3 gl = winctx.context.getGL().getGL2GL3();
gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3();
@@ -147,12 +155,15 @@ public class TestFBOMRTNEWT01 extends UITestCase {
texCoords0.enableBuffer(gl, false);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ final int texA0Point = 0; // attachment point for texA0
+ final int texA1Point = 1; // attachment point for texA1
+
// FBO w/ 2 texture2D color buffers
- final FBObject fbo_mrt = new FBObject(drawable.getWidth(), drawable.getHeight());
- fbo_mrt.init(gl);
- Assert.assertTrue( 0 == fbo_mrt.attachTexture2D(gl, texUnit0.intValue(), GL.GL_NEAREST, GL.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE) );
- Assert.assertTrue( 1 == fbo_mrt.attachTexture2D(gl, texUnit1.intValue(), GL.GL_NEAREST, GL.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE) );
- Assert.assertTrue( fbo_mrt.attachDepthBuffer(gl, GL.GL_DEPTH_COMPONENT16) );
+ final FBObject fbo_mrt = new FBObject();
+ fbo_mrt.reset(gl, drawable.getWidth(), drawable.getHeight());
+ final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ final TextureAttachment texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, 24);
Assert.assertTrue( fbo_mrt.isStatusValid() ) ;
fbo_mrt.unbind(gl);
@@ -170,9 +181,13 @@ public class TestFBOMRTNEWT01 extends UITestCase {
st.uniform(gl, pmvMatrixUniform);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0, GL.GL_COLOR_ATTACHMENT0+1 };
+ final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0+texA0Point, GL.GL_COLOR_ATTACHMENT0+texA1Point };
final int[] bck_buffers = new int[] { GL2GL3.GL_BACK_LEFT };
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ int step_i = 0;
+ int[] last_snap_size = new int[] { 0, 0 };
+
for(int i=0; i<durationPerTest; i+=50) {
// pass 1 - MRT: Red -> buffer0, Green -> buffer1
st.attachShaderProgram(gl, sp0, true);
@@ -198,8 +213,11 @@ public class TestFBOMRTNEWT01 extends UITestCase {
gl.glDrawBuffers(1, bck_buffers, 0);
gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
- fbo_mrt.use(gl, 0);
- fbo_mrt.use(gl, 1);
+
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
+ fbo_mrt.use(gl, texA0);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue());
+ fbo_mrt.use(gl, texA1);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
fbo_mrt.unuse(gl);
@@ -207,8 +225,27 @@ public class TestFBOMRTNEWT01 extends UITestCase {
colors0.enableBuffer(gl, false);
texCoords0.enableBuffer(gl, false);
+ {
+ final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface();
+ if(last_snap_size[0] != ns.getWidth() && last_snap_size[1] != ns.getHeight()) {
+ gl.glFinish(); // sync .. no swap buffers yet!
+ snapshot(getSimpleTestName("."), step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok
+ last_snap_size[0] = ns.getWidth();
+ last_snap_size[1] = ns.getHeight();
+ }
+ }
+
drawable.swapBuffers();
Thread.sleep(50);
+ int j = (int) ( (long)i / (durationPerTest/(long)step) ) + 1;
+ if(j>step_i) {
+ int w = width/step * j;
+ int h = height/step * j;
+ System.err.println("resize: "+step_i+" -> "+j+" - "+w+"x"+h);
+ fbo_mrt.reset(gl, w, h);
+ winctx.window.setSize(w, h);
+ step_i = j;
+ }
}
NEWTGLContext.destroyWindow(winctx);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
new file mode 100644
index 000000000..b384c9327
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
@@ -0,0 +1,258 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+public class TestFBOMix2DemosES2NEWT extends UITestCase {
+ static long duration = 500; // ms
+ static int swapInterval = 1;
+ static boolean showFPS = false;
+ static boolean forceES2 = false;
+ static boolean doRotate = true;
+ static boolean demo0Only = false;
+ static int globalNumSamples = 0;
+ static boolean mainRun = false;
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(GLCapabilitiesImmutable caps, int numSamples) throws InterruptedException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ System.err.println("requested: vsync "+swapInterval+", "+caps);
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval);
+ if(mainRun) {
+ glWindow.setSize(512, 512);
+ } else {
+ glWindow.setSize(128, 128);
+ }
+
+ final FBOMix2DemosES2 demo = new FBOMix2DemosES2(swapInterval);
+ demo.setMSAA(numSamples);
+ demo.setDoRotation(doRotate);
+ demo.setDemo0Only(demo0Only);
+ glWindow.addGLEventListener(demo);
+ glWindow.addGLEventListener(new GLEventListener() {
+ int i=0, c=0;
+ int origS;
+ public void init(GLAutoDrawable drawable) {
+ origS = demo.getMSAA();
+ }
+ public void dispose(GLAutoDrawable drawable) {}
+ public void display(GLAutoDrawable drawable) {
+ if(mainRun) return;
+
+ final int dw = drawable.getWidth();
+ final int dh = drawable.getHeight();
+ c++;
+
+ if(dw<800) {
+ System.err.println("XXX: "+dw+"x"+dh+", c "+c);
+ if(0 == c%3) {
+ snapshot(getSimpleTestName("."), i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ if( 3 == c ) {
+ new Thread() {
+ @Override
+ public void run() {
+ demo.setMSAA(4);
+ } }.start();
+ } else if( 6 == c ) {
+ new Thread() {
+ @Override
+ public void run() {
+ demo.setMSAA(8);
+ } }.start();
+ } else if(9 == c) {
+ c=0;
+ new Thread() {
+ @Override
+ public void run() {
+ glWindow.setSize(dw+256, dh+256);
+ demo.setMSAA(origS);
+ } }.start();
+ }
+ }
+ }
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ });
+
+ Animator animator = new Animator(glWindow);
+ QuitAdapter quitAdapter = new QuitAdapter();
+
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.addWindowListener(new WindowAdapter() {
+ public void windowResized(WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
+ }
+ public void windowMoved(WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
+ }
+ });
+
+ glWindow.addKeyListener(new KeyAdapter() {
+ public void keyTyped(KeyEvent e) {
+ System.err.println("*** "+e);
+ if(e.getKeyChar()=='f') {
+ new Thread() {
+ public void run() {
+ System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ } }.start();
+ } else if(e.getKeyChar()=='d') {
+ demo.setDemo0Only(!demo.getDemo0Only());
+ } else {
+ int num = e.getKeyChar() - '0';
+ System.err.println("*** "+num);
+ if(0 <= num && num <= 8) {
+ System.err.println("MSAA: "+demo.getMSAA()+" -> "+num);
+ demo.setMSAA(num);
+ }
+ }
+ }
+ });
+
+ animator.start();
+ // glWindow.setSkipContextReleaseThread(animator.getThread());
+
+ glWindow.setVisible(true);
+
+ System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
+ System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
+
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ glWindow.destroy();
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ }
+
+ @Test
+ public void test01_Main() throws InterruptedException {
+ if( mainRun ) {
+ GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ caps.setAlphaBits(1);
+ runTestGL(caps, globalNumSamples);
+ }
+ }
+
+ @Test
+ public void test01() throws InterruptedException {
+ if( mainRun ) return ;
+ GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ caps.setAlphaBits(1);
+ runTestGL(caps, 0);
+ }
+
+ public static void main(String args[]) throws IOException {
+ boolean waitForKey = false;
+
+ mainRun = true;
+
+ 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("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-showFPS")) {
+ showFPS = true;
+ } else if(args[i].equals("-samples")) {
+ i++;
+ globalNumSamples = MiscUtils.atoi(args[i], globalNumSamples);
+ } else if(args[i].equals("-norotate")) {
+ doRotate = false;
+ } else if(args[i].equals("-demo0Only")) {
+ demo0Only = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ } else if(args[i].equals("-nomain")) {
+ mainRun = false;
+ }
+ }
+
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("forceES2 "+forceES2);
+
+ if(waitForKey) {
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ try {
+ System.err.println(stdin.readLine());
+ } catch (IOException e) { }
+ }
+ org.junit.runner.JUnitCore.main(TestFBOMix2DemosES2NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
index a2d060a8c..96d9b2e28 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
@@ -85,10 +85,10 @@ public class TestGLAutoDrawableDelegateNEWT extends UITestCase {
Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
context.release();
- final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context) {
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false) {
@Override
- public void destroy() {
- super.destroy(); // destroys drawable/context
+ protected void destroyImplInLock() {
+ super.destroyImplInLock(); // destroys drawable/context
window.destroy(); // destroys the actual window
}
};
@@ -97,15 +97,15 @@ public class TestGLAutoDrawableDelegateNEWT extends UITestCase {
window.addWindowListener(new WindowAdapter() {
@Override
public void windowRepaint(WindowUpdateEvent e) {
- glad.defaultWindowRepaintOp();
+ glad.windowRepaintOp();
}
@Override
public void windowResized(WindowEvent e) {
- glad.defaultWindowResizedOp();
+ glad.windowResizedOp();
}
@Override
public void windowDestroyNotify(WindowEvent e) {
- glad.defaultWindowDestroyNotifyOp();
+ glad.windowDestroyNotifyOp();
}
});
window.addWindowListener(wl);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
index 483a09735..cece4c6d5 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
@@ -88,10 +88,10 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
drawable.setRealized(true);
Assert.assertTrue(drawable.isRealized());
- final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null) {
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false) {
@Override
- public void destroy() {
- super.destroy(); // destroys drawable/context
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
window.destroy(); // destroys the actual window
}
};
@@ -100,15 +100,15 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
window.addWindowListener(new WindowAdapter() {
@Override
public void windowRepaint(WindowUpdateEvent e) {
- glad.defaultWindowRepaintOp();
+ glad.windowRepaintOp();
}
@Override
public void windowResized(WindowEvent e) {
- glad.defaultWindowResizedOp();
+ glad.windowResizedOp();
}
@Override
public void windowDestroyNotify(WindowEvent e) {
- glad.defaultWindowDestroyNotifyOp();
+ glad.windowDestroyNotifyOp();
}
});
window.addWindowListener(wl);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java
index 78988c0e5..b3516d6b4 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java
@@ -33,9 +33,9 @@ import java.io.IOException;
import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
-import org.junit.Assert;
import org.junit.Test;
import com.jogamp.newt.opengl.GLWindow;
@@ -69,7 +69,7 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
public void run() {
- System.err.println("Animatr "+id+": PRE: "+Thread.currentThread().getName());
+ System.err.println("Animatr "+id+", count "+frameCount+": PRE: "+Thread.currentThread().getName());
for(int c=0; c<frameCount; c++) {
glad.display();
@@ -99,10 +99,10 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
public void run() {
- System.err.println("Resizer "+id+": PRE: "+Thread.currentThread().getName());
+ System.err.println("Resizer "+id+", count "+actionCount+": PRE: "+Thread.currentThread().getName());
for(int c=0; c<actionCount; c++) {
- win.runOnEDTIfAvail(false, new Runnable() {
+ win.runOnEDTIfAvail(true, new Runnable() {
public void run() {
// Normal resize, may trigger immediate display within lock
win.setSize(win.getWidth()+1, win.getHeight()+1);
@@ -148,41 +148,80 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
return true;
}
+ protected class MyEventCounter implements GLEventListener {
+ volatile int reshapeCount = 0;
+ volatile int displayCount = 0;
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ }
+
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ System.err.println("*** reshapes: "+reshapeCount+", displays "+displayCount);
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ displayCount++;
+ }
+
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ reshapeCount++;
+ }
+
+ public void reset() {
+ reshapeCount = 0;
+ displayCount = 0;
+ }
+ }
+
protected void runJOGLTasks(int animThreadCount, int frameCount, int reszThreadCount, int resizeCount) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getDefault()));
- Assert.assertNotNull(glWindow);
+ final GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getDefault()));
+ final MyEventCounter myEventCounter = new MyEventCounter();
glWindow.addGLEventListener(new GearsES2(0));
+ glWindow.addGLEventListener(myEventCounter);
glWindow.setSize(demoSize, demoSize);
glWindow.setVisible(true);
final String currentThreadName = Thread.currentThread().getName();
final Object sync = new Object();
- final MyRunnable[] tasks = new MyRunnable[animThreadCount+reszThreadCount];
- final Thread[] threads = new Thread[animThreadCount+reszThreadCount];
- int i=0;
+ final MyRunnable[] animTasks = new MyRunnable[animThreadCount];
+ final MyRunnable[] resizeTasks = new MyRunnable[animThreadCount];
+ final Thread[] animThreads = new Thread[reszThreadCount];
+ final Thread[] resizeThreads = new Thread[reszThreadCount];
System.err.println("animThreadCount "+animThreadCount+", frameCount "+frameCount);
System.err.println("reszThreadCount "+reszThreadCount+", resizeCount "+resizeCount);
- System.err.println("tasks "+tasks.length+", threads "+threads.length);
+ System.err.println("tasks "+(animTasks.length+resizeTasks.length)+", threads "+(animThreads.length+resizeThreads.length));
- for(; i<animThreadCount; i++) {
+ for(int i=0; i<animThreadCount; i++) {
System.err.println("create anim task/thread "+i);
- tasks[i] = new RudeAnimator(glWindow, frameCount, sync, i);
- threads[i] = new Thread(tasks[i], currentThreadName+"-anim"+i);
+ animTasks[i] = new RudeAnimator(glWindow, frameCount, sync, i);
+ animThreads[i] = new Thread(animTasks[i], currentThreadName+"-anim"+i);
}
- for(; i<animThreadCount+reszThreadCount; i++) {
+ for(int i=0; i<reszThreadCount; i++) {
System.err.println("create resz task/thread "+i);
- tasks[i] = new RudeResizer(glWindow, resizeCount, sync, i);
- threads[i] = new Thread(tasks[i], currentThreadName+"-resz"+i);
+ resizeTasks[i] = new RudeResizer(glWindow, resizeCount, sync, i);
+ resizeThreads[i] = new Thread(resizeTasks[i], currentThreadName+"-resz"+i);
}
- for(i=0; i<animThreadCount+reszThreadCount; i++) {
- System.err.println("start thread "+i);
- threads[i].start();
+ myEventCounter.reset();
+
+ int j=0, k=0;
+ for(int i=0; i<reszThreadCount+animThreadCount; i++) {
+ if(0==i%2) {
+ System.err.println("start resize thread "+j);
+ resizeThreads[j++].start();
+ } else {
+ System.err.println("start anim thread "+k);
+ animThreads[k++].start();
+ }
}
synchronized (sync) {
- while(!done(tasks)) {
+ while(!done(resizeTasks) || !done(animTasks)) {
try {
sync.wait();
} catch (InterruptedException e) {
@@ -190,8 +229,8 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
}
}
- i=0;
- while(i<30 && !isDead(threads)) {
+ int i=0;
+ while(i<30 && !isDead(animThreads) && !isDead(resizeThreads)) {
Thread.sleep(100);
i++;
}
@@ -200,8 +239,13 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
@Test
- public void test01_1AThreads_600Frames() throws InterruptedException {
- runJOGLTasks(1, 600, 1, 600);
+ public void test01_1A1RThreads_100Resizes() throws InterruptedException {
+ runJOGLTasks(1, 200, 1, 100);
+ }
+
+ @Test
+ public void test01_3A3RThreads_50Resizes() throws InterruptedException {
+ runJOGLTasks(3, 100, 3, 50);
}
public static void main(String args[]) throws IOException {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
index 9ca6670ad..d9429129b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
@@ -54,7 +54,7 @@ public class TestGLProfile01NEWT extends UITestCase {
System.err.println(JoglVersion.getInstance());
System.err.println(NewtVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
}
@Test
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
index e14d5b800..33a9b7799 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
@@ -43,10 +43,10 @@ public class TestNEWTCloseX11DisplayBug565 {
if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
final int openD = X11Util.getOpenDisplayConnectionNumber() - open0;
- if(openD>1) {
+ if( openD > 0) {
X11Util.dumpOpenDisplayConnections();
X11Util.dumpPendingDisplayConnections();
- Assert.assertTrue("More than 1 new open display connections", false);
+ Assert.assertEquals("New display connection didn't close", 0, openD);
}
}
}
@@ -86,10 +86,10 @@ public class TestNEWTCloseX11DisplayBug565 {
if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
final int openD = X11Util.getOpenDisplayConnectionNumber() - open0;
- if(openD>1) {
+ if(openD > 0) {
X11Util.dumpOpenDisplayConnections();
X11Util.dumpPendingDisplayConnections();
- Assert.assertTrue("More than 1 new open display connections", false);
+ Assert.assertEquals("New display connection didn't close", 0, openD);
}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java
index 5f374830d..b21ad5b5b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java
@@ -86,7 +86,7 @@ public class TestShutdownCompleteNEWT extends UITestCase {
}
long t2 = System.nanoTime();
if(glInfo) {
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, false).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, false).toString());
}
long t3 = System.nanoTime();
GLProfile.shutdown(GLProfile.ShutdownType.COMPLETE);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java
index 8384e5b61..3f6935588 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java
@@ -9,11 +9,8 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
-import javax.media.nativewindow.NativeWindow;
import javax.media.opengl.GLAnimatorControl;
-import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JComboBox;
@@ -21,11 +18,8 @@ import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
-import jogamp.nativewindow.windows.GDI;
-
import org.junit.Test;
-import com.jogamp.common.os.Platform;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -83,7 +77,7 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
canvas.setPreferredSize(new Dimension(640, 480));
final GLAnimatorControl animatorCtrl = useFPSAnimator ? new FPSAnimator(canvas, 60) : new Animator(canvas);
- animatorCtrl.setUpdateFPSFrames(60, System.err);
+ animatorCtrl.setUpdateFPSFrames(60, null);// System.err);
switch (animCtrl) {
case PauseResume:
animatorCtrl.start();
@@ -92,6 +86,7 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
case Continue:
animatorCtrl.start();
break;
+ default:
}
canvas.addGLEventListener(new GearsES2(1));
@@ -141,6 +136,7 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
case PauseResume:
animatorCtrl.resume();
break;
+ default:
}
selected = CANVAS;
} else if(newSelection.equals(LABEL)) {
@@ -151,6 +147,7 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
case PauseResume:
animatorCtrl.pause();
break;
+ default:
}
cl.show(cards, LABEL);
selected = LABEL;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java
index 4b0caf898..478bd4543 100755
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java
@@ -40,7 +40,6 @@
package com.jogamp.opengl.test.junit.jogl.caps;
-import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.awt.BorderLayout;
import java.awt.Frame;
@@ -48,14 +47,15 @@ import java.awt.Frame;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
-import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.MultisampleDemoES1;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
import org.junit.Test;
@@ -75,13 +75,6 @@ public class TestMultisampleES1AWT extends UITestCase {
org.junit.runner.JUnitCore.main(tstname);
}
- protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) {
- GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false);
- if(screenshot.readPixels(drawable.getGL(), drawable, flip)) {
- screenshot.write(new File(filename));
- }
- }
-
@Test
public void testOnscreenMultiSampleAA0() throws InterruptedException, InvocationTargetException {
testMultiSampleAAImpl(0);
@@ -98,6 +91,7 @@ public class TestMultisampleES1AWT extends UITestCase {
}
private void testMultiSampleAAImpl(int reqSamples) throws InterruptedException, InvocationTargetException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
GLProfile glp = GLProfile.getMaxFixedFunc(true);
GLCapabilities caps = new GLCapabilities(glp);
GLCapabilitiesChooser chooser = new MultisampleChooser01();
@@ -110,14 +104,11 @@ public class TestMultisampleES1AWT extends UITestCase {
canvas = new GLCanvas(caps, chooser, null, null);
canvas.addGLEventListener(new MultisampleDemoES1(reqSamples>0?true:false));
canvas.addGLEventListener(new GLEventListener() {
+ int displayCount = 0;
public void init(GLAutoDrawable drawable) {}
public void dispose(GLAutoDrawable drawable) {}
public void display(GLAutoDrawable drawable) {
- final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
- final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_";
- final String aaext = caps.getSampleExtension();
- final int samples = caps.getSampleBuffers() ? caps.getNumSamples() : 0 ;
- snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-S"+samples+"-"+aaext+"-"+drawable.getGLProfile().getName()+".png");
+ snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
});
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java
index 2e47b6841..ed8e2bd85 100755
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java
@@ -40,21 +40,20 @@
package com.jogamp.opengl.test.junit.jogl.caps;
-import java.io.File;
-
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
-import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import org.junit.Test;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.MultisampleDemoES1;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
public class TestMultisampleES1NEWT extends UITestCase {
static long durationPerTest = 60; // ms
@@ -71,13 +70,6 @@ public class TestMultisampleES1NEWT extends UITestCase {
org.junit.runner.JUnitCore.main(tstname);
}
- protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) {
- GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false);
- if(screenshot.readPixels(drawable.getGL(), drawable, flip)) {
- screenshot.write(new File(filename));
- }
- }
-
@Test
public void testOnscreenMultiSampleAA0() throws InterruptedException {
testMultiSampleAAImpl(true, 0);
@@ -119,6 +111,7 @@ public class TestMultisampleES1NEWT extends UITestCase {
}
private void testMultiSampleAAImpl(boolean onscreen, int reqSamples) throws InterruptedException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
GLProfile glp = GLProfile.getMaxFixedFunc(true);
GLCapabilities caps = new GLCapabilities(glp);
GLCapabilitiesChooser chooser = new MultisampleChooser01();
@@ -136,14 +129,11 @@ public class TestMultisampleES1NEWT extends UITestCase {
window.setCapabilitiesChooser(chooser);
window.addGLEventListener(new MultisampleDemoES1(reqSamples>0?true:false));
window.addGLEventListener(new GLEventListener() {
+ int displayCount = 0;
public void init(GLAutoDrawable drawable) {}
public void dispose(GLAutoDrawable drawable) {}
public void display(GLAutoDrawable drawable) {
- final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
- final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_";
- final String aaext = caps.getSampleExtension();
- final int samples = caps.getSampleBuffers() ? caps.getNumSamples() : 0 ;
- snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-S"+samples+"-"+aaext+"-"+drawable.getGLProfile().getName()+".png");
+ snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
});
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java
new file mode 100644
index 000000000..02fcae6ef
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.caps;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesChooser;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Test;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+public class TestMultisampleES2NEWT extends UITestCase {
+ static long durationPerTest = 60; // ms
+
+ public static void main(String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], 500);
+ }
+ }
+ System.out.println("durationPerTest: "+durationPerTest);
+ String tstname = TestMultisampleES2NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+ @Test
+ public void testOnscreenMultiSampleAA0() throws InterruptedException {
+ testMultiSampleAAImpl(false, false, 0);
+ }
+
+ @Test
+ public void testOnscreenMultiSampleAA8() throws InterruptedException {
+ testMultiSampleAAImpl(false, false, 8);
+ }
+
+ @Test
+ public void testOffscreenPBufferMultiSampleAA0() throws InterruptedException {
+ testMultiSampleAAImpl(false, true, 0);
+ }
+
+ @Test(timeout = 3000) // 3s timeout
+ public void testOffsreenPBufferMultiSampleAA8() throws InterruptedException {
+ testMultiSampleAAImpl(false, true, 8);
+ }
+
+ @Test(timeout = 3000) // 3s timeout
+ public void testOffscreenFBOMultiSampleAA0() throws InterruptedException {
+ testMultiSampleAAImpl(true, false, 0);
+ }
+
+ @Test(timeout = 3000) // 3s timeout
+ public void testOffsreenFBOMultiSampleAA8() throws InterruptedException {
+ testMultiSampleAAImpl(true, false, 8);
+ }
+
+ private void testMultiSampleAAImpl(boolean useFBO, boolean usePBuffer, int reqSamples) throws InterruptedException {
+ if(useFBO) {
+ System.err.println("NEWT offscreen FBO Window n/a yet");
+ return;
+ }
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ GLProfile glp = GLProfile.getGL2ES2();
+ GLCapabilities caps = new GLCapabilities(glp);
+ GLCapabilitiesChooser chooser = new MultisampleChooser01();
+
+ caps.setAlphaBits(1);
+ caps.setFBO(useFBO);
+ caps.setPBuffer(usePBuffer);
+
+ if(reqSamples>0) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(reqSamples);
+ }
+
+ final GLWindow window = GLWindow.create(caps);
+ window.setCapabilitiesChooser(chooser);
+ window.addGLEventListener(new MultisampleDemoES2(reqSamples>0?true:false));
+ window.addGLEventListener(new GLEventListener() {
+ int displayCount = 0;
+ public void init(GLAutoDrawable drawable) {}
+ public void dispose(GLAutoDrawable drawable) {}
+ public void display(GLAutoDrawable drawable) {
+ snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ });
+ window.setSize(512, 512);
+ window.setVisible(true);
+ window.requestFocus();
+
+ Thread.sleep(durationPerTest);
+
+ window.destroy();
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java
index 8e720965c..7cce5d1e4 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java
@@ -65,7 +65,6 @@ public class TestTranslucencyAWT extends UITestCase {
public static void initClass() {
size = new Dimension(400,200);
glCaps = new GLCapabilities(null);
- glCaps.setAlphaBits(8);
glCaps.setBackgroundOpaque(false);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
index 5c82a43c6..e81d1b4af 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
@@ -129,12 +129,13 @@ public class GearsES1 implements GLEventListener {
gl.glEnable(GL2ES1.GL_NORMALIZE);
- if (drawable.getNativeSurface() instanceof Window) {
- Window window = (Window) drawable.getNativeSurface();
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.addMouseListener(gearsMouse);
window.addKeyListener(gearsKeys);
- } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) {
- java.awt.Component comp = (java.awt.Component) drawable;
+ } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) upstreamWidget;
new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse).addTo(comp);
new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys).addTo(comp);
}
@@ -165,8 +166,9 @@ public class GearsES1 implements GLEventListener {
public void dispose(GLAutoDrawable drawable) {
System.err.println(Thread.currentThread()+" GearsES1.dispose ... ");
- if (drawable.getNativeSurface() instanceof Window) {
- Window window = (Window) drawable.getNativeSurface();
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.removeMouseListener(gearsMouse);
window.removeKeyListener(gearsKeys);
}
@@ -188,8 +190,9 @@ public class GearsES1 implements GLEventListener {
GL2ES1 gl = drawable.getGL().getGL2ES1();
final boolean hasFocus;
- if(drawable.getNativeSurface() instanceof NativeWindow) {
- hasFocus = ((NativeWindow)drawable.getNativeSurface()).hasFocus();
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if(upstreamWidget instanceof NativeWindow) {
+ hasFocus = ((NativeWindow)upstreamWidget).hasFocus();
} else {
hasFocus = true;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleDemoES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java
index 0aaf4b020..aad56581b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleDemoES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java
@@ -38,24 +38,16 @@
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
-package com.jogamp.opengl.test.junit.jogl.caps;
+package com.jogamp.opengl.test.junit.jogl.demos.es1;
-import jogamp.opengl.x11.glx.GLX;
-import jogamp.opengl.x11.glx.X11GLXGraphicsConfiguration;
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES1;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLPipelineFactory;
import com.jogamp.opengl.util.ImmModeSink;
-class MultisampleDemoES1 implements GLEventListener {
-
- static boolean glDebug = false;
- static boolean glTrace = false;
+public class MultisampleDemoES1 implements GLEventListener {
boolean multisample;
ImmModeSink immModeSink;
@@ -70,30 +62,7 @@ class MultisampleDemoES1 implements GLEventListener {
System.err.println();
System.err.println("Chosen : " + drawable.getChosenGLCapabilities());
System.err.println();
- if (!drawable.getGL().isGLES() && NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(false))) {
- AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
- X11GLXGraphicsConfiguration x11config = (X11GLXGraphicsConfiguration) config;
- long display = drawable.getNativeSurface().getDisplayHandle();
- int[] foo = new int[1];
- GLX.glXGetFBConfigAttrib(display, x11config.getFBConfig(), GLX.GLX_SAMPLES, foo, 0);
- System.out.println("GLX_SAMPLES " + foo[0]);
- GLX.glXGetFBConfigAttrib(display, x11config.getFBConfig(), GLX.GLX_SAMPLE_BUFFERS, foo, 0);
- System.out.println("GLX_SAMPLE_BUFFERS " + foo[0]);
- }
- GL _gl = drawable.getGL();
- if (glDebug) {
- try {
- // Debug ..
- _gl = _gl.getContext().setGL(GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, _gl, null));
- if (glTrace) {
- // Trace ..
- _gl = _gl.getContext().setGL(GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, _gl, new Object[]{System.err}));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- GL2ES1 gl = _gl.getGL2ES1();
+ GL2ES1 gl = drawable.getGL().getGL2ES1();
if (multisample) {
gl.glEnable(GL.GL_MULTISAMPLE);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java
new file mode 100644
index 000000000..3dfbb4893
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java
@@ -0,0 +1,309 @@
+/**
+ * Copyright (C) 2011 JogAmp Community. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.TextureAttachment;
+import com.jogamp.opengl.FBObject.Attachment.Type;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+public class FBOMix2DemosES2 implements GLEventListener {
+ private final GearsES2 demo0;
+ private final RedSquareES2 demo1;
+ private final int swapInterval;
+ private int numSamples;
+ private boolean demo0Only;
+
+
+ private final ShaderState st;
+ private final PMVMatrix pmvMatrix;
+
+ private final FBObject fbo0;
+ private final FBObject fbo1;
+
+ private TextureAttachment fbo0Tex;
+ private TextureAttachment fbo1Tex;
+
+ private ShaderProgram sp0;
+ private GLUniformData pmvMatrixUniform;
+ private GLArrayDataServer interleavedVBO;
+ private GLUniformData texUnit0;
+ private GLUniformData texUnit1;
+
+ public FBOMix2DemosES2(int swapInterval) {
+ demo0 = new GearsES2(-1);
+ demo0.setIsFBOSlave(true);
+ demo1 = new RedSquareES2(-1);
+ demo1.setIsFBOSlave(true);
+ this.swapInterval = swapInterval;
+
+ st = new ShaderState();
+ // st.setVerbose(true);
+ pmvMatrix = new PMVMatrix();
+
+ fbo0 = new FBObject();
+ fbo1 = new FBObject();
+
+ numSamples = 0;
+ demo0Only = false;
+ }
+
+ public void setDemo0Only(boolean v) {
+ this.demo0Only = v;
+ }
+ public boolean getDemo0Only() { return demo0Only; }
+
+ public void setMSAA(int numSamples) {
+ this.numSamples=numSamples;
+ }
+ public int getMSAA() { return numSamples; }
+
+ public void setDoRotation(boolean rotate) { demo1.setDoRotation(rotate); }
+
+ static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
+ static final String gl2_prelude = "#version 110\n";
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ demo0.init(drawable);
+ demo1.init(drawable);
+
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, FBOMix2DemosES2.class, "shader",
+ "shader/bin", "texture01_xxx", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, FBOMix2DemosES2.class, "shader",
+ "shader/bin", "texture02_xxx", true);
+
+ // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
+ int fp0Pos;
+ if(gl.isGLES2()) {
+ vp0.insertShaderSource(0, 0, es2_prelude[0]);
+ fp0Pos = fp0.insertShaderSource(0, 0, es2_prelude[0]);
+ } else {
+ vp0.insertShaderSource(0, 0, gl2_prelude);
+ fp0Pos = fp0.insertShaderSource(0, 0, gl2_prelude);
+ }
+ if(gl.isGLES2()) {
+ fp0Pos = fp0.insertShaderSource(0, fp0Pos, es2_prelude[1]);
+ }
+
+ sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0, true);
+
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
+ {
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+
+ FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+
+ for(int i=0; i<4; i++) {
+ ib.put(s_quadVertices, i*3, 3);
+ ib.put(s_quadColors, i*4, 4);
+ //ib.put(s_cubeNormals, i*3, 3);
+ ib.put(s_quadTexCoords, i*2, 2);
+ }
+ }
+ interleavedVBO.seal(gl, true);
+ interleavedVBO.enableBuffer(gl, false);
+ st.ownAttribute(interleavedVBO, true);
+
+ texUnit0 = new GLUniformData("mgl_Texture0", 0);
+ st.ownUniform(texUnit0);
+ st.uniform(gl, texUnit0);
+ texUnit1 = new GLUniformData("mgl_Texture1", 1);
+ st.ownUniform(texUnit1);
+ st.uniform(gl, texUnit1);
+
+ st.useProgram(gl, false);
+
+ System.err.println("**** Init");
+ resetFBOs(gl, drawable);
+
+ fbo0.attachRenderbuffer(gl, Type.DEPTH, 24);
+ fbo0.unbind(gl);
+ fbo1.attachRenderbuffer(gl, Type.DEPTH, 24);
+ fbo1.unbind(gl);
+ gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+
+ numSamples=fbo0.getNumSamples();
+ }
+
+ /** Since we switch MSAA and non-MSAA we need to take extra care, i.e. sync msaa for both FBOs ..*/
+ private void resetFBOs(GL gl, GLAutoDrawable drawable) {
+ // remove all texture attachments, since MSAA uses just color-render-buffer
+ // and non-MSAA uses texture2d-buffer
+ fbo0.detachAllColorbuffer(gl);
+ fbo1.detachAllColorbuffer(gl);
+
+ fbo0.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples);
+ fbo1.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples);
+ if(fbo0.getNumSamples() != fbo1.getNumSamples()) {
+ throw new InternalError("sample size mismatch: \n\t0: "+fbo0+"\n\t1: "+fbo1);
+ }
+ numSamples = fbo0.getNumSamples();
+
+ if(numSamples>0) {
+ fbo0.attachColorbuffer(gl, 0, true);
+ fbo1.attachColorbuffer(gl, 0, true);
+ fbo0Tex = fbo0.getSamplingSink();
+ fbo1Tex = fbo1.getSamplingSink();
+ } else {
+ fbo0Tex = fbo0.attachTexture2D(gl, 0, true);
+ fbo1Tex = fbo1.attachTexture2D(gl, 0, true);
+ }
+ }
+
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ demo0.dispose(drawable);
+ demo1.dispose(drawable);
+ fbo0.destroy(gl);
+ fbo1.destroy(gl);
+ st.destroy(gl);
+
+ fbo0Tex = null;
+ fbo1Tex = null;
+ sp0 = null;
+ pmvMatrixUniform = null;
+ interleavedVBO = null;
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ if( fbo0.getNumSamples() != numSamples ) {
+ System.err.println("**** NumSamples: "+fbo0.getNumSamples()+" -> "+numSamples);
+ resetFBOs(gl, drawable);
+ }
+
+ if(0 < numSamples) {
+ gl.glEnable(GL.GL_MULTISAMPLE);
+ }
+
+ fbo0.bind(gl);
+ demo0.display(drawable);
+ fbo0.unbind(gl);
+
+ if(!demo0Only) {
+ fbo1.bind(gl);
+ demo1.display(drawable);
+ fbo1.unbind(gl);
+ }
+
+ st.useProgram(gl, true);
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
+ fbo0.use(gl, fbo0Tex);
+ if(!demo0Only) {
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue());
+ fbo1.use(gl, fbo1Tex);
+ }
+ interleavedVBO.enableBuffer(gl, true);
+
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+
+ interleavedVBO.enableBuffer(gl, false);
+ fbo0.unuse(gl);
+ if(!demo0Only) {
+ fbo1.unuse(gl);
+ }
+
+ st.useProgram(gl, false);
+ }
+
+ @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(drawable.getWidth() == fbo0.getWidth() && drawable.getHeight() == fbo0.getHeight() ) {
+ System.err.println("**** Reshape: "+width+"x"+height);
+ resetFBOs(gl, drawable);
+ //}
+
+ fbo0.bind(gl);
+ demo0.reshape(drawable, x, y, width, height);
+ fbo0.unbind(gl);
+ fbo1.bind(gl);
+ demo1.reshape(drawable, x, y, width, height);
+ fbo1.unbind(gl);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+
+ }
+
+ private static final float[] s_quadVertices = {
+ -1f, -1f, 0f, // LB
+ 1f, -1f, 0f, // RB
+ -1f, 1f, 0f, // LT
+ 1f, 1f, 0f // RT
+ };
+ private static final float[] s_quadColors = {
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f };
+ private static final float[] s_quadTexCoords = {
+ 0f, 0f, // LB
+ 1f, 0f, // RB
+ 0f, 1f, // LT
+ 1f, 1f // RT
+ };
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index 6aea5bb9c..38e8a15ce 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -65,6 +65,7 @@ public class GearsES2 implements GLEventListener {
private int prevMouseX, prevMouseY;
private boolean isInitialized = false;
+ boolean isFBOSlave = false;
public GearsES2(int swapInterval) {
this.swapInterval = swapInterval;
@@ -74,6 +75,8 @@ public class GearsES2 implements GLEventListener {
this.swapInterval = 1;
}
+ public void setIsFBOSlave(boolean v) { isFBOSlave = v; }
+
public void setPMVUseBackingArray(boolean pmvUseBackingArray) {
this.pmvUseBackingArray = pmvUseBackingArray;
}
@@ -115,7 +118,6 @@ public class GearsES2 implements GLEventListener {
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- gl.glEnable(GL.GL_CULL_FACE);
gl.glEnable(GL.GL_DEPTH_TEST);
st = new ShaderState();
@@ -168,13 +170,14 @@ public class GearsES2 implements GLEventListener {
gear3 = new GearsObjectES2(gear3, pmvMatrix, pmvMatrixUniform, colorU);
System.err.println("gear3 reused: "+gear3);
}
-
- if (drawable.getNativeSurface() instanceof Window) {
- Window window = (Window) drawable.getNativeSurface();
+
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.addMouseListener(gearsMouse);
window.addKeyListener(gearsKeys);
- } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) {
- java.awt.Component comp = (java.awt.Component) drawable;
+ } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) upstreamWidget;
new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse).addTo(comp);
new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys).addTo(comp);
}
@@ -187,7 +190,9 @@ public class GearsES2 implements GLEventListener {
System.err.println(Thread.currentThread()+" GearsES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval);
GL2ES2 gl = drawable.getGL().getGL2ES2();
- gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ }
st.useProgram(gl, true);
pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
@@ -218,8 +223,9 @@ public class GearsES2 implements GLEventListener {
}
isInitialized = false;
System.err.println(Thread.currentThread()+" GearsES2.dispose ... ");
- if (drawable.getNativeSurface() instanceof Window) {
- Window window = (Window) drawable.getNativeSurface();
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.removeMouseListener(gearsMouse);
window.removeKeyListener(gearsKeys);
}
@@ -235,6 +241,7 @@ public class GearsES2 implements GLEventListener {
colorU = null;
st.destroy(gl);
st = null;
+
System.err.println(Thread.currentThread()+" GearsES2.dispose FIN");
}
@@ -246,12 +253,16 @@ public class GearsES2 implements GLEventListener {
GL2ES2 gl = drawable.getGL().getGL2ES2();
final boolean hasFocus;
- if(drawable.getNativeSurface() instanceof NativeWindow) {
- hasFocus = ((NativeWindow)drawable.getNativeSurface()).hasFocus();
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if(upstreamWidget instanceof NativeWindow) {
+ hasFocus = ((NativeWindow)upstreamWidget).hasFocus();
} else {
hasFocus = true;
}
- if(hasFocus) {
+
+ gl.glEnable(GL.GL_CULL_FACE);
+
+ if( isFBOSlave || hasFocus ) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
} else {
gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
@@ -278,7 +289,9 @@ public class GearsES2 implements GLEventListener {
gear2.draw(gl, 3.1f, -2.0f, -2f * angle - 9.0f, GearsObject.green);
gear3.draw(gl, -3.1f, 4.2f, -2f * angle - 25.0f, GearsObject.blue);
pmvMatrix.glPopMatrix();
- st.useProgram(gl, false);
+ st.useProgram(gl, false);
+
+ gl.glDisable(GL.GL_CULL_FACE);
}
boolean confinedFixedCenter = false;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java
new file mode 100644
index 000000000..5facc1a49
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.opengl.util.ImmModeSink;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+public class MultisampleDemoES2 implements GLEventListener {
+
+ private boolean multisample;
+ private final ShaderState st;
+ private final PMVMatrix pmvMatrix;
+ private ShaderProgram sp0;
+ private GLUniformData pmvMatrixUniform;
+ private ImmModeSink immModeSink;
+
+ public MultisampleDemoES2(boolean multisample) {
+ this.multisample = multisample;
+ st = new ShaderState();
+ st.setVerbose(true);
+ pmvMatrix = new PMVMatrix();
+ }
+
+ static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
+ static final String gl2_prelude = "#version 110\n";
+
+ public void init(GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ System.err.println();
+ System.err.println("Requested: " + glad.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities());
+ System.err.println();
+ System.err.println("Chosen : " + glad.getChosenGLCapabilities());
+ System.err.println();
+
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MultisampleDemoES2.class, "shader",
+ "shader/bin", "mgl_default_xxx", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MultisampleDemoES2.class, "shader",
+ "shader/bin", "mgl_default_xxx", true);
+
+ // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
+ int fp0Pos;
+ if(gl.isGLES2()) {
+ vp0.insertShaderSource(0, 0, es2_prelude[0]);
+ fp0Pos = fp0.insertShaderSource(0, 0, es2_prelude[0]);
+ } else {
+ vp0.insertShaderSource(0, 0, gl2_prelude);
+ fp0Pos = fp0.insertShaderSource(0, 0, gl2_prelude);
+ }
+ if(gl.isGLES2()) {
+ fp0Pos = fp0.insertShaderSource(0, fp0Pos, es2_prelude[1]);
+ }
+
+ sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0, true);
+
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ // Using predef array names, see
+ // GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex);
+ immModeSink = ImmModeSink.createGLSL(gl, GL.GL_STATIC_DRAW, 40,
+ 3, GL.GL_FLOAT, // vertex
+ 4, GL.GL_FLOAT, // color
+ 0, GL.GL_FLOAT,// normal
+ 0, GL.GL_FLOAT); // texture
+ final int numSteps = 20;
+ final double increment = Math.PI / numSteps;
+ final double radius = 1;
+ immModeSink.glBegin(GL.GL_LINES);
+ for (int i = numSteps - 1; i >= 0; i--) {
+ immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)),
+ (float) (radius * Math.sin(i * increment)),
+ 0f);
+ immModeSink.glColor4f( 1f, 1f, 1f, 1f );
+ immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)),
+ (float) (-1.0 * radius * Math.sin(i * increment)),
+ 0f);
+ immModeSink.glColor4f( 1f, 1f, 1f, 1f );
+ }
+ immModeSink.glEnd(gl, false);
+
+ st.useProgram(gl, false);
+ }
+
+ public void dispose(GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ immModeSink.destroy(gl);
+ immModeSink = null;
+ st.destroy(gl);
+ }
+
+ public void display(GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if (multisample) {
+ gl.glEnable(GL.GL_MULTISAMPLE);
+ }
+ gl.glClearColor(0, 0, 0, 0);
+ // gl.glEnable(GL.GL_DEPTH_TEST);
+ // gl.glDepthFunc(GL.GL_LESS);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ st.useProgram(gl, true);
+
+ immModeSink.draw(gl, true);
+
+ st.useProgram(gl, false);
+ }
+
+ // Unused routines
+ public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
+ System.err.println("reshape ..");
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ // pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
+ pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+
+ public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
index 6982d61b7..a956fe1e4 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
@@ -27,9 +27,7 @@
*/
package com.jogamp.opengl.test.junit.jogl.demos.es2;
-import com.jogamp.newt.event.MouseAdapter;
-import com.jogamp.newt.event.MouseEvent;
-import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.Window;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderCode;
@@ -37,10 +35,8 @@ import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderState;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLRunnable;
import javax.media.opengl.GLUniformData;
public class RedSquareES2 implements GLEventListener {
@@ -51,11 +47,11 @@ public class RedSquareES2 implements GLEventListener {
GLArrayDataServer colors ;
long t0;
private int swapInterval = 0;
- MyMouseAdapter myMouse = new MyMouseAdapter();
- GLWindow glWindow = null;
+ Window window = null;
float aspect = 1.0f;
boolean doRotate = true;
boolean isInitialized = false;
+ boolean isFBOSlave = false;
public RedSquareES2(int swapInterval) {
this.swapInterval = swapInterval;
@@ -65,6 +61,7 @@ public class RedSquareES2 implements GLEventListener {
this.swapInterval = 1;
}
+ public void setIsFBOSlave(boolean v) { isFBOSlave = v; }
public void setAspect(float aspect) { this.aspect = aspect; }
public void setDoRotation(boolean rotate) { this.doRotate = rotate; }
@@ -129,14 +126,9 @@ public class RedSquareES2 implements GLEventListener {
colors.enableBuffer(gl, false);
// OpenGL Render Settings
- gl.glClearColor(0, 0, 0, 0);
gl.glEnable(GL2ES2.GL_DEPTH_TEST);
st.useProgram(gl, false);
- if (glad instanceof GLWindow) {
- glWindow = (GLWindow) glad;
- glWindow.addMouseListener(myMouse);
- }
t0 = System.currentTimeMillis();
System.err.println(Thread.currentThread()+" RedSquareES2.init FIN");
}
@@ -145,6 +137,7 @@ public class RedSquareES2 implements GLEventListener {
long t1 = System.currentTimeMillis();
GL2ES2 gl = glad.getGL().getGL2ES2();
+ gl.glClearColor(0, 0, 0, 0);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
st.useProgram(gl, true);
// One rotation every four seconds
@@ -171,7 +164,9 @@ public class RedSquareES2 implements GLEventListener {
System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval);
GL2ES2 gl = glad.getGL().getGL2ES2();
- gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ }
st.useProgram(gl, true);
// Set location in front of camera
@@ -192,40 +187,11 @@ public class RedSquareES2 implements GLEventListener {
}
isInitialized = false;
System.err.println(Thread.currentThread()+" RedSquareES2.dispose ... ");
- if (null != glWindow) {
- glWindow.removeMouseListener(myMouse);
- glWindow = null;
- }
GL2ES2 gl = glad.getGL().getGL2ES2();
st.destroy(gl);
st = null;
pmvMatrix.destroy();
pmvMatrix = null;
System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN");
- }
-
- class MyMouseAdapter extends MouseAdapter {
- public void mouseClicked(MouseEvent e) {
- System.err.println(e);
- if(null != glWindow && e.getSource() == glWindow.getDelegatedWindow()) {
- if(e.getX() < glWindow.getWidth()/2) {
- glWindow.setFullscreen(!glWindow.isFullscreen());
- System.err.println("setFullscreen: "+glWindow.isFullscreen());
- } else {
- glWindow.invoke(false, new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
- gl.setSwapInterval(gl.getSwapInterval()<=0?1:0);
- System.err.println("setSwapInterval: "+gl.getSwapInterval());
- final GLAnimatorControl a = drawable.getAnimator();
- if( null != a ) {
- a.resetFPSCounter();
- }
- return true;
- }
- });
- }
- }
- }
- }
+ }
}
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 b04bd07c1..9217e2b53 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
@@ -265,11 +265,12 @@ public class TextureSequenceCubeES2 implements GLEventListener {
st.useProgram(gl, false);
- if (drawable instanceof Window) {
- Window window = (Window) drawable;
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.addMouseListener(mouseAction);
- } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) {
- java.awt.Component comp = (java.awt.Component) drawable;
+ } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) upstreamWidget;
new com.jogamp.newt.event.awt.AWTMouseAdapter(mouseAction).addTo(comp);
}
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 0b83aacd8..7f2713354 100755
--- 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
@@ -163,8 +163,9 @@ public class MovieCube implements GLEventListener, GLMediaEventListener {
mPlayer.start();
boolean added;
- if (drawable instanceof Window) {
- Window window = (Window) drawable;
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.addKeyListener(keyAction);
added = true;
} else { added = false; }
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 8210065ab..e17c9e88b 100755
--- 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
@@ -400,8 +400,9 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener {
startTime = System.currentTimeMillis();
- if (drawable instanceof Window) {
- Window window = (Window) drawable;
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.addMouseListener(mouseAction);
winWidth = window.getWidth();
winHeight = window.getHeight();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
index 04563d62e..fab5bf99b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
@@ -37,6 +37,8 @@ import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.opengl.GLWindow;
@@ -220,6 +222,12 @@ public class TestGearsES2NEWT extends UITestCase {
}
}
});
+ glWindow.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ System.err.println("setFullscreen: "+glWindow.isFullscreen());
+ }
+ });
animator.start();
// glWindow.setSkipContextReleaseThread(animator.getThread());
@@ -258,7 +266,6 @@ public class TestGearsES2NEWT extends UITestCase {
public static void main(String args[]) throws IOException {
int x=0, y=0, w=640, h=480;
- boolean useSize = false;
boolean usePos = false;
for(int i=0; i<args.length; i++) {
@@ -291,11 +298,9 @@ public class TestGearsES2NEWT extends UITestCase {
} else if(args[i].equals("-width")) {
i++;
w = MiscUtils.atoi(args[i], w);
- useSize = true;
} else if(args[i].equals("-height")) {
i++;
h = MiscUtils.atoi(args[i], h);
- useSize = true;
} else if(args[i].equals("-x")) {
i++;
x = MiscUtils.atoi(args[i], x);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java
index 74d52c352..ff231ef91 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java
@@ -54,6 +54,7 @@ public class TestRedSquareES2NEWT extends UITestCase {
static GLProfile.ShutdownType loop_shutdown = null;
static boolean vsync = false;
static boolean forceES2 = false;
+ static boolean doRotate = true;
@BeforeClass
public static void initClass() {
@@ -72,7 +73,9 @@ public class TestRedSquareES2NEWT extends UITestCase {
glWindow.setTitle("Gears NEWT Test");
glWindow.setSize(width, height);
- glWindow.addGLEventListener(new RedSquareES2(vsync ? 1 : -1));
+ final RedSquareES2 demo = new RedSquareES2(vsync ? 1 : -1);
+ demo.setDoRotation(doRotate);
+ glWindow.addGLEventListener(demo);
Animator animator = new Animator(glWindow);
QuitAdapter quitAdapter = new QuitAdapter();
@@ -143,6 +146,8 @@ public class TestRedSquareES2NEWT extends UITestCase {
} catch (Exception ex) { ex.printStackTrace(); }
} else if(args[i].equals("-es2")) {
forceES2 = true;
+ } else if(args[i].equals("-norotate")) {
+ doRotate = false;
} else if(args[i].equals("-loops")) {
i++;
loops = MiscUtils.atoi(args[i], 1);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp
new file mode 100644
index 000000000..a26dc9737
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp
@@ -0,0 +1,10 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+varying vec4 frontColor;
+
+void main (void)
+{
+ gl_FragColor = frontColor;
+ // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp
new file mode 100644
index 000000000..097a73e4c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp
@@ -0,0 +1,14 @@
+//Copyright 2012 JogAmp Community. All rights reserved.
+
+
+uniform mat4 mgl_PMVMatrix[2]; // P, Mv
+attribute vec4 mgl_Vertex;
+attribute vec4 mgl_Color;
+
+varying vec4 frontColor;
+
+void main(void)
+{
+ frontColor = mgl_Color;
+ gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp
new file mode 100644
index 000000000..d222606cd
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp
@@ -0,0 +1,20 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+varying vec2 mgl_texCoord;
+varying vec4 frontColor;
+
+uniform sampler2D mgl_Texture0;
+uniform sampler2D mgl_Texture1;
+
+const vec4 One = vec4(1.0, 1.0, 1.0, 1.0);
+
+void main (void)
+{
+ vec4 texColor0 = texture2D(mgl_Texture0, mgl_texCoord);
+ vec4 texColor1 = texture2D(mgl_Texture1, mgl_texCoord);
+
+ // gl_FragColor = ( ( texColor0 + texColor1 ) / 2.0 ) * frontColor;
+ // gl_FragColor = mix(texColor0, texColor1, One/2.0) * frontColor;
+ gl_FragColor = min(One, mix(texColor0, texColor1, One/2.0) * 1.6) * frontColor;
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
index c09119a32..b3166b03b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
@@ -124,14 +124,15 @@ public class Gears implements GLEventListener {
gl.glEnable(GL2.GL_NORMALIZE);
- if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) {
- java.awt.Component comp = (java.awt.Component) drawable;
- new AWTMouseAdapter(gearsMouse).addTo(comp);
- new AWTKeyAdapter(gearsKeys).addTo(comp);
- } else if (drawable.getNativeSurface() instanceof Window) {
- Window window = (Window) drawable.getNativeSurface();
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.addMouseListener(gearsMouse);
window.addKeyListener(gearsKeys);
+ } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) upstreamWidget;
+ new AWTMouseAdapter(gearsMouse).addTo(comp);
+ new AWTKeyAdapter(gearsKeys).addTo(comp);
}
}
@@ -159,8 +160,9 @@ public class Gears implements GLEventListener {
public void dispose(GLAutoDrawable drawable) {
System.err.println("Gears: Dispose");
try {
- if (drawable.getNativeSurface() instanceof Window) {
- Window window = (Window) drawable.getNativeSurface();
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
window.removeMouseListener(gearsMouse);
window.removeKeyListener(gearsKeys);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWTBug450.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java
index e3f33e301..4f97feb4f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWTBug450.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java
@@ -31,6 +31,7 @@ import javax.media.opengl.*;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
import javax.media.opengl.awt.GLJPanel;
import javax.media.opengl.glu.gl2.GLUgl2;
@@ -39,7 +40,6 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
import java.awt.AWTException;
import java.awt.BorderLayout;
-import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
@@ -61,7 +61,7 @@ import org.junit.Test;
*
* @author Wade Walker (adapted from TestGearsGLJPanelAWT)
*/
-public class TestGearsGLJPanelAWTBug450 extends UITestCase {
+public class TestGLJPanelAWTBug450 extends UITestCase {
static GLProfile glp;
static int width, height;
static int r_x, r_y;
@@ -83,16 +83,10 @@ public class TestGearsGLJPanelAWTBug450 extends UITestCase {
public static void releaseClass() {
}
- protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) {
- GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false);
- if(screenshot.readPixels(drawable.getGL(), drawable, flip)) {
- screenshot.write(new File(filename));
- }
- }
-
protected void runTestGL(GLCapabilities caps)
throws AWTException, InterruptedException, InvocationTargetException
{
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
JFrame frame = new JFrame("Swing GLJPanel");
Assert.assertNotNull(frame);
@@ -123,7 +117,7 @@ public class TestGearsGLJPanelAWTBug450 extends UITestCase {
}
if(0 == f) {
System.err.println("BGR ("+r_x+"/"+r_y+"): "+byte0+", "+byte1+", "+byte2+" - OK "+(!failed));
- snapshot(drawable, true, false, getSimpleTestName(".")+".png");
+ snapshot(getSimpleTestName("."), f, null, gl, screenshot, TextureIO.PNG, null);
}
f++;
}
@@ -189,6 +183,6 @@ public class TestGearsGLJPanelAWTBug450 extends UITestCase {
} catch (Exception ex) { ex.printStackTrace(); }
}
}
- org.junit.runner.JUnitCore.main(TestGearsGLJPanelAWTBug450.class.getName());
+ org.junit.runner.JUnitCore.main(TestGLJPanelAWTBug450.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java
index 881399ddb..987dedc65 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java
@@ -47,7 +47,6 @@ import javax.media.opengl.GLUniformData;
import org.junit.Assert;
import org.junit.Test;
-import org.junit.BeforeClass;
/**
* Testing different vertex attribute (VA) data sets on one shader
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java
index 6421c2405..91dcfc3c3 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java
@@ -47,7 +47,6 @@ import javax.media.opengl.GLUniformData;
import org.junit.Assert;
import org.junit.Test;
-import org.junit.BeforeClass;
/**
* Testing different vertex attribute (VA) data sets on one shader
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java
index e3ca25ae6..4ef7b2719 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java
@@ -85,9 +85,7 @@ public class ReadBufferBase implements GLEventListener {
}
public void display(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
-
- readBufferUtil.readPixels(gl, drawable, false);
+ readBufferUtil.readPixels(drawable.getGL(), false);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java
index b046df6af..974e32289 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java
@@ -64,7 +64,7 @@ public class Surface2File implements SurfaceUpdatedListener {
GL gl = ctx.getGL();
// FIXME glFinish() is an expensive paranoia sync, should not be necessary due to spec
gl.glFinish();
- if(readBufferUtil.readPixels(gl, drawable, false)) {
+ if(readBufferUtil.readPixels(gl, false)) {
gl.glFinish();
try {
surface2File();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
index 2121205e2..6a27e6f27 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
@@ -28,20 +28,16 @@
package com.jogamp.opengl.test.junit.jogl.swt;
-import javax.media.opengl.GL2ES1;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
-import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.junit.Assert;
@@ -52,22 +48,29 @@ import org.junit.After;
import org.junit.Test;
import com.jogamp.nativewindow.swt.SWTAccessor;
-import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.ProxySurface;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLDrawable;
-import org.eclipse.swt.widgets.Canvas;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
/**
- * Tests that a basic SWT app can open without crashing under different GL profiles.
+ * Tests that a basic SWT app can open without crashing under different GL profiles
+ * _and_ custom GLCapabilities.
* <p>
- * Uses JOGL's SWTAccessor only.
+ * Uses JOGL's NewtCanvasSWT, which allows to be a native container of a NEWT Window.<br/>
+ * This method allows utilizing custom GLCapability settings,
+ * independent from the already instantiated SWT visual.
+ * </p>
+ * <p>
+ * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
+ * SWT running on Mac OSX, i.e. to enforce UI action on the main thread.
* </p>
- * @author Wade Walker, et.al.
*/
-public class TestSWTAccessor02GLn extends UITestCase {
+public class TestNewtCanvasSWTGLn extends UITestCase {
static int duration = 250;
@@ -95,7 +98,7 @@ public class TestSWTAccessor02GLn extends UITestCase {
composite = new Composite( shell, SWT.NONE );
composite.setLayout( new FillLayout() );
Assert.assertNotNull( composite );
- }});
+ }});
}
@After
@@ -119,95 +122,58 @@ public class TestSWTAccessor02GLn extends UITestCase {
shell = null;
composite = null;
}
-
- class CanvasCStr implements Runnable {
- Canvas canvas;
-
- public void run() {
- canvas = new Canvas( composite, SWT.NO_BACKGROUND);
- }
- }
-
- protected void runTestAGL( GLProfile glprofile ) throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glprofile);
- GLDrawableFactory factory = GLDrawableFactory.getFactory(glprofile);
-
- // need SWT.NO_BACKGROUND to prevent SWT from clearing the window
- // at the wrong times (we use glClear for this instead)
- CanvasCStr canvasCstr = new CanvasCStr();
+
+ protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo,
+ boolean postAttach, boolean useAnimator ) throws InterruptedException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
- SWTAccessor.invoke(true, canvasCstr);
- final Canvas canvas = canvasCstr.canvas;
- Assert.assertNotNull( canvas );
+ final GLWindow glWindow1 = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow1);
+ Assert.assertEquals(false, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertNull(glWindow1.getParent());
+ glWindow1.addGLEventListener(demo);
+ glWindow1.addGLEventListener(new GLEventListener() {
+ int displayCount = 0;
+ public void init(final GLAutoDrawable drawable) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ public void display(final GLAutoDrawable drawable) {
+ if(displayCount < 3) {
+ snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ }
+ public void dispose(final GLAutoDrawable drawable) { }
+ });
- SWTAccessor.setRealized(canvas, true);
- AbstractGraphicsDevice device = SWTAccessor.getDevice(canvas);
- long nativeWindowHandle = SWTAccessor.getWindowHandle(canvas);
- System.err.println("*** device: " + device);
- System.err.println("*** window handle: 0x" + Long.toHexString(nativeWindowHandle));
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, postAttach ? null : glWindow1 );
+ Assert.assertNotNull( canvas1 );
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( 640, 480 );
+ shell.open();
+ }
+ });
- ProxySurface proxySurface = factory.createProxySurface(device, nativeWindowHandle, caps, null);
- Assert.assertNotNull( proxySurface );
- proxySurface.surfaceSizeChanged( 640, 480 );
- System.err.println("*** ProxySurface: " + proxySurface);
- final GLDrawable drawable = factory.createGLDrawable(proxySurface);
- Assert.assertNotNull( drawable );
- drawable.setRealized(true);
- System.err.println("*** Drawable: " + drawable);
- Assert.assertTrue( drawable.isRealized() );
- final GLContext glcontext = drawable.createContext(null);
- // trigger native creation ..
- if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) {
- glcontext.release();
+ if(postAttach) {
+ canvas1.setNEWTChild(glWindow1);
}
- final boolean[] sizeMissing = new boolean[] { false };
+ // canvas1.update();
- // fix the viewport when the user resizes the window
- canvas.addListener( SWT.Resize, new Listener() {
- public void handleEvent( Event event ) {
- Rectangle rectangle = canvas.getClientArea();
- boolean glok=false;
- if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) {
- glok=true;
- GL2ES1 gl = glcontext.getGL().getGL2ES1();
- OneTriangle.setup( gl, rectangle.width, rectangle.height );
- glcontext.release();
- } else {
- sizeMissing[0] = true;
- }
- System.err.println("resize: glok " + glok);
- }
- });
-
- // draw the triangle when the OS tells us that any part of the window needs drawing
- canvas.addPaintListener( new PaintListener() {
- public void paintControl( PaintEvent paintevent ) {
- Rectangle rectangle = canvas.getClientArea();
- boolean glok=false;
- if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) {
- glok=true;
- GL2ES1 gl = glcontext.getGL().getGL2ES1();
- if(sizeMissing[0]) {
- OneTriangle.setup( gl, rectangle.width, rectangle.height);
- sizeMissing[0] = false;
- }
- OneTriangle.render( gl, rectangle.width, rectangle.height);
- drawable.swapBuffers();
- glcontext.release();
- }
- System.err.println("paint: glok " + glok);
- }
- });
+ Animator anim;
+ if(useAnimator) {
+ anim = new Animator(glWindow1);
+ anim.start();
+ } else {
+ anim = null;
+ }
- shell.setText( getClass().getName() );
- shell.setSize( 640, 480 );
- shell.open();
-
long lStartTime = System.currentTimeMillis();
long lEndTime = lStartTime + duration;
try {
- while( (System.currentTimeMillis() < lEndTime) && !canvas.isDisposed() ) {
+ while( (System.currentTimeMillis() < lEndTime) && !canvas1.isDisposed() ) {
if( !display.readAndDispatch() ) {
// blocks on linux .. display.sleep();
Thread.sleep(10);
@@ -217,15 +183,34 @@ public class TestSWTAccessor02GLn extends UITestCase {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
- glcontext.destroy();
- drawable.setRealized(false);
- canvas.dispose();
+ if(null != anim) {
+ anim.stop();
+ }
+
+ canvas1.dispose();
+ }
+
+ @Test
+ public void preAttach_WithAnimator() throws InterruptedException {
+ runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, true /* animator */);
+ }
+
+ @Test
+ public void preAttach_NoAnimator() throws InterruptedException {
+ runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, false /* animator */);
}
@Test
- public void test() throws InterruptedException {
- GLProfile glprofile = GLProfile.getGL2ES1();
- runTestAGL( glprofile );
+ public void postAttach_WithAnimator() throws InterruptedException {
+ runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), true /* postAttach */, true /* animator */);
+ }
+
+ @Test
+ public void test_MultisampleAndAlpha() throws InterruptedException {
+ GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(2);
+ runTestAGL( caps, new MultisampleDemoES2(true), false /* postAttach */, false /* animator */);
}
static int atoi(String a) {
@@ -243,6 +228,6 @@ public class TestSWTAccessor02GLn extends UITestCase {
}
}
System.out.println("durationPerTest: "+duration);
- org.junit.runner.JUnitCore.main(TestSWTAccessor02GLn.class.getName());
+ org.junit.runner.JUnitCore.main(TestNewtCanvasSWTGLn.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
index 5e3d4dd8e..4ca1dae0d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
@@ -47,11 +47,12 @@ import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Test;
-import com.jogamp.common.os.Platform;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.swt.GLCanvas;
-import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
/**
* Tests that a basic SWT app can open without crashing under different GL profiles.
@@ -59,6 +60,9 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
* Uses JOGL's new SWT GLCanvas.
* </p>
* <p>
+ * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used.
+ * </p>
+ * <p>
* Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
* SWT running on Mac OSX, i.e. to enforce UI action on the main thread.
* </p>
@@ -117,34 +121,32 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
composite = null;
}
- protected void runTestAGL( GLProfile glprofile ) throws InterruptedException {
- // need SWT.NO_BACKGROUND to prevent SWT from clearing the window
- // at the wrong times (we use glClear for this instead)
- final GLCapabilitiesImmutable caps = new GLCapabilities( glprofile );
+ protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo ) throws InterruptedException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
- final GLCanvas canvas = new GLCanvas( composite, SWT.NO_BACKGROUND, caps, null, null);
+ final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null, null);
Assert.assertNotNull( canvas );
+ canvas.addGLEventListener( demo );
canvas.addGLEventListener(new GLEventListener() {
- public void init(final GLAutoDrawable drawable) {
- System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - init()");
- }
- public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
- System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - reshape()");
- OneTriangle.setup( drawable.getGL().getGL2(), width, height );
- }
+ int displayCount = 0;
+ public void init(final GLAutoDrawable drawable) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
public void display(final GLAutoDrawable drawable) {
- OneTriangle.render( drawable.getGL().getGL2(), drawable.getWidth(), drawable.getHeight());
+ if(displayCount < 3) {
+ snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
}
- public void dispose(final GLAutoDrawable drawable) {
- System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - dispose()");
- }
- });
+ public void dispose(final GLAutoDrawable drawable) { }
+ });
- shell.setText( getClass().getName() );
- shell.setSize( 640, 480 );
- shell.open();
-
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( 640, 480 );
+ shell.open();
+ } } );
+
long lStartTime = System.currentTimeMillis();
long lEndTime = lStartTime + duration;
try {
@@ -158,13 +160,15 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
- canvas.dispose();
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ canvas.dispose();
+ } } );
}
@Test
public void test() throws InterruptedException {
- GLProfile glprofile = GLProfile.getGL2ES1();
- runTestAGL( glprofile );
+ runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() );
}
static int atoi(String a) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java
index f79a73040..6cee319ba 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java
@@ -30,7 +30,6 @@ package com.jogamp.opengl.test.junit.jogl.util.texture;
import java.awt.Dimension;
import java.awt.Frame;
-import java.io.File;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -42,6 +41,7 @@ import jogamp.nativewindow.jawt.JAWTUtil;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -68,14 +68,10 @@ public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase {
height = 256;
}
- protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) {
- GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false);
- if(screenshot.readPixels(drawable.getGL(), drawable, flip)) {
- screenshot.write(new File(filename));
- }
- }
-
protected void testWritePNG_Impl(boolean offscreenLayer) throws InterruptedException {
+ final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false);
+ final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false);
+
if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) {
System.err.println("onscreen layer n/a");
return;
@@ -96,12 +92,13 @@ public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase {
glc.setSize(width, height);
glc.addGLEventListener(new GearsES2(1));
glc.addGLEventListener(new GLEventListener() {
+ int f = 0;
public void init(GLAutoDrawable drawable) {}
public void dispose(GLAutoDrawable drawable) {}
public void display(GLAutoDrawable drawable) {
- final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_";
- snapshot(drawable, true, false, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png");
- snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png");
+ snapshot(getSimpleTestName("."), f, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null);
+ snapshot(getSimpleTestName("."), f, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null);
+ f++;
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
});
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java
index b5b12035d..5681df0ad 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java
@@ -28,8 +28,6 @@
package com.jogamp.opengl.test.junit.jogl.util.texture;
-import java.io.File;
-
import com.jogamp.newt.opengl.GLWindow;
import javax.media.opengl.GLAutoDrawable;
@@ -37,6 +35,7 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
@@ -62,32 +61,26 @@ public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase {
height = 256;
}
- protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) {
- GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false);
- if(screenshot.readPixels(drawable.getGL(), drawable, flip)) {
- screenshot.write(new File(filename));
- }
- }
-
@Test
public void testOnscreenWritePNG_TGA_PAM() throws InterruptedException {
+ final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false);
+ final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false);
GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Shared Gears NEWT Test");
glWindow.setSize(width, height);
glWindow.addGLEventListener(new GearsES2(1));
glWindow.addGLEventListener(new GLEventListener() {
+ int f = 0;
public void init(GLAutoDrawable drawable) {}
public void dispose(GLAutoDrawable drawable) {}
public void display(GLAutoDrawable drawable) {
- final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_";
- // snapshot(drawable, false, true, getSimpleTestName(".")+"-rgb_-"+drawable.getGLProfile().getName()+".ppm");
- snapshot(drawable, true, false, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png");
- snapshot(drawable, true, false, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".tga");
- snapshot(drawable, true, true, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".pam");
- snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png");
- snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".tga");
- snapshot(drawable, false, true, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".pam");
+ snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null);
+ snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null);
+ snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGBA, TextureIO.TGA, null);
+ snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGB, TextureIO.TGA, null);
+ snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGBA, TextureIO.PAM, null);
+ snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGB, TextureIO.PAM, null);
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
});
@@ -98,18 +91,21 @@ public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase {
@Test
public void testOffscreenWritePNG() throws InterruptedException {
+ final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false);
+ final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false);
final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false);
GLWindow glWindow = GLWindow.create(caps2);
Assert.assertNotNull(glWindow);
glWindow.setSize(width, height);
glWindow.addGLEventListener(new GearsES2(1));
glWindow.addGLEventListener(new GLEventListener() {
+ int f = 0;
public void init(GLAutoDrawable drawable) {}
public void dispose(GLAutoDrawable drawable) {}
public void display(GLAutoDrawable drawable) {
- final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_";
- snapshot(drawable, true, false, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png");
- snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png");
+ snapshot(getSimpleTestName("."), f, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null);
+ snapshot(getSimpleTestName("."), f, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null);
+ f++;
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
});
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java
index 10dd4ea70..43641fe6d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java
@@ -30,9 +30,6 @@ package com.jogamp.opengl.test.junit.jogl.util.texture;
import java.awt.Dimension;
import java.awt.Frame;
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -45,6 +42,7 @@ import jogamp.nativewindow.jawt.JAWTUtil;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -71,20 +69,6 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
height = 64;
}
- protected void snapshot(GLAutoDrawable drawable, GLReadBufferUtil screenshot, int i) {
- final StringWriter filename = new StringWriter();
- {
- final PrintWriter pw = new PrintWriter(filename);
- final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_";
- pw.printf("%s-F_rgba-I_%s-%s-n%03d-%04dx%04d.png",
- getSimpleTestName("."), pfmt, drawable.getGLProfile().getName(), i, drawable.getWidth(), drawable.getHeight());
- }
- drawable.getGL().glFinish(); // poor mans sync ..
- if(screenshot.readPixels(drawable.getGL(), drawable, false)) {
- screenshot.write(new File(filename.toString()));
- }
- }
-
protected void testWritePNGWithResizeImpl(boolean offscreenLayer) throws InterruptedException {
if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) {
System.err.println("onscreen layer n/a");
@@ -127,7 +111,7 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
if(snap) {
System.err.println("XXX: ["+fw_old+", "+dw_old+"], "+fw+"x"+fh+", "+dw+"x"+dh+", sz_changed "+sz_changed+", snap "+snap);
c=0;
- snapshot(drawable, screenshot, i++);
+ snapshot(getSimpleTestName("."), i++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
dw_old = dw;
fw_old = fw;
Threading.invoke(true, new Runnable() {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java
index ed0791f7c..d1ffa84cf 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java
@@ -28,10 +28,6 @@
package com.jogamp.opengl.test.junit.jogl.util.texture;
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
import com.jogamp.newt.opengl.GLWindow;
import javax.media.opengl.GLAutoDrawable;
@@ -41,6 +37,7 @@ import javax.media.opengl.GLProfile;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
@@ -66,19 +63,6 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase {
height = 64;
}
- protected void snapshot(GLAutoDrawable drawable, GLReadBufferUtil screenshot, int i) {
- final StringWriter filename = new StringWriter();
- {
- final PrintWriter pw = new PrintWriter(filename);
- final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_";
- pw.printf("%s-F_rgba-I_%s-%s-n%03d-%04dx%04d.png",
- getSimpleTestName("."), pfmt, drawable.getGLProfile().getName(), i, drawable.getWidth(), drawable.getHeight());
- }
- if(screenshot.readPixels(drawable.getGL(), drawable, false)) {
- screenshot.write(new File(filename.toString()));
- }
- }
-
private void testWritePNGWithResizeImpl(boolean offscreen) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
final GLCapabilities caps2 = offscreen ? WindowUtilNEWT.fixCaps(caps, false, true, false) : caps;
@@ -110,7 +94,7 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase {
if(snap) {
System.err.println("XXX: ["+dw_old+"], "+dw+"x"+dh+", sz_changed "+sz_changed+", snap "+snap);
c=0;
- snapshot(drawable, screenshot, i++);
+ snapshot(getSimpleTestName("."), i++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
dw_old = dw;
new Thread() {
@Override
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java
index 068732696..0d4f2b01e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java
@@ -52,7 +52,6 @@ import com.jogamp.opengl.util.GLReadBufferUtil;
import java.awt.Dimension;
import java.awt.Frame;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
@@ -96,16 +95,10 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
testTextureStream = null;
}
- protected void snapshot(GLAutoDrawable drawable, String filename) {
- GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
- if(screenshot.readPixels(drawable.getGL(), drawable, false)) {
- screenshot.write(new File(filename));
- }
- }
-
public void testImpl(boolean useFFP, final InputStream istream, final boolean useAWTIIOP)
throws InterruptedException, IOException
{
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
GLProfile glp;
if(useFFP && GLProfile.isAvailable(GLProfile.GL2GL3)) {
glp = GLProfile.getGL2GL3();
@@ -137,7 +130,7 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
// the bug submitter was doing it
final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData ) ;
glc.addGLEventListener(gle);
- glc.addGLEventListener(new GLEventListener() {
+ glc.addGLEventListener(new GLEventListener() {
boolean shot = false;
@Override public void init(GLAutoDrawable drawable) {}
@@ -147,7 +140,7 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
// 1 snapshot
if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
shot = true;
- snapshot(drawable, getSimpleTestName(".")+".png");
+ snapshot(getSimpleTestName("."), 0, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java
index d973dea2d..b4faafbe7 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java
@@ -48,7 +48,6 @@ import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
@@ -80,14 +79,8 @@ public class TestPNGTextureFromFileNEWT extends UITestCase {
testTextureStream = null;
}
- protected void snapshot(GLAutoDrawable drawable, String filename) {
- GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
- if(screenshot.readPixels(drawable.getGL(), drawable, false)) {
- screenshot.write(new File(filename));
- }
- }
-
public void testImpl(boolean useFFP, final InputStream istream) throws InterruptedException, IOException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
GLProfile glp;
if(useFFP && GLProfile.isAvailable(GLProfile.GL2GL3)) {
glp = GLProfile.getGL2GL3();
@@ -119,7 +112,7 @@ public class TestPNGTextureFromFileNEWT extends UITestCase {
// 1 snapshot
if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
shot = true;
- snapshot(drawable, getSimpleTestName(".")+".png");
+ snapshot(getSimpleTestName("."), 0, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java
new file mode 100644
index 000000000..11aef7c24
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java
@@ -0,0 +1,210 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.parenting;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Simple visibility test ..
+ */
+public class TestParenting01aSWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 800;
+ static GLCapabilities glCaps;
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite1 = null;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite1 = new Composite( shell, SWT.NONE );
+ composite1.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite1 );
+ }});
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite1 );
+ try {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ composite1.dispose();
+ shell.dispose();
+ display.dispose();
+ }});
+ }
+ catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell = null;
+ composite1 = null;
+ }
+
+ @Test
+ public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
+
+ GLWindow glWindow1 = GLWindow.create(glCaps);
+ Assert.assertNotNull(glWindow1);
+ Assert.assertEquals(false, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertNull(glWindow1.getParent());
+ glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
+ GLEventListener demo1 = new RedSquareES2();
+ setDemoFields(demo1, glWindow1, false);
+ glWindow1.addGLEventListener(demo1);
+
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 );
+ Assert.assertNotNull(canvas1);
+ Assert.assertEquals(false, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertNull(glWindow1.getParent());
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( 640, 480 );
+ shell.open();
+ }
+ });
+
+ // visible test
+ Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
+
+ for(int i=0; i*10<durationPerTest; i++) {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ canvas1.setVisible(false);
+ }
+ });
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ canvas1.setVisible(true);
+ }
+ });
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+
+ canvas1.dispose();
+
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ }
+
+ public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ Assert.assertNotNull(demo);
+ Assert.assertNotNull(glWindow);
+ Window window = glWindow.getDelegatedWindow();
+ if(debug) {
+ MiscUtils.setFieldIfExists(demo, "glDebug", true);
+ MiscUtils.setFieldIfExists(demo, "glTrace", true);
+ }
+ if(!MiscUtils.setFieldIfExists(demo, "window", window)) {
+ MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
+ }
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ String tstname = TestParenting01aSWT.class.getName();
+ org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+ tstname,
+ "filtertrace=true",
+ "haltOnError=false",
+ "haltOnFailure=false",
+ "showoutput=true",
+ "outputtoformatters=true",
+ "logfailedtests=true",
+ "logtestlistenerevents=true",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
new file mode 100644
index 000000000..09b6d048c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
@@ -0,0 +1,239 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.parenting;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Frame;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.newt.Window;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Using {@link NewtCanvasAWT#setNEWTChild(Window)} for reparenting, i.e. NEWT/AWT hopping
+ */
+public class TestParenting04AWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 800;
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 400;
+ height = 400;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @Test
+ public void winHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException {
+ // Will produce some artifacts .. resizing etc
+ winHopFrame2Frame(false);
+ }
+
+ @Test
+ public void winHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException {
+ // Note: detaching first setNEWTChild(null) is much cleaner visually
+ winHopFrame2Frame(true);
+ }
+
+ protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ GLEventListener demo1 = new RedSquareES2();
+ setDemoFields(demo1, glWindow1, false);
+ glWindow1.addGLEventListener(demo1);
+ Animator anim1 = new Animator(glWindow1);
+
+ final GLWindow glWindow2 = GLWindow.create(glCaps);
+ GLEventListener demo2 = new GearsES2();
+ setDemoFields(demo2, glWindow2, false);
+ glWindow2.addGLEventListener(demo2);
+ Animator anim2 = new Animator(glWindow2);
+
+ final NewtCanvasAWT canvas1 = new NewtCanvasAWT(glWindow1);
+ final NewtCanvasAWT canvas2 = new NewtCanvasAWT(glWindow2);
+
+ final Frame frame1 = new Frame("AWT Parent Frame");
+ frame1.setLayout(new BorderLayout());
+ frame1.add(new Button("North"), BorderLayout.NORTH);
+ frame1.add(new Button("South"), BorderLayout.SOUTH);
+ frame1.add(new Button("East"), BorderLayout.EAST);
+ frame1.add(new Button("West"), BorderLayout.WEST);
+ frame1.setSize(width, height);
+ frame1.setLocation(0, 0);
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ frame1.validate();
+ }
+ });
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.add(canvas1, BorderLayout.CENTER);
+ frame1.validate();
+ }
+ });
+ Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
+
+ final Frame frame2 = new Frame("AWT Parent Frame");
+ frame2.setLayout(new BorderLayout());
+ frame2.add(new Button("North"), BorderLayout.NORTH);
+ frame2.add(new Button("South"), BorderLayout.SOUTH);
+ frame2.add(new Button("East"), BorderLayout.EAST);
+ frame2.add(new Button("West"), BorderLayout.WEST);
+ frame2.setSize(width, height);
+ frame2.setLocation(width+50, 0);
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame2.setVisible(true);
+ frame2.validate();
+ }
+ });
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame2.add(canvas2, BorderLayout.CENTER);
+ frame2.validate();
+ }
+ });
+ Assert.assertEquals(canvas2.getNativeWindow(),glWindow2.getParent());
+
+ anim1.start();
+ anim2.start();
+
+ int state;
+ for(state=0; state<3; state++) {
+ Thread.sleep(durationPerTest);
+ switch(state) {
+ case 0:
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ // 1 -> 2
+ if(detachFirst) {
+ canvas1.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
+ } else {
+ canvas2.setNEWTChild(null); // free g2 of w2
+ }
+ canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1
+ canvas2.setNEWTChild(glWindow1); // put g1 -> w2
+ frame1.validate();
+ frame2.validate();
+ }
+ });
+ break;
+ case 1:
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ // 2 -> 1
+ if(detachFirst) {
+ canvas1.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
+ } else {
+ canvas2.setNEWTChild(null);
+ }
+ canvas1.setNEWTChild(glWindow1);
+ canvas2.setNEWTChild(glWindow2);
+ frame1.validate();
+ frame2.validate();
+ }
+ });
+ break;
+ }
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.dispose();
+ frame2.dispose();
+ } } );
+ glWindow1.destroy();
+ glWindow2.destroy();
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertEquals(false, glWindow2.isNativeValid());
+ }
+
+ public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ Assert.assertNotNull(demo);
+ Assert.assertNotNull(glWindow);
+ Window window = glWindow.getDelegatedWindow();
+ if(debug) {
+ MiscUtils.setFieldIfExists(demo, "glDebug", true);
+ MiscUtils.setFieldIfExists(demo, "glTrace", true);
+ }
+ if(!MiscUtils.setFieldIfExists(demo, "window", window)) {
+ MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
+ }
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ String tstname = TestParenting04AWT.class.getName();
+ org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+ tstname,
+ "filtertrace=true",
+ "haltOnError=false",
+ "haltOnFailure=false",
+ "showoutput=true",
+ "outputtoformatters=true",
+ "logfailedtests=true",
+ "logtestlistenerevents=true",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java
new file mode 100644
index 000000000..14a36c573
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java
@@ -0,0 +1,264 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.parenting;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Using {@link NewtCanvasSWT#setNEWTChild(Window)} for reparenting, i.e. NEWT/AWT hopping
+ */
+public class TestParenting04SWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 800;
+ static GLCapabilities glCaps;
+
+ Display display = null;
+ Shell shell1 = null;
+ Shell shell2 = null;
+ Composite composite1 = null;
+ Composite composite2 = null;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 400;
+ height = 400;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+
+ shell1 = new Shell( display );
+ Assert.assertNotNull( shell1 );
+ shell1.setLayout( new FillLayout() );
+ composite1 = new Composite( shell1, SWT.NONE );
+ composite1.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite1 );
+
+ shell2 = new Shell( display );
+ Assert.assertNotNull( shell2 );
+ shell2.setLayout( new FillLayout() );
+ composite2 = new Composite( shell2, SWT.NONE );
+ composite2.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite2 );
+ }});
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell1 );
+ Assert.assertNotNull( shell2 );
+ Assert.assertNotNull( composite1 );
+ Assert.assertNotNull( composite2 );
+ try {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ composite1.dispose();
+ composite2.dispose();
+ shell1.dispose();
+ shell2.dispose();
+ display.dispose();
+ }});
+ }
+ catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell1 = null;
+ shell2 = null;
+ composite1 = null;
+ composite2 = null;
+ }
+
+ @Test
+ public void winHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException {
+ // Will produce some artifacts .. resizing etc
+ winHopFrame2Frame(false);
+ }
+
+ @Test
+ public void winHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException {
+ // Note: detaching first setNEWTChild(null) is much cleaner visually
+ winHopFrame2Frame(true);
+ }
+
+ protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ GLEventListener demo1 = new RedSquareES2();
+ setDemoFields(demo1, glWindow1, false);
+ glWindow1.addGLEventListener(demo1);
+ Animator anim1 = new Animator(glWindow1);
+
+ final GLWindow glWindow2 = GLWindow.create(glCaps);
+ GLEventListener demo2 = new GearsES2();
+ setDemoFields(demo2, glWindow2, false);
+ glWindow2.addGLEventListener(demo2);
+ Animator anim2 = new Animator(glWindow2);
+
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 );
+ final NewtCanvasSWT canvas2 = NewtCanvasSWT.create( composite2, 0, glWindow2 );
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell1.setText( getSimpleTestName(".")+"-Win1" );
+ shell1.setSize( width, height);
+ shell1.setLocation(0, 0);
+ shell1.open();
+ shell2.setText( getSimpleTestName(".")+"-Win2" );
+ shell2.setSize( width, height);
+ shell2.setLocation(width + 50, 0);
+ shell2.open();
+ }
+ });
+ Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
+ Assert.assertEquals(canvas2.getNativeWindow(),glWindow2.getParent());
+
+ anim1.start();
+ anim2.start();
+
+ int state;
+ for(state=0; state<3; state++) {
+ for(int i=0; i*10<durationPerTest; i++) {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+ switch(state) {
+ case 0:
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ // 1 -> 2
+ if(detachFirst) {
+ canvas1.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
+ } else {
+ canvas2.setNEWTChild(null); // free g2 of w2
+ }
+ canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1
+ canvas2.setNEWTChild(glWindow1); // put g1 -> w2
+ } } );
+ break;
+ case 1:
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ // 2 -> 1
+ if(detachFirst) {
+ canvas1.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
+ } else {
+ canvas2.setNEWTChild(null);
+ }
+ canvas1.setNEWTChild(glWindow1);
+ canvas2.setNEWTChild(glWindow2);
+ } } );
+ break;
+ }
+ }
+
+ canvas1.dispose();
+ canvas2.dispose();
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertEquals(false, glWindow2.isNativeValid());
+ }
+
+ public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ Assert.assertNotNull(demo);
+ Assert.assertNotNull(glWindow);
+ Window window = glWindow.getDelegatedWindow();
+ if(debug) {
+ MiscUtils.setFieldIfExists(demo, "glDebug", true);
+ MiscUtils.setFieldIfExists(demo, "glTrace", true);
+ }
+ if(!MiscUtils.setFieldIfExists(demo, "window", window)) {
+ MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
+ }
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ String tstname = TestParenting04SWT.class.getName();
+ org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+ tstname,
+ "filtertrace=true",
+ "haltOnError=false",
+ "haltOnFailure=false",
+ "showoutput=true",
+ "outputtoformatters=true",
+ "logfailedtests=true",
+ "logtestlistenerevents=true",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java
index 57b8517a6..373c83fce 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java
@@ -69,7 +69,6 @@ public class TestTranslucentParentingAWT extends UITestCase {
public static void initClass() {
size = new Dimension(400,200);
glCaps = new GLCapabilities(null);
- glCaps.setAlphaBits(8);
glCaps.setBackgroundOpaque(false);
}
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 672675fab..c07d5b741 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
@@ -28,7 +28,17 @@
package com.jogamp.opengl.test.junit.util;
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawable;
+
import com.jogamp.common.util.locks.SingletonInstance;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
import org.junit.Assume;
import org.junit.Before;
@@ -108,6 +118,49 @@ public abstract class UITestCase {
}
static final String unsupportedTestMsg = "Test not supported on this platform.";
-
+
+ /**
+ * Takes a snapshot of the drawable's current framebuffer. Example filenames:
+ * <pre>
+ * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png
+ * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png
+ * </pre>
+ *
+ * @param simpleTestName will be used as the filename prefix
+ * @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.
+ * @param fileSuffix Optional file suffix without a <i>dot</i> defining the file type, i.e. <code>"png"</code>.
+ * 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.
+ */
+ public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
+ if(null == fileSuffix) {
+ fileSuffix = TextureIO.PNG;
+ }
+ final StringWriter filenameSW = new StringWriter();
+ {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_";
+ final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_";
+ final String aaext = caps.getSampleExtension();
+ final int samples = caps.getNumSamples() ;
+ postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
+ final PrintWriter pw = new PrintWriter(filenameSW);
+ pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s",
+ simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(),
+ drawable.getWidth(), drawable.getHeight(), fileSuffix);
+ }
+ final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString();
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename);
+ gl.glFinish(); // just make sure rendering finished ..
+ if(readBufferUtil.readPixels(gl, false)) {
+ readBufferUtil.write(new File(filename));
+ }
+ }
}